http_impl.c 37 KB

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