request.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714
  1. /* $OpenLDAP$ */
  2. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  3. *
  4. * Copyright 1998-2022 The OpenLDAP Foundation.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted only as authorized by the OpenLDAP
  9. * Public License.
  10. *
  11. * A copy of this license is available in the file LICENSE in the
  12. * top-level directory of the distribution or, alternatively, at
  13. * <http://www.OpenLDAP.org/license.html>.
  14. */
  15. /* Portions Copyright (c) 1995 Regents of the University of Michigan.
  16. * All rights reserved.
  17. */
  18. /* This notice applies to changes, created by or for Novell, Inc.,
  19. * to preexisting works for which notices appear elsewhere in this file.
  20. *
  21. * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
  22. *
  23. * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
  24. * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
  25. * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
  26. * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
  27. * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
  28. * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
  29. * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
  30. * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
  31. *---
  32. * Modification to OpenLDAP source by Novell, Inc.
  33. * April 2000 sfs Added code to chase V3 referrals
  34. * request.c - sending of ldap requests; handling of referrals
  35. *---
  36. * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
  37. * can be found in the file "build/LICENSE-2.0.1" in this distribution
  38. * of OpenLDAP Software.
  39. */
  40. #include "portable.h"
  41. #include <stdio.h>
  42. #include <ac/stdlib.h>
  43. #include <ac/errno.h>
  44. #include <ac/param.h>
  45. #include <ac/socket.h>
  46. #include <ac/string.h>
  47. #include <ac/time.h>
  48. #include <ac/unistd.h>
  49. #include "ldap-int.h"
  50. #include "lber.h"
  51. /* used by ldap_send_server_request and ldap_new_connection */
  52. #ifdef LDAP_R_COMPILE
  53. #define LDAP_CONN_LOCK_IF(nolock) \
  54. { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); }
  55. #define LDAP_CONN_UNLOCK_IF(nolock) \
  56. { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); }
  57. #define LDAP_REQ_LOCK_IF(nolock) \
  58. { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); }
  59. #define LDAP_REQ_UNLOCK_IF(nolock) \
  60. { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); }
  61. #define LDAP_RES_LOCK_IF(nolock) \
  62. { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); }
  63. #define LDAP_RES_UNLOCK_IF(nolock) \
  64. { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); }
  65. #else
  66. #define LDAP_CONN_LOCK_IF(nolock)
  67. #define LDAP_CONN_UNLOCK_IF(nolock)
  68. #define LDAP_REQ_LOCK_IF(nolock)
  69. #define LDAP_REQ_UNLOCK_IF(nolock)
  70. #define LDAP_RES_LOCK_IF(nolock)
  71. #define LDAP_RES_UNLOCK_IF(nolock)
  72. #endif
  73. static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any ));
  74. static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc ));
  75. static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr ));
  76. static BerElement *
  77. re_encode_request( LDAP *ld,
  78. BerElement *origber,
  79. ber_int_t msgid,
  80. int sref,
  81. LDAPURLDesc *srv,
  82. int *type );
  83. BerElement *
  84. ldap_alloc_ber_with_options( LDAP *ld )
  85. {
  86. BerElement *ber;
  87. ber = ber_alloc_t( ld->ld_lberoptions );
  88. if ( ber == NULL ) {
  89. ld->ld_errno = LDAP_NO_MEMORY;
  90. }
  91. return( ber );
  92. }
  93. void
  94. ldap_set_ber_options( LDAP *ld, BerElement *ber )
  95. {
  96. /* ld_lberoptions is constant, hence no lock */
  97. ber->ber_options = ld->ld_lberoptions;
  98. }
  99. /* sets needed mutexes - no mutexes set to this point */
  100. ber_int_t
  101. ldap_send_initial_request(
  102. LDAP *ld,
  103. ber_tag_t msgtype,
  104. const char *dn,
  105. BerElement *ber,
  106. ber_int_t msgid)
  107. {
  108. int rc = 1;
  109. ber_socket_t sd = AC_SOCKET_INVALID;
  110. Debug0( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n" );
  111. LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
  112. if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ) == -1 ) {
  113. /* not connected yet */
  114. rc = ldap_open_defconn( ld );
  115. if ( rc == 0 ) {
  116. ber_sockbuf_ctrl( ld->ld_defconn->lconn_sb,
  117. LBER_SB_OPT_GET_FD, &sd );
  118. }
  119. }
  120. if ( ld->ld_defconn && ld->ld_defconn->lconn_status == LDAP_CONNST_CONNECTING )
  121. rc = ldap_int_check_async_open( ld, sd );
  122. if( rc < 0 ) {
  123. ber_free( ber, 1 );
  124. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  125. return( -1 );
  126. } else if ( rc == 0 ) {
  127. Debug0( LDAP_DEBUG_TRACE,
  128. "ldap_open_defconn: successful\n" );
  129. }
  130. #ifdef LDAP_CONNECTIONLESS
  131. if (LDAP_IS_UDP(ld)) {
  132. if (msgtype == LDAP_REQ_BIND) {
  133. LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
  134. if (ld->ld_options.ldo_cldapdn)
  135. ldap_memfree(ld->ld_options.ldo_cldapdn);
  136. ld->ld_options.ldo_cldapdn = ldap_strdup(dn);
  137. ber_free( ber, 1 );
  138. LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
  139. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  140. return 0;
  141. }
  142. if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH)
  143. {
  144. ber_free( ber, 1 );
  145. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  146. return LDAP_PARAM_ERROR;
  147. }
  148. }
  149. #endif
  150. LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
  151. rc = ldap_send_server_request( ld, ber, msgid, NULL,
  152. NULL, NULL, NULL, 0, 0 );
  153. LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
  154. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  155. return(rc);
  156. }
  157. /* protected by conn_mutex */
  158. int
  159. ldap_int_flush_request(
  160. LDAP *ld,
  161. LDAPRequest *lr )
  162. {
  163. LDAPConn *lc = lr->lr_conn;
  164. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
  165. if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) {
  166. if (( sock_errno() == EAGAIN ) || ( sock_errno() == ENOTCONN )) {
  167. /* ENOTCONN is returned in Solaris 10 */
  168. /* need to continue write later */
  169. lr->lr_status = LDAP_REQST_WRITING;
  170. ldap_mark_select_write( ld, lc->lconn_sb );
  171. ld->ld_errno = LDAP_BUSY;
  172. return -2;
  173. } else {
  174. ld->ld_errno = LDAP_SERVER_DOWN;
  175. ldap_free_request( ld, lr );
  176. ldap_free_connection( ld, lc, 0, 0 );
  177. return( -1 );
  178. }
  179. } else {
  180. if ( lr->lr_parent == NULL ) {
  181. lr->lr_ber->ber_end = lr->lr_ber->ber_ptr;
  182. lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf;
  183. }
  184. lr->lr_status = LDAP_REQST_INPROGRESS;
  185. /* sent -- waiting for a response */
  186. ldap_mark_select_read( ld, lc->lconn_sb );
  187. ldap_clear_select_write( ld, lc->lconn_sb );
  188. }
  189. return 0;
  190. }
  191. /*
  192. * protected by req_mutex
  193. * if m_noconn then protect using conn_lock
  194. * else already protected with conn_lock
  195. * if m_res then also protected by res_mutex
  196. */
  197. int
  198. ldap_send_server_request(
  199. LDAP *ld,
  200. BerElement *ber,
  201. ber_int_t msgid,
  202. LDAPRequest *parentreq,
  203. LDAPURLDesc **srvlist,
  204. LDAPConn *lc,
  205. LDAPreqinfo *bind,
  206. int m_noconn,
  207. int m_res )
  208. {
  209. LDAPRequest *lr;
  210. int incparent, rc;
  211. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
  212. Debug0( LDAP_DEBUG_TRACE, "ldap_send_server_request\n" );
  213. incparent = 0;
  214. ld->ld_errno = LDAP_SUCCESS; /* optimistic */
  215. LDAP_CONN_LOCK_IF(m_noconn);
  216. if ( lc == NULL ) {
  217. if ( srvlist == NULL ) {
  218. lc = ld->ld_defconn;
  219. } else {
  220. lc = find_connection( ld, *srvlist, 1 );
  221. if ( lc == NULL ) {
  222. if ( (bind != NULL) && (parentreq != NULL) ) {
  223. /* Remember the bind in the parent */
  224. incparent = 1;
  225. ++parentreq->lr_outrefcnt;
  226. }
  227. lc = ldap_new_connection( ld, srvlist, 0,
  228. 1, bind, 1, m_res );
  229. }
  230. }
  231. }
  232. /* async connect... */
  233. if ( lc != NULL && lc->lconn_status == LDAP_CONNST_CONNECTING ) {
  234. ber_socket_t sd = AC_SOCKET_ERROR;
  235. struct timeval tv = { 0 };
  236. ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sd );
  237. /* poll ... */
  238. switch ( ldap_int_poll( ld, sd, &tv, 1 ) ) {
  239. case 0:
  240. /* go on! */
  241. lc->lconn_status = LDAP_CONNST_CONNECTED;
  242. break;
  243. case -2:
  244. /* async only occurs if a network timeout is set */
  245. /* honor network timeout */
  246. LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
  247. if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec )
  248. {
  249. /* caller will have to call again */
  250. ld->ld_errno = LDAP_X_CONNECTING;
  251. }
  252. LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
  253. /* fallthru */
  254. default:
  255. /* error */
  256. break;
  257. }
  258. }
  259. if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
  260. if ( ld->ld_errno == LDAP_SUCCESS ) {
  261. ld->ld_errno = LDAP_SERVER_DOWN;
  262. }
  263. ber_free( ber, 1 );
  264. if ( incparent ) {
  265. /* Forget about the bind */
  266. --parentreq->lr_outrefcnt;
  267. }
  268. LDAP_CONN_UNLOCK_IF(m_noconn);
  269. return( -1 );
  270. }
  271. use_connection( ld, lc );
  272. #ifdef LDAP_CONNECTIONLESS
  273. if ( LDAP_IS_UDP( ld )) {
  274. BerElement tmpber = *ber;
  275. ber_rewind( &tmpber );
  276. LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
  277. rc = ber_write( &tmpber, ld->ld_options.ldo_peer,
  278. sizeof( struct sockaddr_storage ), 0 );
  279. LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
  280. if ( rc == -1 ) {
  281. ld->ld_errno = LDAP_ENCODING_ERROR;
  282. ber_free( ber, 1 );
  283. LDAP_CONN_UNLOCK_IF(m_noconn);
  284. return rc;
  285. }
  286. }
  287. #endif
  288. /* If we still have an incomplete write, try to finish it before
  289. * dealing with the new request. If we don't finish here, return
  290. * LDAP_BUSY and let the caller retry later. We only allow a single
  291. * request to be in WRITING state.
  292. */
  293. rc = 0;
  294. if ( ld->ld_requests != NULL ) {
  295. TAvlnode *node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_RIGHT );
  296. LDAPRequest *lr;
  297. assert( node != NULL );
  298. lr = node->avl_data;
  299. if ( lr->lr_status == LDAP_REQST_WRITING &&
  300. ldap_int_flush_request( ld, lr ) < 0 ) {
  301. rc = -1;
  302. }
  303. }
  304. if ( rc ) {
  305. ber_free( ber, 1 );
  306. LDAP_CONN_UNLOCK_IF(m_noconn);
  307. return rc;
  308. }
  309. lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) );
  310. if ( lr == NULL ) {
  311. ld->ld_errno = LDAP_NO_MEMORY;
  312. ldap_free_connection( ld, lc, 0, 0 );
  313. ber_free( ber, 1 );
  314. if ( incparent ) {
  315. /* Forget about the bind */
  316. --parentreq->lr_outrefcnt;
  317. }
  318. LDAP_CONN_UNLOCK_IF(m_noconn);
  319. return( -1 );
  320. }
  321. lr->lr_msgid = msgid;
  322. lr->lr_status = LDAP_REQST_INPROGRESS;
  323. lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */
  324. lr->lr_ber = ber;
  325. lr->lr_conn = lc;
  326. if ( parentreq != NULL ) { /* sub-request */
  327. if ( !incparent ) {
  328. /* Increment if we didn't do it before the bind */
  329. ++parentreq->lr_outrefcnt;
  330. }
  331. lr->lr_origid = parentreq->lr_origid;
  332. lr->lr_parentcnt = ++parentreq->lr_parentcnt;
  333. lr->lr_parent = parentreq;
  334. lr->lr_refnext = parentreq->lr_child;
  335. parentreq->lr_child = lr;
  336. } else { /* original request */
  337. lr->lr_origid = lr->lr_msgid;
  338. }
  339. /* Extract requestDN for future reference */
  340. #ifdef LDAP_CONNECTIONLESS
  341. if ( !LDAP_IS_UDP(ld) )
  342. #endif
  343. {
  344. BerElement tmpber = *ber;
  345. ber_int_t bint;
  346. ber_tag_t tag, rtag;
  347. ber_reset( &tmpber, 1 );
  348. rtag = ber_scanf( &tmpber, "{it", /*}*/ &bint, &tag );
  349. switch ( tag ) {
  350. case LDAP_REQ_BIND:
  351. rtag = ber_scanf( &tmpber, "{i" /*}*/, &bint );
  352. break;
  353. case LDAP_REQ_DELETE:
  354. break;
  355. default:
  356. rtag = ber_scanf( &tmpber, "{" /*}*/ );
  357. case LDAP_REQ_ABANDON:
  358. break;
  359. }
  360. if ( tag != LDAP_REQ_ABANDON ) {
  361. ber_skip_tag( &tmpber, &lr->lr_dn.bv_len );
  362. lr->lr_dn.bv_val = tmpber.ber_ptr;
  363. }
  364. }
  365. rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error );
  366. assert( rc == LDAP_SUCCESS );
  367. ld->ld_errno = LDAP_SUCCESS;
  368. if ( ldap_int_flush_request( ld, lr ) == -1 ) {
  369. msgid = -1;
  370. }
  371. LDAP_CONN_UNLOCK_IF(m_noconn);
  372. return( msgid );
  373. }
  374. /* return 0 if no StartTLS ext, 1 if present, 2 if critical */
  375. static int
  376. find_tls_ext( LDAPURLDesc *srv )
  377. {
  378. int i, crit;
  379. char *ext;
  380. if ( !srv->lud_exts )
  381. return 0;
  382. for (i=0; srv->lud_exts[i]; i++) {
  383. crit = 0;
  384. ext = srv->lud_exts[i];
  385. if ( ext[0] == '!') {
  386. ext++;
  387. crit = 1;
  388. }
  389. if ( !strcasecmp( ext, "StartTLS" ) ||
  390. !strcasecmp( ext, "X-StartTLS" ) ||
  391. !strcmp( ext, LDAP_EXOP_START_TLS )) {
  392. return crit + 1;
  393. }
  394. }
  395. return 0;
  396. }
  397. /*
  398. * always protected by conn_mutex
  399. * optionally protected by req_mutex and res_mutex
  400. */
  401. LDAPConn *
  402. ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
  403. int connect, LDAPreqinfo *bind, int m_req, int m_res )
  404. {
  405. LDAPConn *lc;
  406. int async = 0;
  407. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
  408. Debug3( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
  409. use_ldsb, connect, (bind != NULL) );
  410. /*
  411. * make a new LDAP server connection
  412. * XXX open connection synchronously for now
  413. */
  414. lc = (LDAPConn *)LDAP_CALLOC( 1, sizeof( LDAPConn ) );
  415. if ( lc == NULL ) {
  416. ld->ld_errno = LDAP_NO_MEMORY;
  417. return( NULL );
  418. }
  419. if ( use_ldsb ) {
  420. assert( ld->ld_sb != NULL );
  421. lc->lconn_sb = ld->ld_sb;
  422. } else {
  423. lc->lconn_sb = ber_sockbuf_alloc();
  424. if ( lc->lconn_sb == NULL ) {
  425. LDAP_FREE( (char *)lc );
  426. ld->ld_errno = LDAP_NO_MEMORY;
  427. return( NULL );
  428. }
  429. }
  430. if ( connect ) {
  431. LDAPURLDesc **srvp, *srv = NULL;
  432. async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC );
  433. for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
  434. int rc;
  435. rc = ldap_int_open_connection( ld, lc, *srvp, async );
  436. if ( rc != -1 ) {
  437. srv = *srvp;
  438. /* If we fully connected, async is moot */
  439. if ( rc == 0 )
  440. async = 0;
  441. if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) {
  442. ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params );
  443. }
  444. break;
  445. }
  446. }
  447. if ( srv == NULL ) {
  448. if ( !use_ldsb ) {
  449. ber_sockbuf_free( lc->lconn_sb );
  450. }
  451. LDAP_FREE( (char *)lc );
  452. ld->ld_errno = LDAP_SERVER_DOWN;
  453. return( NULL );
  454. }
  455. lc->lconn_server = ldap_url_dup( srv );
  456. if ( !lc->lconn_server ) {
  457. if ( !use_ldsb )
  458. ber_sockbuf_free( lc->lconn_sb );
  459. LDAP_FREE( (char *)lc );
  460. ld->ld_errno = LDAP_NO_MEMORY;
  461. return( NULL );
  462. }
  463. }
  464. lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
  465. lc->lconn_next = ld->ld_conns;
  466. ld->ld_conns = lc;
  467. if ( connect ) {
  468. #ifdef HAVE_TLS
  469. if ( lc->lconn_server->lud_exts ) {
  470. int rc, ext = find_tls_ext( lc->lconn_server );
  471. if ( ext ) {
  472. LDAPConn *savedefconn;
  473. savedefconn = ld->ld_defconn;
  474. ++lc->lconn_refcnt; /* avoid premature free */
  475. ld->ld_defconn = lc;
  476. LDAP_REQ_UNLOCK_IF(m_req);
  477. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  478. LDAP_RES_UNLOCK_IF(m_res);
  479. rc = ldap_start_tls_s( ld, NULL, NULL );
  480. LDAP_RES_LOCK_IF(m_res);
  481. LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
  482. LDAP_REQ_LOCK_IF(m_req);
  483. ld->ld_defconn = savedefconn;
  484. --lc->lconn_refcnt;
  485. if ( rc != LDAP_SUCCESS && ext == 2 ) {
  486. ldap_free_connection( ld, lc, 1, 0 );
  487. return NULL;
  488. }
  489. }
  490. }
  491. #endif
  492. }
  493. if ( bind != NULL ) {
  494. int err = 0;
  495. LDAPConn *savedefconn;
  496. /* Set flag to prevent additional referrals
  497. * from being processed on this
  498. * connection until the bind has completed
  499. */
  500. lc->lconn_rebind_inprogress = 1;
  501. /* V3 rebind function */
  502. if ( ld->ld_rebind_proc != NULL) {
  503. LDAPURLDesc *srvfunc;
  504. srvfunc = ldap_url_dup( *srvlist );
  505. if ( srvfunc == NULL ) {
  506. ld->ld_errno = LDAP_NO_MEMORY;
  507. err = -1;
  508. } else {
  509. savedefconn = ld->ld_defconn;
  510. ++lc->lconn_refcnt; /* avoid premature free */
  511. ld->ld_defconn = lc;
  512. Debug0( LDAP_DEBUG_TRACE, "Call application rebind_proc\n" );
  513. LDAP_REQ_UNLOCK_IF(m_req);
  514. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  515. LDAP_RES_UNLOCK_IF(m_res);
  516. err = (*ld->ld_rebind_proc)( ld,
  517. bind->ri_url, bind->ri_request, bind->ri_msgid,
  518. ld->ld_rebind_params );
  519. LDAP_RES_LOCK_IF(m_res);
  520. LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
  521. LDAP_REQ_LOCK_IF(m_req);
  522. ld->ld_defconn = savedefconn;
  523. --lc->lconn_refcnt;
  524. if ( err != 0 ) {
  525. err = -1;
  526. ldap_free_connection( ld, lc, 1, 0 );
  527. lc = NULL;
  528. }
  529. ldap_free_urldesc( srvfunc );
  530. }
  531. } else {
  532. int msgid, rc;
  533. struct berval passwd = BER_BVNULL;
  534. savedefconn = ld->ld_defconn;
  535. ++lc->lconn_refcnt; /* avoid premature free */
  536. ld->ld_defconn = lc;
  537. Debug0( LDAP_DEBUG_TRACE,
  538. "anonymous rebind via ldap_sasl_bind(\"\")\n" );
  539. LDAP_REQ_UNLOCK_IF(m_req);
  540. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  541. LDAP_RES_UNLOCK_IF(m_res);
  542. rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd,
  543. NULL, NULL, &msgid );
  544. if ( rc != LDAP_SUCCESS ) {
  545. err = -1;
  546. } else {
  547. for ( err = 1; err > 0; ) {
  548. struct timeval tv = { 0, 100000 };
  549. LDAPMessage *res = NULL;
  550. switch ( ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) {
  551. case -1:
  552. err = -1;
  553. break;
  554. case 0:
  555. #ifdef LDAP_R_COMPILE
  556. ldap_pvt_thread_yield();
  557. #endif
  558. break;
  559. case LDAP_RES_BIND:
  560. rc = ldap_parse_result( ld, res, &err, NULL, NULL, NULL, NULL, 1 );
  561. if ( rc != LDAP_SUCCESS ) {
  562. err = -1;
  563. } else if ( err != LDAP_SUCCESS ) {
  564. err = -1;
  565. }
  566. /* else err == LDAP_SUCCESS == 0 */
  567. break;
  568. default:
  569. Debug3( LDAP_DEBUG_TRACE,
  570. "ldap_new_connection %p: "
  571. "unexpected response %d "
  572. "from BIND request id=%d\n",
  573. (void *) ld, ldap_msgtype( res ), msgid );
  574. err = -1;
  575. break;
  576. }
  577. }
  578. }
  579. LDAP_RES_LOCK_IF(m_res);
  580. LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
  581. LDAP_REQ_LOCK_IF(m_req);
  582. ld->ld_defconn = savedefconn;
  583. --lc->lconn_refcnt;
  584. if ( err != 0 ) {
  585. ldap_free_connection( ld, lc, 1, 0 );
  586. lc = NULL;
  587. }
  588. }
  589. if ( lc != NULL )
  590. lc->lconn_rebind_inprogress = 0;
  591. }
  592. return( lc );
  593. }
  594. /* protected by ld_conn_mutex */
  595. static LDAPConn *
  596. find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
  597. /*
  598. * return an existing connection (if any) to the server srv
  599. * if "any" is non-zero, check for any server in the "srv" chain
  600. */
  601. {
  602. LDAPConn *lc;
  603. LDAPURLDesc *lcu, *lsu;
  604. int lcu_port, lsu_port;
  605. int found = 0;
  606. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
  607. for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
  608. lcu = lc->lconn_server;
  609. lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme,
  610. lcu->lud_port );
  611. for ( lsu = srv; lsu != NULL; lsu = lsu->lud_next ) {
  612. lsu_port = ldap_pvt_url_scheme_port( lsu->lud_scheme,
  613. lsu->lud_port );
  614. if ( lsu_port == lcu_port
  615. && strcmp( lcu->lud_scheme, lsu->lud_scheme ) == 0
  616. && lcu->lud_host != NULL && lsu->lud_host != NULL
  617. && strcasecmp( lsu->lud_host, lcu->lud_host ) == 0 )
  618. {
  619. found = 1;
  620. break;
  621. }
  622. if ( !any ) break;
  623. }
  624. if ( found )
  625. break;
  626. }
  627. return lc;
  628. }
  629. /* protected by ld_conn_mutex */
  630. static void
  631. use_connection( LDAP *ld, LDAPConn *lc )
  632. {
  633. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
  634. ++lc->lconn_refcnt;
  635. lc->lconn_lastused = time( NULL );
  636. }
  637. /* protected by ld_conn_mutex */
  638. void
  639. ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
  640. {
  641. LDAPConn *tmplc, *prevlc;
  642. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
  643. Debug2( LDAP_DEBUG_TRACE,
  644. "ldap_free_connection %d %d\n",
  645. force, unbind );
  646. if ( force || --lc->lconn_refcnt <= 0 ) {
  647. /* remove from connections list first */
  648. for ( prevlc = NULL, tmplc = ld->ld_conns;
  649. tmplc != NULL;
  650. tmplc = tmplc->lconn_next )
  651. {
  652. if ( tmplc == lc ) {
  653. if ( prevlc == NULL ) {
  654. ld->ld_conns = tmplc->lconn_next;
  655. } else {
  656. prevlc->lconn_next = tmplc->lconn_next;
  657. }
  658. if ( ld->ld_defconn == lc ) {
  659. ld->ld_defconn = NULL;
  660. }
  661. break;
  662. }
  663. prevlc = tmplc;
  664. }
  665. /* process connection callbacks */
  666. {
  667. struct ldapoptions *lo;
  668. ldaplist *ll;
  669. ldap_conncb *cb;
  670. lo = &ld->ld_options;
  671. LDAP_MUTEX_LOCK( &lo->ldo_mutex );
  672. if ( lo->ldo_conn_cbs ) {
  673. for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
  674. cb = ll->ll_data;
  675. cb->lc_del( ld, lc->lconn_sb, cb );
  676. }
  677. }
  678. LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
  679. lo = LDAP_INT_GLOBAL_OPT();
  680. LDAP_MUTEX_LOCK( &lo->ldo_mutex );
  681. if ( lo->ldo_conn_cbs ) {
  682. for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
  683. cb = ll->ll_data;
  684. cb->lc_del( ld, lc->lconn_sb, cb );
  685. }
  686. }
  687. LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
  688. }
  689. if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
  690. ldap_mark_select_clear( ld, lc->lconn_sb );
  691. if ( unbind ) {
  692. ldap_send_unbind( ld, lc->lconn_sb,
  693. NULL, NULL );
  694. }
  695. }
  696. if ( lc->lconn_ber != NULL ) {
  697. ber_free( lc->lconn_ber, 1 );
  698. }
  699. ldap_int_sasl_close( ld, lc );
  700. ldap_free_urllist( lc->lconn_server );
  701. /* FIXME: is this at all possible?
  702. * ldap_ld_free() in unbind.c calls ldap_free_connection()
  703. * with force == 1 __after__ explicitly calling
  704. * ldap_tavl_free on ld->ld_requests */
  705. if ( force ) {
  706. ldap_tavl_free( ld->ld_requests, ldap_do_free_request );
  707. ld->ld_requests = NULL;
  708. }
  709. if ( lc->lconn_sb != ld->ld_sb ) {
  710. ber_sockbuf_free( lc->lconn_sb );
  711. } else {
  712. ber_int_sb_close( lc->lconn_sb );
  713. }
  714. if ( lc->lconn_rebind_queue != NULL) {
  715. int i;
  716. for( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) {
  717. LDAP_VFREE( lc->lconn_rebind_queue[i] );
  718. }
  719. LDAP_FREE( lc->lconn_rebind_queue );
  720. }
  721. LDAP_FREE( lc );
  722. Debug0( LDAP_DEBUG_TRACE,
  723. "ldap_free_connection: actually freed\n" );
  724. } else {
  725. lc->lconn_lastused = time( NULL );
  726. Debug1( LDAP_DEBUG_TRACE, "ldap_free_connection: refcnt %d\n",
  727. lc->lconn_refcnt );
  728. }
  729. }
  730. /* Protects self with ld_conn_mutex */
  731. #ifdef LDAP_DEBUG
  732. void
  733. ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
  734. {
  735. LDAPConn *lc;
  736. char timebuf[32];
  737. Debug2( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "" );
  738. LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
  739. for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
  740. if ( lc->lconn_server != NULL ) {
  741. Debug3( LDAP_DEBUG_TRACE, "* host: %s port: %d%s\n",
  742. ( lc->lconn_server->lud_host == NULL ) ? "(null)"
  743. : lc->lconn_server->lud_host,
  744. lc->lconn_server->lud_port, ( lc->lconn_sb ==
  745. ld->ld_sb ) ? " (default)" : "" );
  746. }
  747. if ( lc->lconn_sb != NULL ) {
  748. char from[LDAP_IPADDRLEN];
  749. struct berval frombv = BER_BVC(from);
  750. ber_socket_t sb;
  751. if ( ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sb ) == 1 ) {
  752. Sockaddr sin;
  753. socklen_t len = sizeof( sin );
  754. if ( getsockname( sb, (struct sockaddr *)&sin, &len ) == 0 ) {
  755. ldap_pvt_sockaddrstr( &sin, &frombv );
  756. Debug1( LDAP_DEBUG_TRACE, "* from: %s\n",
  757. ( from == NULL ) ? "(null)" : from );
  758. }
  759. }
  760. }
  761. Debug2( LDAP_DEBUG_TRACE, " refcnt: %d status: %s\n", lc->lconn_refcnt,
  762. ( lc->lconn_status == LDAP_CONNST_NEEDSOCKET )
  763. ? "NeedSocket" :
  764. ( lc->lconn_status == LDAP_CONNST_CONNECTING )
  765. ? "Connecting" : "Connected" );
  766. Debug2( LDAP_DEBUG_TRACE, " last used: %s%s\n",
  767. ldap_pvt_ctime( &lc->lconn_lastused, timebuf ),
  768. lc->lconn_rebind_inprogress ? " rebind in progress" : "" );
  769. if ( lc->lconn_rebind_inprogress ) {
  770. if ( lc->lconn_rebind_queue != NULL) {
  771. int i;
  772. for ( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) {
  773. int j;
  774. for( j = 0; lc->lconn_rebind_queue[i][j] != 0; j++ ) {
  775. Debug3( LDAP_DEBUG_TRACE, " queue %d entry %d - %s\n",
  776. i, j, lc->lconn_rebind_queue[i][j] );
  777. }
  778. }
  779. } else {
  780. Debug0( LDAP_DEBUG_TRACE, " queue is empty\n" );
  781. }
  782. }
  783. Debug0( LDAP_DEBUG_TRACE, "\n" );
  784. if ( !all ) {
  785. break;
  786. }
  787. }
  788. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  789. }
  790. /* protected by req_mutex and res_mutex */
  791. void
  792. ldap_dump_requests_and_responses( LDAP *ld )
  793. {
  794. LDAPMessage *lm, *l;
  795. TAvlnode *node;
  796. int i;
  797. Debug1( LDAP_DEBUG_TRACE, "** ld %p Outstanding Requests:\n",
  798. (void *)ld );
  799. node = ldap_tavl_end( ld->ld_requests, TAVL_DIR_LEFT );
  800. if ( node == NULL ) {
  801. Debug0( LDAP_DEBUG_TRACE, " Empty\n" );
  802. }
  803. for ( i = 0 ; node != NULL; i++, node = ldap_tavl_next( node, TAVL_DIR_RIGHT ) ) {
  804. LDAPRequest *lr = node->avl_data;
  805. Debug3( LDAP_DEBUG_TRACE, " * msgid %d, origid %d, status %s\n",
  806. lr->lr_msgid, lr->lr_origid,
  807. ( lr->lr_status == LDAP_REQST_INPROGRESS ) ? "InProgress" :
  808. ( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" :
  809. ( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" :
  810. ( lr->lr_status == LDAP_REQST_WRITING ) ? "Writing" :
  811. ( lr->lr_status == LDAP_REQST_COMPLETED ) ? "RequestCompleted"
  812. : "InvalidStatus" );
  813. Debug2( LDAP_DEBUG_TRACE, " outstanding referrals %d, parent count %d\n",
  814. lr->lr_outrefcnt, lr->lr_parentcnt );
  815. }
  816. Debug3( LDAP_DEBUG_TRACE, " ld %p request count %d (abandoned %lu)\n",
  817. (void *)ld, i, ld->ld_nabandoned );
  818. Debug1( LDAP_DEBUG_TRACE, "** ld %p Response Queue:\n", (void *)ld );
  819. if ( ( lm = ld->ld_responses ) == NULL ) {
  820. Debug0( LDAP_DEBUG_TRACE, " Empty\n" );
  821. }
  822. for ( i = 0; lm != NULL; lm = lm->lm_next, i++ ) {
  823. Debug2( LDAP_DEBUG_TRACE, " * msgid %d, type %lu\n",
  824. lm->lm_msgid, (unsigned long)lm->lm_msgtype );
  825. if ( lm->lm_chain != NULL ) {
  826. Debug0( LDAP_DEBUG_TRACE, " chained responses:\n" );
  827. for ( l = lm->lm_chain; l != NULL; l = l->lm_chain ) {
  828. Debug2( LDAP_DEBUG_TRACE,
  829. " * msgid %d, type %lu\n",
  830. l->lm_msgid,
  831. (unsigned long)l->lm_msgtype );
  832. }
  833. }
  834. }
  835. Debug2( LDAP_DEBUG_TRACE, " ld %p response count %d\n", (void *)ld, i );
  836. }
  837. #endif /* LDAP_DEBUG */
  838. /* protected by req_mutex */
  839. void
  840. ldap_do_free_request( void *arg )
  841. {
  842. LDAPRequest *lr = arg;
  843. Debug3( LDAP_DEBUG_TRACE, "ldap_do_free_request: "
  844. "asked to free lr %p msgid %d refcnt %d\n",
  845. (void *) lr, lr->lr_msgid, lr->lr_refcnt );
  846. /* if lr_refcnt > 0, the request has been looked up
  847. * by ldap_find_request_by_msgid(); if in the meanwhile
  848. * the request is free()'d by someone else, just decrease
  849. * the reference count; later on, it will be freed. */
  850. if ( lr->lr_refcnt > 0 ) {
  851. assert( lr->lr_refcnt == 1 );
  852. lr->lr_refcnt = -lr->lr_refcnt;
  853. return;
  854. }
  855. if ( lr->lr_ber != NULL ) {
  856. ber_free( lr->lr_ber, 1 );
  857. lr->lr_ber = NULL;
  858. }
  859. if ( lr->lr_res_error != NULL ) {
  860. LDAP_FREE( lr->lr_res_error );
  861. lr->lr_res_error = NULL;
  862. }
  863. if ( lr->lr_res_matched != NULL ) {
  864. LDAP_FREE( lr->lr_res_matched );
  865. lr->lr_res_matched = NULL;
  866. }
  867. LDAP_FREE( lr );
  868. }
  869. int
  870. ldap_req_cmp( const void *l, const void *r )
  871. {
  872. const LDAPRequest *left = l, *right = r;
  873. return left->lr_msgid - right->lr_msgid;
  874. }
  875. /* protected by req_mutex */
  876. static void
  877. ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
  878. {
  879. LDAPRequest *removed;
  880. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
  881. removed = ldap_tavl_delete( &ld->ld_requests, lr, ldap_req_cmp );
  882. assert( !removed || removed == lr );
  883. Debug3( LDAP_DEBUG_TRACE, "ldap_free_request_int: "
  884. "lr %p msgid %d%s removed\n",
  885. (void *) lr, lr->lr_msgid, removed ? "" : " not" );
  886. ldap_do_free_request( lr );
  887. }
  888. /* protected by req_mutex */
  889. void
  890. ldap_free_request( LDAP *ld, LDAPRequest *lr )
  891. {
  892. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
  893. Debug2( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n",
  894. lr->lr_origid, lr->lr_msgid );
  895. /* free all referrals (child requests) */
  896. while ( lr->lr_child ) {
  897. ldap_free_request( ld, lr->lr_child );
  898. }
  899. if ( lr->lr_parent != NULL ) {
  900. LDAPRequest **lrp;
  901. --lr->lr_parent->lr_outrefcnt;
  902. for ( lrp = &lr->lr_parent->lr_child;
  903. *lrp && *lrp != lr;
  904. lrp = &(*lrp)->lr_refnext );
  905. if ( *lrp == lr ) {
  906. *lrp = lr->lr_refnext;
  907. }
  908. }
  909. ldap_free_request_int( ld, lr );
  910. }
  911. /*
  912. * call first time with *cntp = -1
  913. * when returns *cntp == -1, no referrals are left
  914. *
  915. * NOTE: may replace *refsp, or shuffle the contents
  916. * of the original array.
  917. */
  918. static int ldap_int_nextref(
  919. LDAP *ld,
  920. char ***refsp,
  921. int *cntp,
  922. void *params )
  923. {
  924. assert( refsp != NULL );
  925. assert( *refsp != NULL );
  926. assert( cntp != NULL );
  927. if ( *cntp < -1 ) {
  928. *cntp = -1;
  929. return -1;
  930. }
  931. (*cntp)++;
  932. if ( (*refsp)[ *cntp ] == NULL ) {
  933. *cntp = -1;
  934. }
  935. return 0;
  936. }
  937. /*
  938. * Chase v3 referrals
  939. *
  940. * Parameters:
  941. * (IN) ld = LDAP connection handle
  942. * (IN) lr = LDAP Request structure
  943. * (IN) refs = array of pointers to referral strings that we will chase
  944. * The array will be free'd by this function when no longer needed
  945. * (IN) sref != 0 if following search reference
  946. * (OUT) errstrp = Place to return a string of referrals which could not be followed
  947. * (OUT) hadrefp = 1 if successfully followed referral
  948. *
  949. * Return value - number of referrals followed
  950. *
  951. * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
  952. */
  953. int
  954. ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp )
  955. {
  956. char *unfollowed;
  957. int unfollowedcnt = 0;
  958. LDAPRequest *origreq;
  959. LDAPURLDesc *srv = NULL;
  960. BerElement *ber;
  961. char **refarray = NULL;
  962. LDAPConn *lc;
  963. int rc, count, i, j, id;
  964. LDAPreqinfo rinfo;
  965. LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref;
  966. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
  967. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
  968. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
  969. Debug0( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n" );
  970. ld->ld_errno = LDAP_SUCCESS; /* optimistic */
  971. *hadrefp = 0;
  972. unfollowed = NULL;
  973. rc = count = 0;
  974. /* If no referrals in array, return */
  975. if ( (refs == NULL) || ( (refs)[0] == NULL) ) {
  976. rc = 0;
  977. goto done;
  978. }
  979. /* Check for hop limit exceeded */
  980. if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) {
  981. Debug1( LDAP_DEBUG_ANY,
  982. "more than %d referral hops (dropping)\n", ld->ld_refhoplimit );
  983. ld->ld_errno = LDAP_REFERRAL_LIMIT_EXCEEDED;
  984. rc = -1;
  985. goto done;
  986. }
  987. /* find original request */
  988. for ( origreq = lr;
  989. origreq->lr_parent != NULL;
  990. origreq = origreq->lr_parent )
  991. {
  992. /* empty */ ;
  993. }
  994. refarray = refs;
  995. refs = NULL;
  996. /* parse out & follow referrals */
  997. /* NOTE: if nextref_proc == ldap_int_nextref, params is ignored */
  998. i = -1;
  999. for ( nextref_proc( ld, &refarray, &i, ld->ld_nextref_params );
  1000. i != -1;
  1001. nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ) )
  1002. {
  1003. /* Parse the referral URL */
  1004. rc = ldap_url_parse_ext( refarray[i], &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN );
  1005. if ( rc != LDAP_URL_SUCCESS ) {
  1006. /* ldap_url_parse_ext() returns LDAP_URL_* errors
  1007. * which do not map on API errors */
  1008. ld->ld_errno = LDAP_PARAM_ERROR;
  1009. rc = -1;
  1010. goto done;
  1011. }
  1012. if( srv->lud_crit_exts ) {
  1013. int ok = 0;
  1014. #ifdef HAVE_TLS
  1015. /* If StartTLS is the only critical ext, OK. */
  1016. if ( find_tls_ext( srv ) == 2 && srv->lud_crit_exts == 1 )
  1017. ok = 1;
  1018. #endif
  1019. if ( !ok ) {
  1020. /* we do not support any other extensions */
  1021. ld->ld_errno = LDAP_NOT_SUPPORTED;
  1022. rc = -1;
  1023. goto done;
  1024. }
  1025. }
  1026. /* check connection for re-bind in progress */
  1027. if (( lc = find_connection( ld, srv, 1 )) != NULL ) {
  1028. /* See if we've already requested this DN with this conn */
  1029. LDAPRequest *lp;
  1030. int looped = 0;
  1031. ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0;
  1032. for ( lp = origreq; lp; ) {
  1033. if ( lp->lr_conn == lc
  1034. && len == lp->lr_dn.bv_len
  1035. && len
  1036. && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) == 0 )
  1037. {
  1038. looped = 1;
  1039. break;
  1040. }
  1041. if ( lp == origreq ) {
  1042. lp = lp->lr_child;
  1043. } else {
  1044. lp = lp->lr_refnext;
  1045. }
  1046. }
  1047. if ( looped ) {
  1048. ldap_free_urllist( srv );
  1049. srv = NULL;
  1050. ld->ld_errno = LDAP_CLIENT_LOOP;
  1051. rc = -1;
  1052. continue;
  1053. }
  1054. if ( lc->lconn_rebind_inprogress ) {
  1055. /* We are already chasing a referral or search reference and a
  1056. * bind on that connection is in progress. We must queue
  1057. * referrals on that connection, so we don't get a request
  1058. * going out before the bind operation completes. This happens
  1059. * if two search references come in one behind the other
  1060. * for the same server with different contexts.
  1061. */
  1062. Debug1( LDAP_DEBUG_TRACE,
  1063. "ldap_chase_v3referrals: queue referral \"%s\"\n",
  1064. refarray[i] );
  1065. if( lc->lconn_rebind_queue == NULL ) {
  1066. /* Create a referral list */
  1067. lc->lconn_rebind_queue =
  1068. (char ***) LDAP_MALLOC( sizeof(void *) * 2);
  1069. if( lc->lconn_rebind_queue == NULL) {
  1070. ld->ld_errno = LDAP_NO_MEMORY;
  1071. rc = -1;
  1072. goto done;
  1073. }
  1074. lc->lconn_rebind_queue[0] = refarray;
  1075. lc->lconn_rebind_queue[1] = NULL;
  1076. refarray = NULL;
  1077. } else {
  1078. /* Count how many referral arrays we already have */
  1079. for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++) {
  1080. /* empty */;
  1081. }
  1082. /* Add the new referral to the list */
  1083. lc->lconn_rebind_queue = (char ***) LDAP_REALLOC(
  1084. lc->lconn_rebind_queue, sizeof(void *) * (j + 2));
  1085. if( lc->lconn_rebind_queue == NULL ) {
  1086. ld->ld_errno = LDAP_NO_MEMORY;
  1087. rc = -1;
  1088. goto done;
  1089. }
  1090. lc->lconn_rebind_queue[j] = refarray;
  1091. lc->lconn_rebind_queue[j+1] = NULL;
  1092. refarray = NULL;
  1093. }
  1094. /* We have queued the referral/reference, now just return */
  1095. rc = 0;
  1096. *hadrefp = 1;
  1097. count = 1; /* Pretend we already followed referral */
  1098. goto done;
  1099. }
  1100. }
  1101. /* Re-encode the request with the new starting point of the search.
  1102. * Note: In the future we also need to replace the filter if one
  1103. * was provided with the search reference
  1104. */
  1105. /* For references we don't want old dn if new dn empty */
  1106. if ( sref && srv->lud_dn == NULL ) {
  1107. srv->lud_dn = LDAP_STRDUP( "" );
  1108. }
  1109. LDAP_NEXT_MSGID( ld, id );
  1110. ber = re_encode_request( ld, origreq->lr_ber, id,
  1111. sref, srv, &rinfo.ri_request );
  1112. if( ber == NULL ) {
  1113. ld->ld_errno = LDAP_ENCODING_ERROR;
  1114. rc = -1;
  1115. goto done;
  1116. }
  1117. Debug2( LDAP_DEBUG_TRACE,
  1118. "ldap_chase_v3referral: msgid %d, url \"%s\"\n",
  1119. lr->lr_msgid, refarray[i] );
  1120. /* Send the new request to the server - may require a bind */
  1121. rinfo.ri_msgid = origreq->lr_origid;
  1122. rinfo.ri_url = refarray[i];
  1123. rc = ldap_send_server_request( ld, ber, id,
  1124. origreq, &srv, NULL, &rinfo, 0, 1 );
  1125. if ( rc < 0 ) {
  1126. /* Failure, try next referral in the list */
  1127. Debug3( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n",
  1128. refarray[i], ld->ld_errno, ldap_err2string( ld->ld_errno ) );
  1129. unfollowedcnt += ldap_append_referral( ld, &unfollowed, refarray[i] );
  1130. ldap_free_urllist( srv );
  1131. srv = NULL;
  1132. ld->ld_errno = LDAP_REFERRAL;
  1133. } else {
  1134. /* Success, no need to try this referral list further */
  1135. rc = 0;
  1136. ++count;
  1137. *hadrefp = 1;
  1138. /* check if there is a queue of referrals that came in during bind */
  1139. if ( lc == NULL) {
  1140. lc = find_connection( ld, srv, 1 );
  1141. if ( lc == NULL ) {
  1142. ld->ld_errno = LDAP_OPERATIONS_ERROR;
  1143. rc = -1;
  1144. LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
  1145. goto done;
  1146. }
  1147. }
  1148. if ( lc->lconn_rebind_queue != NULL ) {
  1149. /* Release resources of previous list */
  1150. LDAP_VFREE( refarray );
  1151. refarray = NULL;
  1152. ldap_free_urllist( srv );
  1153. srv = NULL;
  1154. /* Pull entries off end of queue so list always null terminated */
  1155. for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++ )
  1156. ;
  1157. refarray = lc->lconn_rebind_queue[j - 1];
  1158. lc->lconn_rebind_queue[j-1] = NULL;
  1159. /* we pulled off last entry from queue, free queue */
  1160. if ( j == 1 ) {
  1161. LDAP_FREE( lc->lconn_rebind_queue );
  1162. lc->lconn_rebind_queue = NULL;
  1163. }
  1164. /* restart the loop the with new referral list */
  1165. i = -1;
  1166. continue;
  1167. }
  1168. break; /* referral followed, break out of for loop */
  1169. }
  1170. } /* end for loop */
  1171. done:
  1172. LDAP_VFREE( refarray );
  1173. ldap_free_urllist( srv );
  1174. LDAP_FREE( *errstrp );
  1175. if( rc == 0 ) {
  1176. *errstrp = NULL;
  1177. LDAP_FREE( unfollowed );
  1178. return count;
  1179. } else {
  1180. *errstrp = unfollowed;
  1181. return rc;
  1182. }
  1183. }
  1184. /*
  1185. * XXX merging of errors in this routine needs to be improved
  1186. * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
  1187. */
  1188. int
  1189. ldap_chase_referrals( LDAP *ld,
  1190. LDAPRequest *lr,
  1191. char **errstrp,
  1192. int sref,
  1193. int *hadrefp )
  1194. {
  1195. int rc, count, id;
  1196. unsigned len;
  1197. char *p, *ref, *unfollowed;
  1198. LDAPRequest *origreq;
  1199. LDAPURLDesc *srv;
  1200. BerElement *ber;
  1201. LDAPreqinfo rinfo;
  1202. LDAPConn *lc;
  1203. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
  1204. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
  1205. LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
  1206. Debug0( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n" );
  1207. ld->ld_errno = LDAP_SUCCESS; /* optimistic */
  1208. *hadrefp = 0;
  1209. if ( *errstrp == NULL ) {
  1210. return( 0 );
  1211. }
  1212. len = strlen( *errstrp );
  1213. for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) {
  1214. if ( strncasecmp( p, LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) {
  1215. *p = '\0';
  1216. p += LDAP_REF_STR_LEN;
  1217. break;
  1218. }
  1219. }
  1220. if ( len < LDAP_REF_STR_LEN ) {
  1221. return( 0 );
  1222. }
  1223. if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) {
  1224. Debug1( LDAP_DEBUG_ANY,
  1225. "more than %d referral hops (dropping)\n",
  1226. ld->ld_refhoplimit );
  1227. /* XXX report as error in ld->ld_errno? */
  1228. return( 0 );
  1229. }
  1230. /* find original request */
  1231. for ( origreq = lr; origreq->lr_parent != NULL;
  1232. origreq = origreq->lr_parent ) {
  1233. /* empty */;
  1234. }
  1235. unfollowed = NULL;
  1236. rc = count = 0;
  1237. /* parse out & follow referrals */
  1238. for ( ref = p; rc == 0 && ref != NULL; ref = p ) {
  1239. p = strchr( ref, '\n' );
  1240. if ( p != NULL ) {
  1241. *p++ = '\0';
  1242. }
  1243. rc = ldap_url_parse_ext( ref, &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN );
  1244. if ( rc != LDAP_URL_SUCCESS ) {
  1245. Debug2( LDAP_DEBUG_TRACE,
  1246. "ignoring %s referral <%s>\n",
  1247. ref, rc == LDAP_URL_ERR_BADSCHEME ? "unknown" : "incorrect" );
  1248. rc = ldap_append_referral( ld, &unfollowed, ref );
  1249. *hadrefp = 1;
  1250. continue;
  1251. }
  1252. Debug1( LDAP_DEBUG_TRACE,
  1253. "chasing LDAP referral: <%s>\n", ref );
  1254. *hadrefp = 1;
  1255. /* See if we've already been here */
  1256. if (( lc = find_connection( ld, srv, 1 )) != NULL ) {
  1257. LDAPRequest *lp;
  1258. int looped = 0;
  1259. ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0;
  1260. for ( lp = lr; lp; lp = lp->lr_parent ) {
  1261. if ( lp->lr_conn == lc
  1262. && len == lp->lr_dn.bv_len )
  1263. {
  1264. if ( len && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) )
  1265. continue;
  1266. looped = 1;
  1267. break;
  1268. }
  1269. }
  1270. if ( looped ) {
  1271. ldap_free_urllist( srv );
  1272. ld->ld_errno = LDAP_CLIENT_LOOP;
  1273. rc = -1;
  1274. continue;
  1275. }
  1276. }
  1277. LDAP_NEXT_MSGID( ld, id );
  1278. ber = re_encode_request( ld, origreq->lr_ber,
  1279. id, sref, srv, &rinfo.ri_request );
  1280. if ( ber == NULL ) {
  1281. ldap_free_urllist( srv );
  1282. return -1 ;
  1283. }
  1284. /* copy the complete referral for rebind process */
  1285. rinfo.ri_url = LDAP_STRDUP( ref );
  1286. rinfo.ri_msgid = origreq->lr_origid;
  1287. rc = ldap_send_server_request( ld, ber, id,
  1288. lr, &srv, NULL, &rinfo, 0, 1 );
  1289. LDAP_FREE( rinfo.ri_url );
  1290. if( rc >= 0 ) {
  1291. ++count;
  1292. } else {
  1293. Debug3( LDAP_DEBUG_ANY,
  1294. "Unable to chase referral \"%s\" (%d: %s)\n",
  1295. ref, ld->ld_errno, ldap_err2string( ld->ld_errno ) );
  1296. rc = ldap_append_referral( ld, &unfollowed, ref );
  1297. }
  1298. ldap_free_urllist(srv);
  1299. }
  1300. LDAP_FREE( *errstrp );
  1301. *errstrp = unfollowed;
  1302. return(( rc == 0 ) ? count : rc );
  1303. }
  1304. int
  1305. ldap_append_referral( LDAP *ld, char **referralsp, char *s )
  1306. {
  1307. int first;
  1308. if ( *referralsp == NULL ) {
  1309. first = 1;
  1310. *referralsp = (char *)LDAP_MALLOC( strlen( s ) + LDAP_REF_STR_LEN
  1311. + 1 );
  1312. } else {
  1313. first = 0;
  1314. *referralsp = (char *)LDAP_REALLOC( *referralsp,
  1315. strlen( *referralsp ) + strlen( s ) + 2 );
  1316. }
  1317. if ( *referralsp == NULL ) {
  1318. ld->ld_errno = LDAP_NO_MEMORY;
  1319. return( -1 );
  1320. }
  1321. if ( first ) {
  1322. strcpy( *referralsp, LDAP_REF_STR );
  1323. } else {
  1324. strcat( *referralsp, "\n" );
  1325. }
  1326. strcat( *referralsp, s );
  1327. return( 0 );
  1328. }
  1329. static BerElement *
  1330. re_encode_request( LDAP *ld,
  1331. BerElement *origber,
  1332. ber_int_t msgid,
  1333. int sref,
  1334. LDAPURLDesc *srv,
  1335. int *type )
  1336. {
  1337. /*
  1338. * XXX this routine knows way too much about how the lber library works!
  1339. */
  1340. ber_int_t along;
  1341. ber_tag_t tag;
  1342. ber_tag_t rtag;
  1343. ber_int_t ver;
  1344. ber_int_t scope;
  1345. int rc;
  1346. BerElement tmpber, *ber;
  1347. struct berval dn;
  1348. Debug2( LDAP_DEBUG_TRACE,
  1349. "re_encode_request: new msgid %ld, new dn <%s>\n",
  1350. (long) msgid,
  1351. ( srv == NULL || srv->lud_dn == NULL) ? "NONE" : srv->lud_dn );
  1352. tmpber = *origber;
  1353. /*
  1354. * all LDAP requests are sequences that start with a message id.
  1355. * For all except delete, this is followed by a sequence that is
  1356. * tagged with the operation code. For delete, the provided DN
  1357. * is not wrapped by a sequence.
  1358. */
  1359. rtag = ber_scanf( &tmpber, "{it", /*}*/ &along, &tag );
  1360. if ( rtag == LBER_ERROR ) {
  1361. ld->ld_errno = LDAP_DECODING_ERROR;
  1362. return( NULL );
  1363. }
  1364. assert( tag != 0);
  1365. if ( tag == LDAP_REQ_BIND ) {
  1366. /* bind requests have a version number before the DN & other stuff */
  1367. rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &dn );
  1368. } else if ( tag == LDAP_REQ_DELETE ) {
  1369. /* delete requests don't have a DN wrapping sequence */
  1370. rtag = ber_scanf( &tmpber, "m", &dn );
  1371. } else if ( tag == LDAP_REQ_SEARCH ) {
  1372. /* search requests need to be re-scope-ed */
  1373. rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &dn, &scope );
  1374. if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
  1375. /* use the scope provided in reference */
  1376. scope = srv->lud_scope;
  1377. } else if ( sref ) {
  1378. /* use scope implied by previous operation
  1379. * base -> base
  1380. * one -> base
  1381. * subtree -> subtree
  1382. * subordinate -> subtree
  1383. */
  1384. switch( scope ) {
  1385. default:
  1386. case LDAP_SCOPE_BASE:
  1387. case LDAP_SCOPE_ONELEVEL:
  1388. scope = LDAP_SCOPE_BASE;
  1389. break;
  1390. case LDAP_SCOPE_SUBTREE:
  1391. case LDAP_SCOPE_SUBORDINATE:
  1392. scope = LDAP_SCOPE_SUBTREE;
  1393. break;
  1394. }
  1395. }
  1396. } else {
  1397. rtag = ber_scanf( &tmpber, "{m" /*}*/, &dn );
  1398. }
  1399. if( rtag == LBER_ERROR ) {
  1400. ld->ld_errno = LDAP_DECODING_ERROR;
  1401. return NULL;
  1402. }
  1403. /* restore character zero'd out by ber_scanf*/
  1404. dn.bv_val[dn.bv_len] = tmpber.ber_tag;
  1405. if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
  1406. return NULL;
  1407. }
  1408. if ( srv->lud_dn ) {
  1409. ber_str2bv( srv->lud_dn, 0, 0, &dn );
  1410. }
  1411. if ( tag == LDAP_REQ_BIND ) {
  1412. rc = ber_printf( ber, "{it{iO" /*}}*/, msgid, tag, ver, &dn );
  1413. } else if ( tag == LDAP_REQ_DELETE ) {
  1414. rc = ber_printf( ber, "{itON}", msgid, tag, &dn );
  1415. } else if ( tag == LDAP_REQ_SEARCH ) {
  1416. rc = ber_printf( ber, "{it{Oe" /*}}*/, msgid, tag, &dn, scope );
  1417. } else {
  1418. rc = ber_printf( ber, "{it{O" /*}}*/, msgid, tag, &dn );
  1419. }
  1420. if ( rc == -1 ) {
  1421. ld->ld_errno = LDAP_ENCODING_ERROR;
  1422. ber_free( ber, 1 );
  1423. return NULL;
  1424. }
  1425. if ( tag != LDAP_REQ_DELETE && (
  1426. ber_write(ber, tmpber.ber_ptr, ( tmpber.ber_end - tmpber.ber_ptr ), 0)
  1427. != ( tmpber.ber_end - tmpber.ber_ptr ) ||
  1428. ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) )
  1429. {
  1430. ld->ld_errno = LDAP_ENCODING_ERROR;
  1431. ber_free( ber, 1 );
  1432. return NULL;
  1433. }
  1434. #ifdef LDAP_DEBUG
  1435. if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
  1436. Debug0( LDAP_DEBUG_ANY, "re_encode_request new request is:\n" );
  1437. ber_log_dump( LDAP_DEBUG_BER, ldap_debug, ber, 0 );
  1438. }
  1439. #endif /* LDAP_DEBUG */
  1440. *type = tag; /* return request type */
  1441. return ber;
  1442. }
  1443. /* protected by req_mutex */
  1444. LDAPRequest *
  1445. ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
  1446. {
  1447. LDAPRequest *lr, needle = {0};
  1448. needle.lr_msgid = msgid;
  1449. lr = ldap_tavl_find( ld->ld_requests, &needle, ldap_req_cmp );
  1450. if ( lr != NULL && lr->lr_status != LDAP_REQST_COMPLETED ) {
  1451. /* lr_refcnt is only negative when we removed it from ld_requests
  1452. * already, it is positive if we have sub-requests (referrals) */
  1453. assert( lr->lr_refcnt >= 0 );
  1454. lr->lr_refcnt++;
  1455. Debug3( LDAP_DEBUG_TRACE, "ldap_find_request_by_msgid: "
  1456. "msgid %d, lr %p lr->lr_refcnt = %d\n",
  1457. msgid, (void *) lr, lr->lr_refcnt );
  1458. return lr;
  1459. }
  1460. Debug2( LDAP_DEBUG_TRACE, "ldap_find_request_by_msgid: "
  1461. "msgid %d, lr %p\n", msgid, (void *) lr );
  1462. return NULL;
  1463. }
  1464. /* protected by req_mutex */
  1465. void
  1466. ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
  1467. {
  1468. LDAPRequest *lr;
  1469. lr = ldap_tavl_find( ld->ld_requests, lrx, ldap_req_cmp );
  1470. Debug2( LDAP_DEBUG_TRACE, "ldap_return_request: "
  1471. "lrx %p, lr %p\n", (void *) lrx, (void *) lr );
  1472. if ( lr ) {
  1473. assert( lr == lrx );
  1474. if ( lr->lr_refcnt > 0 ) {
  1475. lr->lr_refcnt--;
  1476. } else if ( lr->lr_refcnt < 0 ) {
  1477. lr->lr_refcnt++;
  1478. if ( lr->lr_refcnt == 0 ) {
  1479. lr = NULL;
  1480. }
  1481. }
  1482. }
  1483. Debug3( LDAP_DEBUG_TRACE, "ldap_return_request: "
  1484. "lrx->lr_msgid %d, lrx->lr_refcnt is now %d, lr is %s present\n",
  1485. lrx->lr_msgid, lrx->lr_refcnt, lr ? "still" : "not" );
  1486. /* The request is not tracked anymore */
  1487. if ( lr == NULL ) {
  1488. ldap_free_request_int( ld, lrx );
  1489. } else if ( freeit ) {
  1490. ldap_free_request( ld, lrx );
  1491. }
  1492. }