http_impl.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
  1. /* --- BEGIN COPYRIGHT BLOCK ---
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * --- END COPYRIGHT BLOCK --- */
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. /**
  13. * Implementation of a Simple HTTP Client
  14. */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include "nspr.h"
  18. #include "nss.h"
  19. #include "pk11func.h"
  20. #include "ssl.h"
  21. #include "prprf.h"
  22. #include "plstr.h"
  23. #include "slapi-plugin.h"
  24. #include "http_client.h"
  25. #include "secerr.h"
  26. #include "sslerr.h"
  27. #include "slap.h"
  28. #include "slapi-private.h"
  29. #include "slapi-plugin-compat4.h"
  30. #include <sys/stat.h>
  31. #ifdef __cplusplus
  32. extern "C" {
  33. #endif
  34. #ifdef BUILD_STANDALONE
  35. #define slapi_log_err(a, b, c, d) printf((c), (d))
  36. #define stricmp strcasecmp
  37. #endif
  38. #ifdef __cplusplus
  39. }
  40. #endif
  41. #define HTTP_PLUGIN_SUBSYSTEM "http-client-plugin" /* used for logging */
  42. #define HTTP_IMPL_SUCCESS 0
  43. #define HTTP_IMPL_FAILURE -1
  44. #define HTTP_REQ_TYPE_GET 1
  45. #define HTTP_REQ_TYPE_REDIRECT 2
  46. #define HTTP_REQ_TYPE_POST 3
  47. #define HTTP_GET "GET"
  48. #define HTTP_POST "POST"
  49. #define HTTP_PROTOCOL "HTTP/1.0"
  50. #define HTTP_CONTENT_LENGTH "Content-length:"
  51. #define HTTP_CONTENT_TYPE_URL_ENCODED "Content-type: application/x-www-form-urlencoded"
  52. #define HTTP_GET_STD_LEN 18
  53. #define HTTP_POST_STD_LEN 85
  54. #define HTTP_DEFAULT_BUFFER_SIZE 4096
  55. #define HTTP_RESPONSE_REDIRECT (retcode == 302 || retcode == 301)
  56. /**
  57. * Error strings used for logging error messages
  58. */
  59. #define HTTP_ERROR_BAD_URL " Badly formatted URL"
  60. #define HTTP_ERROR_NET_ADDR " NetAddr initialization failed"
  61. #define HTTP_ERROR_SOCKET_CREATE " Creation of socket failed"
  62. #define HTTP_ERROR_SSLSOCKET_CREATE " Creation of SSL socket failed"
  63. #define HTTP_ERROR_CONNECT_FAILED " Couldn't connect to remote host"
  64. #define HTTP_ERROR_SEND_REQ " Send request failed"
  65. #define HTTP_ERROR_BAD_RESPONSE " Invalid response from remote host"
  66. #define HTTP_PLUGIN_DN "cn=HTTP Client,cn=plugins,cn=config"
  67. #define CONFIG_DN "cn=config"
  68. #define ATTR_CONNECTION_TIME_OUT "nsHTTPConnectionTimeOut"
  69. #define ATTR_READ_TIME_OUT "nsHTTPReadTimeOut"
  70. #define ATTR_RETRY_COUNT "nsHTTPRetryCount"
  71. #define ATTR_DS_SECURITY "nsslapd-security"
  72. #define ATTR_INSTANCE_PATH "nsslapd-errorlog"
  73. /*static Slapi_ComponentId *plugin_id = NULL;*/
  74. typedef struct
  75. {
  76. int retryCount;
  77. int connectionTimeOut;
  78. int readTimeOut;
  79. int nssInitialized;
  80. char *DS_sslOn;
  81. } httpPluginConfig;
  82. httpPluginConfig *httpConfig;
  83. /**
  84. * Public functions
  85. */
  86. int http_impl_init(Slapi_ComponentId *plugin_id);
  87. int http_impl_get_text(char *url, char **data, int *bytesRead);
  88. int http_impl_get_binary(char *url, char **data, int *bytesRead);
  89. int http_impl_get_redirected_uri(char *url, char **data, int *bytesRead);
  90. int http_impl_post(char *url, httpheader **httpheaderArray, char *body, char **data, int *bytesRead);
  91. void http_impl_shutdown(void);
  92. /**
  93. * Http handling functions
  94. */
  95. static int doRequest(const char *url, httpheader **httpheaderArray, char *body, char **buf, int *bytesRead, int reqType);
  96. static int doRequestRetry(const char *url, httpheader **httpheaderArray, char *body, char **buf, int *bytesRead, int reqType);
  97. static void setTCPNoDelay(PRFileDesc *fd);
  98. static PRStatus sendGetReq(PRFileDesc *fd, const char *path);
  99. static PRStatus sendPostReq(PRFileDesc *fd, const char *path, httpheader **httpheaderArray, char *body);
  100. static PRStatus processResponse(PRFileDesc *fd, char **resBUF, int *bytesRead, int reqType);
  101. static PRStatus getChar(PRFileDesc *fd, char *buf);
  102. static PRInt32 http_read(PRFileDesc *fd, char *buf, int size);
  103. static PRStatus getBody(PRFileDesc *fd, char **buf, int *actualBytesRead);
  104. static PRBool isWhiteSpace(char ch);
  105. static PRStatus sendFullData(PRFileDesc *fd, char *buf, int timeOut);
  106. /**
  107. * Helper functions to parse URL
  108. */
  109. static PRStatus parseURI(const char *url, char **host, PRInt32 *port, char **path, int *sslOn);
  110. static void toLowerCase(char *str);
  111. static PRStatus parseAtPort(const char *url, PRInt32 *port, char **path);
  112. static PRStatus parseAtPath(const char *url, char **path);
  113. static PRInt32 getPort(const char *src);
  114. static PRBool isAsciiSpace(char aChar);
  115. static PRBool isAsciiDigit(char aChar);
  116. static char *isHttpReq(const char *url, int *sslOn);
  117. /*To get config from entry*/
  118. static int readConfigLDAPurl(Slapi_ComponentId *plugin_id, char *plugindn);
  119. static int parseHTTPConfigEntry(Slapi_Entry *e);
  120. static int parseConfigEntry(Slapi_Entry *e);
  121. /*SSL functions */
  122. PRFileDesc *setupSSLSocket(PRFileDesc *fd);
  123. /*SSL callback functions */
  124. SECStatus badCertHandler(void *arg, PRFileDesc *socket);
  125. SECStatus authCertificate(void *arg, PRFileDesc *socket, PRBool checksig, PRBool isServer);
  126. SECStatus getClientAuthData(void *arg, PRFileDesc *socket, struct CERTDistNamesStr *caNames, struct CERTCertificateStr **pRetCert, struct SECKEYPrivateKeyStr **pRetKey);
  127. SECStatus handshakeCallback(PRFileDesc *socket, void *arg);
  128. static int
  129. doRequestRetry(const char *url, httpheader **httpheaderArray, char *body, char **buf, int *bytesRead, int reqType)
  130. {
  131. int status = HTTP_IMPL_SUCCESS;
  132. int retrycnt = 0;
  133. int i = 1;
  134. retrycnt = httpConfig->retryCount;
  135. if (retrycnt == 0) {
  136. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequestRetry - Retry Count cannot be read. Setting to default value of 3\n");
  137. retrycnt = 3;
  138. }
  139. status = doRequest(url, httpheaderArray, body, buf, bytesRead, reqType);
  140. if (status != HTTP_IMPL_SUCCESS) {
  141. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequestRetry - Failed to perform http request \n");
  142. while (retrycnt > 0) {
  143. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequestRetry - Retrying http request %d.\n", i);
  144. status = doRequest(url, httpheaderArray, body, buf, bytesRead, reqType);
  145. if (status == HTTP_IMPL_SUCCESS) {
  146. break;
  147. }
  148. retrycnt--;
  149. i++;
  150. }
  151. if (status != HTTP_IMPL_SUCCESS) {
  152. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM, "doRequestRetry - Failed to perform http request after %d attempts.\n", i);
  153. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM, "doRequestRetry - Verify plugin URI configuration and contact Directory Administrator.\n");
  154. }
  155. }
  156. return status;
  157. }
  158. static int
  159. doRequest(const char *url, httpheader **httpheaderArray, char *body, char **buf, int *bytesRead, int reqType)
  160. {
  161. PRStatus status = PR_SUCCESS;
  162. char *host = NULL;
  163. char *path = NULL;
  164. PRFileDesc *fd = NULL;
  165. PRNetAddr addr;
  166. PRInt32 port;
  167. PRInt32 errcode = 0;
  168. PRInt32 http_connection_time_out = 0;
  169. PRInt32 sslOn = 0;
  170. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - BEGIN\n");
  171. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - url=[%s] \n", url);
  172. /* Parse the URL and initialize the host, port, path */
  173. if (parseURI(url, &host, &port, &path, &sslOn) == PR_FAILURE) {
  174. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  175. "doRequest: %s \n", HTTP_ERROR_BAD_URL);
  176. status = PR_FAILURE;
  177. goto bail;
  178. }
  179. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - host=[%s] port[%d] path[%s] \n", host, port, path);
  180. /* Initialize the Net Addr */
  181. if (PR_StringToNetAddr(host, &addr) == PR_FAILURE) {
  182. char buf[PR_NETDB_BUF_SIZE];
  183. PRHostEnt ent;
  184. status = PR_GetIPNodeByName(host, PR_AF_INET, PR_AI_DEFAULT, buf, sizeof(buf), &ent);
  185. if (status == PR_SUCCESS) {
  186. PR_EnumerateHostEnt(0, &ent, (PRUint16)port, &addr);
  187. } else {
  188. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  189. "doRequest - %s\n", HTTP_ERROR_NET_ADDR);
  190. status = HTTP_CLIENT_ERROR_NET_ADDR;
  191. goto bail;
  192. }
  193. } else {
  194. addr.inet.port = (PRUint16)port;
  195. }
  196. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - Successfully created NetAddr \n");
  197. /* open a TCP connection to the server */
  198. fd = PR_NewTCPSocket();
  199. if (!fd) {
  200. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  201. "doRequest - %s\n", HTTP_ERROR_SOCKET_CREATE);
  202. status = HTTP_CLIENT_ERROR_SOCKET_CREATE;
  203. goto bail;
  204. }
  205. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - Successfully created New TCP Socket \n");
  206. /* immediately send the response */
  207. setTCPNoDelay(fd);
  208. if (sslOn) {
  209. fd = setupSSLSocket(fd);
  210. if (fd == NULL) {
  211. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  212. "doRequest - %s\n", HTTP_ERROR_SSLSOCKET_CREATE);
  213. status = HTTP_CLIENT_ERROR_SSLSOCKET_CREATE;
  214. goto bail;
  215. }
  216. if (SSL_SetURL(fd, host) != 0) {
  217. errcode = PR_GetError();
  218. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  219. "doRequest - SSL_SetURL -> NSPR Error code (%d) \n", errcode);
  220. status = HTTP_CLIENT_ERROR_SSLSOCKET_CREATE;
  221. goto bail;
  222. }
  223. }
  224. http_connection_time_out = httpConfig->connectionTimeOut;
  225. /* connect to the host */
  226. if (PR_Connect(fd, &addr, PR_MillisecondsToInterval(http_connection_time_out)) == PR_FAILURE) {
  227. errcode = PR_GetError();
  228. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  229. "doRequest - %s (%s:%d) -> NSPR Error code (%d)\n",
  230. HTTP_ERROR_CONNECT_FAILED, host, addr.inet.port, errcode);
  231. status = HTTP_CLIENT_ERROR_CONNECT_FAILED;
  232. goto bail;
  233. }
  234. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - Successfully connected to host [%s] \n", host);
  235. /* send the request to the server */
  236. if (reqType == HTTP_REQ_TYPE_POST) {
  237. if (sendPostReq(fd, path, httpheaderArray, body) == PR_FAILURE) {
  238. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  239. "doRequest - sendPostReq: %s (%s)\n", HTTP_ERROR_SEND_REQ, path);
  240. status = HTTP_CLIENT_ERROR_SEND_REQ;
  241. goto bail;
  242. }
  243. } else {
  244. if (sendGetReq(fd, path) == PR_FAILURE) {
  245. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  246. "doRequest - sendGetReq: %s (%s)\n", HTTP_ERROR_SEND_REQ, path);
  247. status = HTTP_CLIENT_ERROR_SEND_REQ;
  248. goto bail;
  249. }
  250. }
  251. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - Successfully sent the request [%s] \n", path);
  252. /* read the response */
  253. if (processResponse(fd, buf, bytesRead, reqType) == PR_FAILURE) {
  254. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  255. "doRequest - %s (%s)\n", HTTP_ERROR_BAD_RESPONSE, url);
  256. status = HTTP_CLIENT_ERROR_BAD_RESPONSE;
  257. goto bail;
  258. }
  259. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - Successfully read the response\n");
  260. bail:
  261. if (host) {
  262. PR_Free(host);
  263. }
  264. if (path) {
  265. PR_Free(path);
  266. }
  267. if (fd) {
  268. PR_Close(fd);
  269. fd = NULL;
  270. }
  271. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "doRequest - END\n");
  272. return status;
  273. }
  274. static PRStatus
  275. processResponse(PRFileDesc *fd, char **resBUF, int *bytesRead, int reqType)
  276. {
  277. PRStatus status = PR_SUCCESS;
  278. char *location = NULL;
  279. char *protocol = NULL;
  280. char *statusNum = NULL;
  281. char *statusString = NULL;
  282. char *headers = NULL;
  283. char tmp[HTTP_DEFAULT_BUFFER_SIZE];
  284. int pos = 0;
  285. char ch;
  286. int index;
  287. int retcode;
  288. PRBool doneParsing = PR_FALSE;
  289. PRBool isRedirect = PR_FALSE;
  290. char name[HTTP_DEFAULT_BUFFER_SIZE];
  291. char value[HTTP_DEFAULT_BUFFER_SIZE];
  292. PRBool atEOL = PR_FALSE;
  293. PRBool inName = PR_TRUE;
  294. /* PKBxxx: If we are getting a redirect and the response is more the
  295. * the HTTP_DEFAULT_BUFFER_SIZE, it will cause the server to crash. A 4k
  296. * buffer should be good enough.
  297. */
  298. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "processResponse - BEGIN\n");
  299. headers = (char *)PR_Calloc(1, 4 * HTTP_DEFAULT_BUFFER_SIZE);
  300. /* Get protocol string */
  301. index = 0;
  302. while (1) {
  303. status = getChar(fd, headers + pos);
  304. if (status == PR_FAILURE) {
  305. /* Error : */
  306. goto bail;
  307. }
  308. ch = (char)headers[pos];
  309. pos++;
  310. if (!isWhiteSpace(ch)) {
  311. tmp[index++] = ch;
  312. } else {
  313. break;
  314. }
  315. }
  316. tmp[index] = '\0';
  317. protocol = PL_strdup(tmp);
  318. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "processResponse - protocol=[%s] \n", protocol);
  319. /* Get status num */
  320. index = 0;
  321. while (1) {
  322. status = getChar(fd, headers + pos);
  323. if (status == PR_FAILURE) {
  324. /* Error : */
  325. goto bail;
  326. }
  327. ch = (char)headers[pos];
  328. pos++;
  329. if (!isWhiteSpace(ch)) {
  330. tmp[index++] = ch;
  331. } else {
  332. break;
  333. }
  334. }
  335. tmp[index] = '\0';
  336. statusNum = PL_strdup(tmp);
  337. retcode = atoi(tmp);
  338. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "processResponse - statusNum=[%s] \n", statusNum);
  339. if (HTTP_RESPONSE_REDIRECT && (reqType == HTTP_REQ_TYPE_REDIRECT)) {
  340. isRedirect = PR_TRUE;
  341. }
  342. /* Get status string */
  343. if (ch != '\r') {
  344. index = 0;
  345. while (ch != '\r') {
  346. status = getChar(fd, headers + pos);
  347. if (status == PR_FAILURE) {
  348. /* Error : */
  349. goto bail;
  350. }
  351. ch = (char)headers[pos];
  352. pos++;
  353. tmp[index++] = ch;
  354. }
  355. tmp[index] = '\0';
  356. statusString = PL_strdup(tmp);
  357. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "processResponse - statusString [%s] \n", statusString);
  358. }
  359. /**
  360. * Skip CRLF
  361. */
  362. status = getChar(fd, headers + pos);
  363. if (status == PR_FAILURE) {
  364. /* Error : */
  365. goto bail;
  366. }
  367. ch = (char)headers[pos];
  368. pos++;
  369. /**
  370. * loop over response headers
  371. */
  372. index = 0;
  373. while (!doneParsing) {
  374. status = getChar(fd, headers + pos);
  375. if (status == PR_FAILURE) {
  376. /* Error : */
  377. goto bail;
  378. }
  379. ch = (char)headers[pos];
  380. pos++;
  381. switch (ch) {
  382. case ':':
  383. if (inName) {
  384. name[index] = '\0';
  385. index = 0;
  386. inName = PR_FALSE;
  387. /* skip whitespace */
  388. ch = ' ';
  389. /* status = getChar(fd, headers+pos);
  390. if (status == PR_FAILURE) {
  391. goto bail;
  392. }
  393. ch = (char)headers[pos];
  394. pos++; */
  395. while (isWhiteSpace(ch)) {
  396. status = getChar(fd, headers + pos);
  397. if (status == PR_FAILURE) {
  398. /* Error : */
  399. goto bail;
  400. }
  401. ch = (char)headers[pos];
  402. pos++;
  403. }
  404. value[index++] = ch;
  405. } else {
  406. value[index++] = ch;
  407. }
  408. break;
  409. case '\r':
  410. if (inName && !atEOL) {
  411. return PR_FALSE;
  412. }
  413. break;
  414. case '\n':
  415. if (atEOL) {
  416. doneParsing = PR_TRUE;
  417. break;
  418. }
  419. if (inName) {
  420. return PR_FALSE;
  421. }
  422. value[index] = '\0';
  423. index = 0;
  424. inName = PR_TRUE;
  425. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "processResponse - name=[%s] value=[%s]\n", name, value);
  426. if (isRedirect && !PL_strcasecmp(name, "location")) {
  427. location = PL_strdup(value);
  428. }
  429. atEOL = PR_TRUE;
  430. break;
  431. default:
  432. atEOL = PR_FALSE;
  433. if (inName) {
  434. name[index++] = ch;
  435. } else {
  436. value[index++] = ch;
  437. }
  438. break;
  439. }
  440. }
  441. if (!isRedirect) {
  442. getBody(fd, resBUF, bytesRead);
  443. } else {
  444. *resBUF = PL_strdup(location);
  445. *bytesRead = strlen(location);
  446. }
  447. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "processResponse -Response Buffer=[%s] bytesRead=[%d] \n", *resBUF, *bytesRead);
  448. bail:
  449. if (headers) {
  450. PR_Free(headers);
  451. }
  452. if (protocol) {
  453. PL_strfree(protocol);
  454. }
  455. if (statusNum) {
  456. PL_strfree(statusNum);
  457. }
  458. if (statusString) {
  459. PL_strfree(statusString);
  460. }
  461. if (location) {
  462. PL_strfree(location);
  463. }
  464. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "processResponse - END\n");
  465. return status;
  466. }
  467. static PRStatus
  468. sendGetReq(PRFileDesc *fd, const char *path)
  469. {
  470. PRStatus status = PR_SUCCESS;
  471. char *reqBUF = NULL;
  472. PRInt32 http_connection_time_out = 0;
  473. int buflen = (HTTP_GET_STD_LEN + strlen(path));
  474. reqBUF = (char *)PR_Calloc(1, buflen);
  475. if (!reqBUF) {
  476. status = PR_FAILURE;
  477. goto out;
  478. }
  479. strcpy(reqBUF, HTTP_GET);
  480. strcat(reqBUF, " ");
  481. strcat(reqBUF, path);
  482. strcat(reqBUF, " ");
  483. strcat(reqBUF, HTTP_PROTOCOL);
  484. strcat(reqBUF, "\r\n\r\n\0");
  485. http_connection_time_out = httpConfig->connectionTimeOut;
  486. status = sendFullData(fd, reqBUF, http_connection_time_out);
  487. out:
  488. if (reqBUF) {
  489. PR_Free(reqBUF);
  490. reqBUF = 0;
  491. }
  492. return status;
  493. }
  494. static PRStatus
  495. sendFullData(PRFileDesc *fd, char *buf, int timeOut)
  496. {
  497. int dataSent = 0;
  498. int bufLen = strlen(buf);
  499. int retVal = 0;
  500. PRInt32 errcode = 0;
  501. while (dataSent < bufLen) {
  502. retVal = PR_Send(fd, buf + dataSent, bufLen - dataSent, 0, PR_MillisecondsToInterval(timeOut));
  503. if (retVal == -1)
  504. break;
  505. dataSent += retVal;
  506. }
  507. if (dataSent == bufLen)
  508. return PR_SUCCESS;
  509. else {
  510. errcode = PR_GetError();
  511. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  512. "sendFullData - dataSent=%d bufLen=%d -> NSPR Error code (%d)\n",
  513. dataSent, bufLen, errcode);
  514. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "sendFullData - NSPR Error code (%d) \n", errcode);
  515. return PR_FAILURE;
  516. }
  517. }
  518. static PRStatus
  519. sendPostReq(PRFileDesc *fd, const char *path, httpheader **httpheaderArray, char *body)
  520. {
  521. PRStatus status = PR_SUCCESS;
  522. char body_len_str[20];
  523. char *reqBUF = NULL;
  524. PRInt32 http_connection_time_out = 0;
  525. int i = 0;
  526. int body_len, buflen = 0;
  527. int path_len;
  528. if (body) {
  529. body_len = strlen(body);
  530. } else {
  531. body_len = 0;
  532. }
  533. if (path) {
  534. path_len = strlen(path);
  535. } else {
  536. path_len = 0;
  537. }
  538. PR_snprintf(body_len_str, sizeof(body_len_str), "%d", body_len);
  539. buflen = (HTTP_POST_STD_LEN + path_len + body_len + strlen(body_len_str));
  540. for (i = 0; httpheaderArray[i] != NULL; i++) {
  541. if (httpheaderArray[i]->name != NULL) {
  542. buflen += strlen(httpheaderArray[i]->name) + 2;
  543. if (httpheaderArray[i]->value != NULL)
  544. buflen += strlen(httpheaderArray[i]->value) + 2;
  545. }
  546. }
  547. reqBUF = (char *)PR_Calloc(1, buflen);
  548. if (!reqBUF) {
  549. status = PR_FAILURE;
  550. goto out;
  551. }
  552. strcpy(reqBUF, HTTP_POST);
  553. strcat(reqBUF, " ");
  554. strcat(reqBUF, path);
  555. strcat(reqBUF, " ");
  556. strcat(reqBUF, HTTP_PROTOCOL);
  557. strcat(reqBUF, "\r\n");
  558. strcat(reqBUF, HTTP_CONTENT_LENGTH);
  559. strcat(reqBUF, " ");
  560. strcat(reqBUF, body_len_str);
  561. strcat(reqBUF, "\r\n");
  562. strcat(reqBUF, HTTP_CONTENT_TYPE_URL_ENCODED);
  563. strcat(reqBUF, "\r\n");
  564. for (i = 0; httpheaderArray[i] != NULL; i++) {
  565. if (httpheaderArray[i]->name != NULL)
  566. strcat(reqBUF, httpheaderArray[i]->name);
  567. strcat(reqBUF, ": ");
  568. if (httpheaderArray[i]->value != NULL)
  569. strcat(reqBUF, httpheaderArray[i]->value);
  570. strcat(reqBUF, "\r\n");
  571. }
  572. strcat(reqBUF, "\r\n");
  573. if (body) {
  574. strcat(reqBUF, body);
  575. }
  576. strcat(reqBUF, "\0");
  577. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "sendPostReq - reqBUF is %s \n", reqBUF);
  578. http_connection_time_out = httpConfig->connectionTimeOut;
  579. status = sendFullData(fd, reqBUF, http_connection_time_out);
  580. out:
  581. if (reqBUF) {
  582. PR_Free(reqBUF);
  583. reqBUF = 0;
  584. }
  585. return status;
  586. }
  587. static PRStatus
  588. getChar(PRFileDesc *fd, char *buf)
  589. {
  590. PRInt32 bytesRead = http_read(fd, buf, 1);
  591. if (bytesRead <= 0) {
  592. PRInt32 errcode = PR_GetError();
  593. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM, "sendPostReq - "
  594. "getChar - NSPR Error code (%d)\n",
  595. errcode);
  596. return PR_FAILURE;
  597. }
  598. return PR_SUCCESS;
  599. }
  600. static PRStatus
  601. getBody(PRFileDesc *fd, char **buf, int *actualBytesRead)
  602. {
  603. int totalBytesRead = 0;
  604. int size = 4 * HTTP_DEFAULT_BUFFER_SIZE;
  605. int bytesRead = size;
  606. char *data = (char *)PR_Calloc(1, size);
  607. while (bytesRead == size) {
  608. bytesRead = http_read(fd, (data + totalBytesRead), size);
  609. if (bytesRead <= 0) {
  610. /* Read error */
  611. return PR_FAILURE;
  612. }
  613. if (bytesRead == size) {
  614. /* more data to be read so increase the buffer */
  615. size = size * 2;
  616. data = (char *)PR_Realloc(data, size);
  617. }
  618. totalBytesRead += bytesRead;
  619. }
  620. *buf = data;
  621. *actualBytesRead = totalBytesRead;
  622. return PR_SUCCESS;
  623. }
  624. static PRInt32
  625. http_read(PRFileDesc *fd, char *buf, int size)
  626. {
  627. PRInt32 http_read_time_out = 0;
  628. http_read_time_out = httpConfig->readTimeOut;
  629. return PR_Recv(fd, buf, size, 0, PR_MillisecondsToInterval(http_read_time_out));
  630. }
  631. static PRBool
  632. isWhiteSpace(char ch)
  633. {
  634. PRBool b = PR_FALSE;
  635. if (ch == ' ') {
  636. b = PR_TRUE;
  637. }
  638. return b;
  639. }
  640. static PRStatus
  641. parseURI(const char *urlstr, char **host, PRInt32 *port, char **path, int *sslOn)
  642. {
  643. PRStatus status = PR_SUCCESS;
  644. char *brk;
  645. int len;
  646. static const char delimiters[] = ":/?#";
  647. char *url = isHttpReq(urlstr, sslOn);
  648. if (*sslOn) {
  649. *port = 443;
  650. } else {
  651. *port = 80;
  652. }
  653. if (url == NULL) {
  654. /* Error : */
  655. status = PR_FAILURE;
  656. goto bail;
  657. }
  658. len = PL_strlen(url);
  659. /* Currently we do not support Ipv6 addresses */
  660. brk = PL_strpbrk(url, delimiters);
  661. if (!brk) {
  662. *host = PL_strndup(url, len);
  663. toLowerCase(*host);
  664. goto bail;
  665. }
  666. switch (*brk) {
  667. case '/':
  668. case '?':
  669. case '#':
  670. /* Get the Host, the rest is Path */
  671. *host = PL_strndup(url, (brk - url));
  672. toLowerCase(*host);
  673. status = parseAtPath(brk, path);
  674. break;
  675. case ':':
  676. /* Get the Host and process port, path */
  677. *host = PL_strndup(url, (brk - url));
  678. toLowerCase(*host);
  679. status = parseAtPort(brk + 1, port, path);
  680. break;
  681. default:
  682. /* Error : HTTP_BAD_URL */
  683. break;
  684. }
  685. bail:
  686. if (url) {
  687. PR_Free(url);
  688. }
  689. return status;
  690. }
  691. static PRStatus
  692. parseAtPort(const char *url, PRInt32 *port, char **path)
  693. {
  694. PRStatus status = PR_SUCCESS;
  695. static const char delimiters[] = "/?#";
  696. char *brk = PL_strpbrk(url, delimiters);
  697. if (!brk) /* everything is a Port */
  698. {
  699. *port = getPort(url);
  700. if (*port <= 0) {
  701. /* Error : HTTP_BAD_URL */
  702. return PR_FAILURE;
  703. } else {
  704. return status;
  705. }
  706. }
  707. switch (*brk) {
  708. case '/':
  709. case '?':
  710. case '#':
  711. /* Get the Port, the rest is Path */
  712. *port = getPort(url);
  713. if (*port <= 0) {
  714. /* Error : HTTP_BAD_URL */
  715. return PR_FAILURE;
  716. }
  717. status = parseAtPath(brk, path);
  718. break;
  719. default:
  720. /* Error : HTTP_BAD_URL */
  721. break;
  722. }
  723. return status;
  724. }
  725. static PRStatus
  726. parseAtPath(const char *url, char **path)
  727. {
  728. PRStatus status = PR_SUCCESS;
  729. char *dir = "%s%s";
  730. *path = (char *)PR_Calloc(1, strlen(dir) + strlen(url) + 2);
  731. if (!*path) {
  732. /* Error : HTTP_BAD_URL */
  733. status = PR_FAILURE;
  734. goto out;
  735. }
  736. /* Just write the path and check for a starting / */
  737. if ('/' != *url) {
  738. sprintf(*path, dir, "/", url);
  739. } else {
  740. strcpy(*path, url);
  741. }
  742. out:
  743. return status;
  744. }
  745. static void
  746. toLowerCase(char *str)
  747. {
  748. if (str) {
  749. char *lstr = str;
  750. PRInt8 shift = 'a' - 'A';
  751. for (; (*lstr != '\0'); ++lstr) {
  752. if ((*(lstr) <= 'Z') && (*(lstr) >= 'A')) {
  753. *(lstr) = *(lstr) + shift;
  754. }
  755. }
  756. }
  757. }
  758. static PRInt32
  759. getPort(const char *src)
  760. {
  761. /* search for digits up to a slash or the string ends */
  762. const char *port = src;
  763. PRInt32 returnValue = -1;
  764. char c;
  765. /* skip leading white space */
  766. while (isAsciiSpace(*port))
  767. port++;
  768. while ((c = *port++) != '\0') {
  769. /* stop if slash or ? or # reached */
  770. if (c == '/' || c == '?' || c == '#')
  771. break;
  772. else if (!isAsciiDigit(c))
  773. return returnValue;
  774. }
  775. return (0 < PR_sscanf(src, "%d", &returnValue)) ? returnValue : -1;
  776. }
  777. static PRBool
  778. isAsciiSpace(char aChar)
  779. {
  780. if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) {
  781. return PR_TRUE;
  782. }
  783. return PR_FALSE;
  784. }
  785. static PRBool
  786. isAsciiDigit(char aChar)
  787. {
  788. if ((aChar >= '0') && (aChar <= '9')) {
  789. return PR_TRUE;
  790. }
  791. return PR_FALSE;
  792. }
  793. static void
  794. setTCPNoDelay(PRFileDesc *fd)
  795. {
  796. PRStatus status = PR_SUCCESS;
  797. PRSocketOptionData opt;
  798. opt.option = PR_SockOpt_NoDelay;
  799. opt.value.no_delay = PR_FALSE;
  800. status = PR_GetSocketOption(fd, &opt);
  801. if (status == PR_FAILURE) {
  802. return;
  803. }
  804. opt.option = PR_SockOpt_NoDelay;
  805. opt.value.no_delay = PR_TRUE;
  806. status = PR_SetSocketOption(fd, &opt);
  807. if (status == PR_FAILURE) {
  808. return;
  809. }
  810. return;
  811. }
  812. static char *
  813. isHttpReq(const char *url, int *sslOn)
  814. {
  815. static const char http_protopol_header[] = "http://";
  816. static const char https_protopol_header[] = "https://";
  817. char *newstr = NULL;
  818. /* skip leading white space */
  819. while (isAsciiSpace(*url)) {
  820. url++;
  821. }
  822. if (strncmp(url, http_protopol_header, strlen(http_protopol_header)) == 0) {
  823. newstr = (char *)PR_Calloc(1, (strlen(url) - strlen(http_protopol_header) + 1));
  824. strcpy(newstr, url + 7);
  825. strcat(newstr, "\0");
  826. *sslOn = 0;
  827. } else if (strncmp(url, https_protopol_header, strlen(https_protopol_header)) == 0) {
  828. newstr = (char *)PR_Calloc(1, (strlen(url) - strlen(https_protopol_header) + 1));
  829. strcpy(newstr, url + 8);
  830. strcat(newstr, "\0");
  831. *sslOn = 1;
  832. }
  833. return newstr;
  834. }
  835. PRFileDesc *
  836. setupSSLSocket(PRFileDesc *fd)
  837. {
  838. SECStatus secStatus;
  839. PRFileDesc *sslSocket;
  840. PRSocketOptionData socketOption;
  841. char *certNickname = NULL;
  842. socketOption.option = PR_SockOpt_Nonblocking;
  843. socketOption.value.non_blocking = PR_FALSE;
  844. if (PR_SetSocketOption(fd, &socketOption) != 0) {
  845. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  846. "setupSSLSocket - Cannot set socket option NSS \n");
  847. return NULL;
  848. }
  849. sslSocket = SSL_ImportFD(NULL, fd);
  850. if (!sslSocket) {
  851. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  852. "setupSSLSocket - Cannot import to SSL Socket\n");
  853. goto sslbail;
  854. }
  855. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  856. "setupSSLSocket - setupssl socket created\n");
  857. secStatus = SSL_OptionSet(sslSocket, SSL_SECURITY, 1);
  858. if (SECSuccess != secStatus) {
  859. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  860. "setupSSLSocket - Cannot set SSL_SECURITY option\n");
  861. goto sslbail;
  862. }
  863. secStatus = SSL_OptionSet(sslSocket, SSL_HANDSHAKE_AS_CLIENT, 1);
  864. if (SECSuccess != secStatus) {
  865. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  866. "setupSSLSocket - Cannot set SSL_HANDSHAKE_AS_CLIENT option\n");
  867. goto sslbail;
  868. }
  869. /* Set SSL callback routines. */
  870. secStatus = SSL_GetClientAuthDataHook(sslSocket,
  871. (SSLGetClientAuthData)getClientAuthData,
  872. (void *)certNickname);
  873. if (secStatus != SECSuccess) {
  874. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  875. "setupSSLSocket - SSL_GetClientAuthDataHook Failed\n");
  876. goto sslbail;
  877. }
  878. secStatus = SSL_AuthCertificateHook(sslSocket,
  879. (SSLAuthCertificate)authCertificate,
  880. (void *)CERT_GetDefaultCertDB());
  881. if (secStatus != SECSuccess) {
  882. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  883. "setupSSLSocket - SSL_AuthCertificateHook Failed\n");
  884. goto sslbail;
  885. }
  886. secStatus = SSL_BadCertHook(sslSocket,
  887. (SSLBadCertHandler)badCertHandler, NULL);
  888. if (secStatus != SECSuccess) {
  889. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  890. "setupSSLSocket - SSL_BadCertHook Failed\n");
  891. goto sslbail;
  892. }
  893. secStatus = SSL_HandshakeCallback(sslSocket,
  894. (SSLHandshakeCallback)handshakeCallback, NULL);
  895. if (secStatus != SECSuccess) {
  896. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  897. "setupSSLSocket - SSL_HandshakeCallback Failed\n");
  898. goto sslbail;
  899. }
  900. return sslSocket;
  901. sslbail:
  902. PR_Close(fd);
  903. return NULL;
  904. }
  905. SECStatus
  906. authCertificate(void *arg, PRFileDesc *socket, PRBool checksig, PRBool isServer)
  907. {
  908. SECCertUsage certUsage;
  909. CERTCertificate *cert;
  910. void *pinArg;
  911. char *hostName;
  912. SECStatus secStatus;
  913. if (!arg || !socket) {
  914. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  915. "authCertificate - Faulty socket in callback function\n");
  916. return SECFailure;
  917. }
  918. /* Define how the cert is being used based upon the isServer flag. */
  919. certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
  920. cert = SSL_PeerCertificate(socket);
  921. pinArg = SSL_RevealPinArg(socket);
  922. secStatus = CERT_VerifyCertNow((CERTCertDBHandle *)arg,
  923. cert,
  924. checksig,
  925. certUsage,
  926. pinArg);
  927. /* If this is a server, we're finished. */
  928. if (isServer || secStatus != SECSuccess) {
  929. return secStatus;
  930. }
  931. hostName = SSL_RevealURL(socket);
  932. if (hostName && hostName[0]) {
  933. secStatus = CERT_VerifyCertName(cert, hostName);
  934. } else {
  935. PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
  936. secStatus = SECFailure;
  937. }
  938. if (hostName)
  939. PR_Free(hostName);
  940. return secStatus;
  941. }
  942. SECStatus
  943. badCertHandler(void *arg, PRFileDesc *socket __attribute__((unused)))
  944. {
  945. SECStatus secStatus = SECFailure;
  946. PRErrorCode err;
  947. /* log invalid cert here */
  948. if (!arg) {
  949. return secStatus;
  950. }
  951. *(PRErrorCode *)arg = err = PORT_GetError();
  952. switch (err) {
  953. case SEC_ERROR_INVALID_AVA:
  954. case SEC_ERROR_INVALID_TIME:
  955. case SEC_ERROR_BAD_SIGNATURE:
  956. case SEC_ERROR_EXPIRED_CERTIFICATE:
  957. case SEC_ERROR_UNKNOWN_ISSUER:
  958. case SEC_ERROR_UNTRUSTED_CERT:
  959. case SEC_ERROR_CERT_VALID:
  960. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
  961. case SEC_ERROR_CRL_EXPIRED:
  962. case SEC_ERROR_CRL_BAD_SIGNATURE:
  963. case SEC_ERROR_EXTENSION_VALUE_INVALID:
  964. case SEC_ERROR_CA_CERT_INVALID:
  965. case SEC_ERROR_CERT_USAGES_INVALID:
  966. case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
  967. secStatus = SECSuccess;
  968. break;
  969. default:
  970. secStatus = SECFailure;
  971. break;
  972. }
  973. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  974. "badCertHandler - Bad certificate: %d\n", err);
  975. return secStatus;
  976. }
  977. SECStatus
  978. getClientAuthData(void *arg,
  979. PRFileDesc *socket,
  980. struct CERTDistNamesStr *caNames,
  981. struct CERTCertificateStr **pRetCert,
  982. struct SECKEYPrivateKeyStr **pRetKey)
  983. {
  984. CERTCertificate *cert;
  985. SECKEYPrivateKey *privKey = NULL;
  986. char *chosenNickName = (char *)arg;
  987. void *proto_win = NULL;
  988. SECStatus secStatus = SECFailure;
  989. proto_win = SSL_RevealPinArg(socket);
  990. if (chosenNickName) {
  991. cert = PK11_FindCertFromNickname(chosenNickName, proto_win);
  992. if (cert) {
  993. privKey = PK11_FindKeyByAnyCert(cert, proto_win);
  994. if (privKey) {
  995. secStatus = SECSuccess;
  996. } else {
  997. CERT_DestroyCertificate(cert);
  998. }
  999. }
  1000. } else { /* no nickname given, automatically find the right cert */
  1001. CERTCertNicknames *names;
  1002. int i;
  1003. names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(),
  1004. SEC_CERT_NICKNAMES_USER, proto_win);
  1005. if (names != NULL) {
  1006. for (i = 0; i < names->numnicknames; i++) {
  1007. cert = PK11_FindCertFromNickname(names->nicknames[i],
  1008. proto_win);
  1009. if (!cert) {
  1010. continue;
  1011. }
  1012. /* Only check unexpired certs */
  1013. if (CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE) != secCertTimeValid) {
  1014. CERT_DestroyCertificate(cert);
  1015. continue;
  1016. }
  1017. secStatus = NSS_CmpCertChainWCANames(cert, caNames);
  1018. if (secStatus == SECSuccess) {
  1019. privKey = PK11_FindKeyByAnyCert(cert, proto_win);
  1020. if (privKey) {
  1021. break;
  1022. }
  1023. secStatus = SECFailure;
  1024. break;
  1025. }
  1026. CERT_FreeNicknames(names);
  1027. } /* for loop */
  1028. }
  1029. }
  1030. if (secStatus == SECSuccess) {
  1031. *pRetCert = cert;
  1032. *pRetKey = privKey;
  1033. }
  1034. return secStatus;
  1035. }
  1036. SECStatus
  1037. handshakeCallback(PRFileDesc *socket __attribute__((unused)), void *arg __attribute__((unused)))
  1038. {
  1039. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  1040. "handshakeCallback - Handshake has completed, ready to send data securely.\n");
  1041. return SECSuccess;
  1042. }
  1043. /**
  1044. * PUBLIC FUNCTIONS IMPLEMENTATION
  1045. */
  1046. int
  1047. http_impl_init(Slapi_ComponentId *plugin_id)
  1048. {
  1049. int status = HTTP_IMPL_SUCCESS;
  1050. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  1051. "-> http_impl_init\n");
  1052. httpConfig = NULL;
  1053. httpConfig = (httpPluginConfig *)slapi_ch_calloc(1, sizeof(httpPluginConfig));
  1054. status = readConfigLDAPurl(plugin_id, HTTP_PLUGIN_DN);
  1055. if (status != 0) {
  1056. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  1057. "http_impl_init - Unable to get HTTP config information \n");
  1058. return HTTP_IMPL_FAILURE;
  1059. }
  1060. status = readConfigLDAPurl(plugin_id, CONFIG_DN);
  1061. if (status != 0) {
  1062. slapi_log_err(SLAPI_LOG_ERR, HTTP_PLUGIN_SUBSYSTEM,
  1063. "http_impl_init - Unable to get config information \n");
  1064. return HTTP_IMPL_FAILURE;
  1065. }
  1066. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  1067. "<- http_impl_init\n");
  1068. return status;
  1069. }
  1070. int
  1071. http_impl_get_text(char *url, char **data, int *bytesRead)
  1072. {
  1073. int status = HTTP_IMPL_SUCCESS;
  1074. status = doRequestRetry(url, NULL, NULL, data, bytesRead, HTTP_REQ_TYPE_GET);
  1075. return status;
  1076. }
  1077. int
  1078. http_impl_get_binary(char *url, char **data, int *bytesRead)
  1079. {
  1080. int status = HTTP_IMPL_SUCCESS;
  1081. status = doRequestRetry(url, NULL, NULL, data, bytesRead, HTTP_REQ_TYPE_GET);
  1082. return status;
  1083. }
  1084. int
  1085. http_impl_get_redirected_uri(char *url, char **data, int *bytesRead)
  1086. {
  1087. int status = HTTP_IMPL_SUCCESS;
  1088. status = doRequestRetry(url, NULL, NULL, data, bytesRead, HTTP_REQ_TYPE_REDIRECT);
  1089. return status;
  1090. }
  1091. int
  1092. http_impl_post(char *url, httpheader **httpheaderArray, char *body, char **data, int *bytesRead)
  1093. {
  1094. int status = HTTP_IMPL_SUCCESS;
  1095. status = doRequestRetry(url, httpheaderArray, body, data, bytesRead, HTTP_REQ_TYPE_POST);
  1096. return status;
  1097. }
  1098. void
  1099. http_impl_shutdown(void)
  1100. {
  1101. /**
  1102. * Put cleanup code here
  1103. */
  1104. }
  1105. static int
  1106. readConfigLDAPurl(Slapi_ComponentId *plugin_id, char *plugindn)
  1107. {
  1108. int rc = LDAP_SUCCESS;
  1109. Slapi_DN *sdn = NULL;
  1110. int status = HTTP_IMPL_SUCCESS;
  1111. Slapi_Entry *entry = NULL;
  1112. sdn = slapi_sdn_new_dn_byref(plugindn);
  1113. rc = slapi_search_internal_get_entry(sdn, NULL, &entry, plugin_id);
  1114. slapi_sdn_free(&sdn);
  1115. if (rc != LDAP_SUCCESS) {
  1116. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  1117. "readConfigLDAPurl - Could not find entry %s (error %d)\n", plugindn, rc);
  1118. status = HTTP_IMPL_FAILURE;
  1119. return status;
  1120. }
  1121. if (NULL == entry) {
  1122. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM,
  1123. "readConfigLDAPurl - No entries found for <%s>\n", plugindn);
  1124. status = HTTP_IMPL_FAILURE;
  1125. return status;
  1126. }
  1127. if ((PL_strcasecmp(plugindn, HTTP_PLUGIN_DN) == 0))
  1128. status = parseHTTPConfigEntry(entry);
  1129. else
  1130. status = parseConfigEntry(entry);
  1131. slapi_entry_free(entry);
  1132. return status;
  1133. }
  1134. /* Retrieves the plugin configuration info */
  1135. /* Retrieves security info as well as the path info required for the SSL
  1136. config dir */
  1137. static int
  1138. parseConfigEntry(Slapi_Entry *e)
  1139. {
  1140. char *value = NULL;
  1141. value = slapi_entry_attr_get_charptr(e, ATTR_DS_SECURITY);
  1142. if (value) {
  1143. httpConfig->DS_sslOn = value;
  1144. }
  1145. return HTTP_IMPL_SUCCESS;
  1146. }
  1147. static int
  1148. parseHTTPConfigEntry(Slapi_Entry *e)
  1149. {
  1150. int value = 0;
  1151. value = slapi_entry_attr_get_int(e, ATTR_RETRY_COUNT);
  1152. if (value) {
  1153. httpConfig->retryCount = value;
  1154. }
  1155. value = slapi_entry_attr_get_int(e, ATTR_CONNECTION_TIME_OUT);
  1156. if (value) {
  1157. httpConfig->connectionTimeOut = value;
  1158. } else {
  1159. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "parseHTTPConfigEntry - HTTP Connection Time Out cannot be read. Setting to default value of 5000 ms \n");
  1160. httpConfig->connectionTimeOut = 5000;
  1161. }
  1162. value = slapi_entry_attr_get_int(e, ATTR_READ_TIME_OUT);
  1163. if (value) {
  1164. httpConfig->readTimeOut = value;
  1165. } else {
  1166. slapi_log_err(SLAPI_LOG_PLUGIN, HTTP_PLUGIN_SUBSYSTEM, "parseHTTPConfigEntry - HTTP Read Time Out cannot be read. Setting to default value of 5000 ms \n");
  1167. httpConfig->readTimeOut = 5000;
  1168. }
  1169. httpConfig->nssInitialized = 0;
  1170. return HTTP_IMPL_SUCCESS;
  1171. }
  1172. /**
  1173. * Self Testing
  1174. */
  1175. #ifdef BUILD_STANDALONE
  1176. int
  1177. main(int argc, char **argv)
  1178. {
  1179. PRStatus status = PR_SUCCESS;
  1180. char *buf;
  1181. int bytes;
  1182. char *host;
  1183. PRInt32 port;
  1184. char *path;
  1185. if (argc < 2) {
  1186. printf("URL missing\n");
  1187. return -1;
  1188. }
  1189. PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  1190. doRequest(argv[1], &buf, &bytes, 2);
  1191. printf("%s\n", buf);
  1192. return -1;
  1193. }
  1194. #endif