request.c 36.4 KB
Newer Older
1
/* $OpenLDAP$ */
2
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2007 The OpenLDAP Foundation.
5
6
7
8
9
10
11
12
13
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
14
 */
15
16
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
17
 */
18
/* This notice applies to changes, created by or for Novell, Inc.,
19
20
21
22
23
24
25
26
27
28
29
30
 * to preexisting works for which notices appear elsewhere in this file.
 *
 * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
 *
 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
 * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
 * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
 * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
 * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
 * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
 * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
 * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. 
31
 *---
32
33
 * Modification to OpenLDAP source by Novell, Inc.
 * April 2000 sfs  Added code to chase V3 referrals
Kurt Zeilenga's avatar
Kurt Zeilenga committed
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
38
39
 * can be found in the file "build/LICENSE-2.0.1" in this distribution
 * of OpenLDAP Software.
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
40

41
#include "portable.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
42
43

#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
44
45

#include <ac/stdlib.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
46

47
48
49
50
51
52
#include <ac/errno.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>

Kurt Zeilenga's avatar
Kurt Zeilenga committed
53
#include "ldap-int.h"
54
#include "lber.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
55

56
static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any ));
57
static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc ));
Pierangelo Masarati's avatar
Pierangelo Masarati committed
58
static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr ));
Kurt Zeilenga's avatar
Kurt Zeilenga committed
59

60
61
static BerElement *
re_encode_request( LDAP *ld,
62
	BerElement *origber,
63
	ber_int_t msgid,
64
	int sref,
65
66
	LDAPURLDesc *srv,
	int *type );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
67
68

BerElement *
69
ldap_alloc_ber_with_options( LDAP *ld )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
70
71
72
{
	BerElement	*ber;

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
73
74
	ber = ber_alloc_t( ld->ld_lberoptions );
	if ( ber == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
75
76
77
78
79
80
81
82
		ld->ld_errno = LDAP_NO_MEMORY;
	}

	return( ber );
}


void
83
ldap_set_ber_options( LDAP *ld, BerElement *ber )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
84
85
86
87
88
{
	ber->ber_options = ld->ld_lberoptions;
}


89
ber_int_t
Kurt Zeilenga's avatar
Kurt Zeilenga committed
90
91
ldap_send_initial_request(
	LDAP *ld,
92
	ber_tag_t msgtype,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
93
	const char *dn,
94
95
	BerElement *ber,
	ber_int_t msgid)
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
{
Howard Chu's avatar
Howard Chu committed
97
	int rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
98

99
	Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
100

Howard Chu's avatar
Howard Chu committed
101
102
103
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
104
	if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
105
		/* not connected yet */
Howard Chu's avatar
Howard Chu committed
106
		rc = ldap_open_defconn( ld );
107

Howard Chu's avatar
Howard Chu committed
108
109
110
111
112
113
114
115
	}
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
	if( rc < 0 ) {
		ber_free( ber, 1 );
		return( -1 );
	} else if ( rc == 0 ) {
116
		Debug( LDAP_DEBUG_TRACE,
117
118
			"ldap_open_defconn: successful\n",
			0, 0, 0 );
119
120
	}

121
122
123
124
125
126
127
128
129
130
131
132
#ifdef LDAP_CONNECTIONLESS
	if (LDAP_IS_UDP(ld)) {
		if (msgtype == LDAP_REQ_BIND) {
			if (ld->ld_options.ldo_cldapdn)
				ldap_memfree(ld->ld_options.ldo_cldapdn);
			ld->ld_options.ldo_cldapdn = ldap_strdup(dn);
			return 0;
		}
		if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH)
			return LDAP_PARAM_ERROR;
	}
#endif
133
134
135
136
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
	rc = ldap_send_server_request( ld, ber, msgid, NULL,
Howard Chu's avatar
Howard Chu committed
137
		NULL, NULL, NULL );
138
139
140
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
141
	return(rc);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
142
143
144
}


145
146
147
int
ldap_int_flush_request(
	LDAP *ld,
148
	LDAPRequest *lr )
149
150
151
{
	LDAPConn *lc = lr->lr_conn;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
152
	if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) {
153
		if ( sock_errno() == EAGAIN ) {
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
			/* need to continue write later */
			lr->lr_status = LDAP_REQST_WRITING;
			ldap_mark_select_write( ld, lc->lconn_sb );
			ld->ld_errno = LDAP_BUSY;
			return -2;
		} else {
			ld->ld_errno = LDAP_SERVER_DOWN;
			ldap_free_request( ld, lr );
			ldap_free_connection( ld, lc, 0, 0 );
			return( -1 );
		}
	} else {
		if ( lr->lr_parent == NULL ) {
			lr->lr_ber->ber_end = lr->lr_ber->ber_ptr;
			lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf;
		}
		lr->lr_status = LDAP_REQST_INPROGRESS;

		/* sent -- waiting for a response */
		ldap_mark_select_read( ld, lc->lconn_sb );
	}
	return 0;
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
177
178

int
179
180
181
182
183
ldap_send_server_request(
	LDAP *ld,
	BerElement *ber,
	ber_int_t msgid,
	LDAPRequest *parentreq,
184
	LDAPURLDesc **srvlist,
185
	LDAPConn *lc,
186
	LDAPreqinfo *bind )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
187
188
{
	LDAPRequest	*lr;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
189
	int		incparent, rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
190

191
	Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
192

193
	incparent = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
194
195
196
197
198
199
	ld->ld_errno = LDAP_SUCCESS;	/* optimistic */

	if ( lc == NULL ) {
		if ( srvlist == NULL ) {
			lc = ld->ld_defconn;
		} else {
200
			lc = find_connection( ld, *srvlist, 1 );
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
201
			if ( lc == NULL ) {
202
				if ( (bind != NULL) && (parentreq != NULL) ) {
203
204
205
206
					/* Remember the bind in the parent */
					incparent = 1;
					++parentreq->lr_outrefcnt;
				}
207
				lc = ldap_new_connection( ld, srvlist, 0, 1, bind );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
208
209
210
211
			}
		}
	}

212
213
214
215
216
217
218
219
220
221
222
223
224
225
	/* async connect... */
	if ( lc != NULL && lc->lconn_status == LDAP_CONNST_CONNECTING ) {
		ber_socket_t	sd = AC_SOCKET_ERROR;
		struct timeval	tv = { 0 };

		ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sd );

		/* poll ... */
		switch ( ldap_int_poll( ld, sd, &tv ) ) {
		case 0:
			/* go on! */
			lc->lconn_status = LDAP_CONNST_CONNECTED;
			break;

Howard Chu's avatar
Howard Chu committed
226
		case -2:
227
			/* async only occurs if a network timeout is set */
Howard Chu's avatar
Howard Chu committed
228
229
230
231
232
233
234
235

			/* honor network timeout */
			if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec )
			{
				/* caller will have to call again */
				ld->ld_errno = LDAP_X_CONNECTING;
			}
			/* fallthru */
236
237
238
239
240
241
242

		default:
			/* error */
			break;
		}
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
243
244
245
246
	if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
		if ( ld->ld_errno == LDAP_SUCCESS ) {
			ld->ld_errno = LDAP_SERVER_DOWN;
		}
247
248

		ber_free( ber, 1 );
249
250
251
252
		if ( incparent ) {
			/* Forget about the bind */
			--parentreq->lr_outrefcnt; 
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
253
254
255
256
		return( -1 );
	}

	use_connection( ld, lc );
257
258
259
260
261
262

	/* If we still have an incomplete write, try to finish it before
	 * dealing with the new request. If we don't finish here, return
	 * LDAP_BUSY and let the caller retry later. We only allow a single
	 * request to be in WRITING state.
	 */
263
	rc = 0;
264
265
	if ( ld->ld_requests &&
		ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
Pierangelo Masarati's avatar
Pierangelo Masarati committed
266
267
		ldap_int_flush_request( ld, ld->ld_requests ) < 0 )
	{
268
		rc = -1;
269
	}
270
	if ( rc ) return rc;
271

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
272
	lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
273
	if ( lr == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
274
		ld->ld_errno = LDAP_NO_MEMORY;
275
		ldap_free_connection( ld, lc, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
276
		ber_free( ber, 1 );
277
278
279
280
		if ( incparent ) {
			/* Forget about the bind */
			--parentreq->lr_outrefcnt; 
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
281
282
283
284
285
286
287
288
		return( -1 );
	} 
	lr->lr_msgid = msgid;
	lr->lr_status = LDAP_REQST_INPROGRESS;
	lr->lr_res_errno = LDAP_SUCCESS;	/* optimistic */
	lr->lr_ber = ber;
	lr->lr_conn = lc;
	if ( parentreq != NULL ) {	/* sub-request */
289
290
291
292
		if ( !incparent ) { 
			/* Increment if we didn't do it before the bind */
			++parentreq->lr_outrefcnt;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
293
		lr->lr_origid = parentreq->lr_origid;
294
		lr->lr_parentcnt = ++parentreq->lr_parentcnt;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
295
		lr->lr_parent = parentreq;
296
297
		lr->lr_refnext = parentreq->lr_child;
		parentreq->lr_child = lr;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
298
299
300
301
	} else {			/* original request */
		lr->lr_origid = lr->lr_msgid;
	}

302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
	/* Extract requestDN for future reference */
	{
		BerElement tmpber = *ber;
		ber_int_t	bint;
		ber_tag_t	tag, rtag;

		ber_reset( &tmpber, 1 );
		rtag = ber_scanf( &tmpber, "{it", /*}*/ &bint, &tag );
		switch ( tag ) {
		case LDAP_REQ_BIND:
			rtag = ber_scanf( &tmpber, "{i" /*}*/, &bint );
			break;
		case LDAP_REQ_DELETE:
			break;
		default:
			rtag = ber_scanf( &tmpber, "{" /*}*/ );
		case LDAP_REQ_ABANDON:
			break;
		}
		if ( tag != LDAP_REQ_ABANDON ) {
			ber_skip_tag( &tmpber, &lr->lr_dn.bv_len );
			lr->lr_dn.bv_val = tmpber.ber_ptr;
		}
	}

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
327
	lr->lr_prev = NULL;
328
329
	lr->lr_next = ld->ld_requests;
	if ( lr->lr_next != NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
330
331
332
333
		lr->lr_next->lr_prev = lr;
	}
	ld->ld_requests = lr;

334
	ld->ld_errno = LDAP_SUCCESS;
335
	if ( ldap_int_flush_request( ld, lr ) == -1 ) {
336
		msgid = -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
337
338
339
340
341
342
	}

	return( msgid );
}

LDAPConn *
343
ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
344
	int connect, LDAPreqinfo *bind )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
345
346
{
	LDAPConn	*lc;
347
	int		async = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
348

Pierangelo Masarati's avatar
Pierangelo Masarati committed
349
350
	Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
		use_ldsb, connect, (bind != NULL) );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
351
352
353
354
	/*
	 * make a new LDAP server connection
	 * XXX open connection synchronously for now
	 */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
355
356
	lc = (LDAPConn *)LDAP_CALLOC( 1, sizeof( LDAPConn ) );
	if ( lc == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
357
358
359
		ld->ld_errno = LDAP_NO_MEMORY;
		return( NULL );
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
360
361
	
	if ( use_ldsb ) {
362
		assert( ld->ld_sb != NULL );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
363
		lc->lconn_sb = ld->ld_sb;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
364

Pierangelo Masarati's avatar
Pierangelo Masarati committed
365
366
367
368
369
370
371
372
	} else {
		lc->lconn_sb = ber_sockbuf_alloc();
		if ( lc->lconn_sb == NULL ) {
			LDAP_FREE( (char *)lc );
			ld->ld_errno = LDAP_NO_MEMORY;
			return( NULL );
		}
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
373
374

	if ( connect ) {
375
376
		LDAPURLDesc	**srvp, *srv = NULL;

377
378
		async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC );

379
		for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) {
380
381
382
383
			int		rc;

			rc = ldap_int_open_connection( ld, lc, *srvp, async );
			if ( rc != -1 ) {
384
385
				srv = *srvp;

386
				if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) {
387
388
389
					ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params );
				}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
390
391
392
393
394
				break;
			}
		}

		if ( srv == NULL ) {
395
396
397
			if ( !use_ldsb ) {
				ber_sockbuf_free( lc->lconn_sb );
			}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
398
399
400
			LDAP_FREE( (char *)lc );
			ld->ld_errno = LDAP_SERVER_DOWN;
			return( NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
401
402
		}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
403
		lc->lconn_server = ldap_url_dup( srv );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
404
405
	}

406
	lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
407
408
409
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
410
411
	lc->lconn_next = ld->ld_conns;
	ld->ld_conns = lc;
412
413
414
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
415

416
	if ( bind != NULL ) {
417
		int		err = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
418
419
		LDAPConn	*savedefconn;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
420
421
		/* Set flag to prevent additional referrals
		 * from being processed on this
422
423
424
425
		 * connection until the bind has completed
		 */
		lc->lconn_rebind_inprogress = 1;
		/* V3 rebind function */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
426
		if ( ld->ld_rebind_proc != NULL) {
427
			LDAPURLDesc	*srvfunc;
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
428

429
			srvfunc = ldap_url_dup( *srvlist );
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
430
			if ( srvfunc == NULL ) {
431
432
				ld->ld_errno = LDAP_NO_MEMORY;
				err = -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
433
			} else {
434
435
436
437
				savedefconn = ld->ld_defconn;
				++lc->lconn_refcnt;	/* avoid premature free */
				ld->ld_defconn = lc;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
438
				Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0);
439
#ifdef LDAP_R_COMPILE
Pierangelo Masarati's avatar
Pierangelo Masarati committed
440
441
				ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
				ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
Julius Enarusai's avatar
   
Julius Enarusai committed
442
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
443
444
				err = (*ld->ld_rebind_proc)( ld,
					bind->ri_url, bind->ri_request, bind->ri_msgid,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
445
					ld->ld_rebind_params );
446
#ifdef LDAP_R_COMPILE
Pierangelo Masarati's avatar
Pierangelo Masarati committed
447
448
				ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
				ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
449
#endif
450
451
452
453

				ld->ld_defconn = savedefconn;
				--lc->lconn_refcnt;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
454
455
				if ( err != 0 ) {
					err = -1;
456
457
					ldap_free_connection( ld, lc, 1, 0 );
					lc = NULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
458
459
				}
				ldap_free_urldesc( srvfunc );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
460
			}
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
461

462
		} else {
463
464
465
			int		msgid, rc;
			struct berval	passwd = BER_BVNULL;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
466
467
			savedefconn = ld->ld_defconn;
			++lc->lconn_refcnt;	/* avoid premature free */
468
			ld->ld_defconn = lc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
469

470
471
472
473
			Debug( LDAP_DEBUG_TRACE,
				"anonymous rebind via ldap_sasl_bind(\"\")\n",
				0, 0, 0);

474
475
476
#ifdef LDAP_R_COMPILE
			ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
			ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
Julius Enarusai's avatar
   
Julius Enarusai committed
477
#endif
478
479
480
			rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd,
				NULL, NULL, &msgid );
			if ( rc != LDAP_SUCCESS ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
481
				err = -1;
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510

			} else {
				for ( err = 1; err > 0; ) {
					struct timeval	tv = { 0, 100000 };
					LDAPMessage	*res = NULL;

					switch ( ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) {
					case -1:
						err = -1;
						break;

					case 0:
#ifdef LDAP_R_COMPILE
						ldap_pvt_thread_yield();
#endif
						break;

					case LDAP_RES_BIND:
						rc = ldap_parse_result( ld, res, &err, NULL, NULL, NULL, NULL, 1 );
						if ( rc != LDAP_SUCCESS ) {
							err = -1;

						} else if ( err != LDAP_SUCCESS ) {
							err = -1;
						}
						/* else err == LDAP_SUCCESS == 0 */
						break;

					default:
511
512
513
514
						Debug( LDAP_DEBUG_TRACE,
							"ldap_new_connection %p: "
							"unexpected response %d "
							"from BIND request id=%d\n",
515
							(void *) ld, ldap_msgtype( res ), msgid );
516
517
						err = -1;
						break;
518
519
					}
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
520
			}
521
522
523
524
#ifdef LDAP_R_COMPILE
			ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
			ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
525
			ld->ld_defconn = savedefconn;
526
			--lc->lconn_refcnt;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
527

Pierangelo Masarati's avatar
Pierangelo Masarati committed
528
529
530
531
			if ( err != 0 ) {
				ldap_free_connection( ld, lc, 1, 0 );
				lc = NULL;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
532
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
533
		if ( lc != NULL )
534
535
			lc->lconn_rebind_inprogress = 0;
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
536
537
538
539
540
541

	return( lc );
}


static LDAPConn *
542
find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
543
544
545
546
547
548
/*
 * return an existing connection (if any) to the server srv
 * if "any" is non-zero, check for any server in the "srv" chain
 */
{
	LDAPConn	*lc;
549
550
	LDAPURLDesc	*lcu, *lsu;
	int lcu_port, lsu_port;
551
	int found = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
552

553
554
555
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
556
	for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
557
		lcu = lc->lconn_server;
558
559
560
		lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme,
			lcu->lud_port );

561
		for ( lsu = srv; lsu != NULL; lsu = lsu->lud_next ) {
562
563
564
			lsu_port = ldap_pvt_url_scheme_port( lsu->lud_scheme,
				lsu->lud_port );

565
566
			if ( lsu_port == lcu_port
				&& strcmp( lcu->lud_scheme, lsu->lud_scheme ) == 0
567
				&& lcu->lud_host != NULL && *lcu->lud_host != '\0'
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
568
				&& lsu->lud_host != NULL && *lsu->lud_host != '\0'
569
				&& strcasecmp( lsu->lud_host, lcu->lud_host ) == 0 )
570
			{
571
572
				found = 1;
				break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
573
			}
574
575

			if ( !any ) break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
576
		}
577
578
		if ( found )
			break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
579
	}
580
581
582
583
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
#endif
	return lc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
584
585
586
587
588
589
590
591
}



static void
use_connection( LDAP *ld, LDAPConn *lc )
{
	++lc->lconn_refcnt;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
592
	lc->lconn_lastused = time( NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
593
594
595
596
}


void
597
ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
598
599
600
{
	LDAPConn	*tmplc, *prevlc;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
601
602
603
	Debug( LDAP_DEBUG_TRACE,
		"ldap_free_connection %d %d\n",
		force, unbind, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
604
605

	if ( force || --lc->lconn_refcnt <= 0 ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
606
		/* remove from connections list first */
607
#ifdef LDAP_R_COMPILE
Pierangelo Masarati's avatar
Pierangelo Masarati committed
608
		ldap_pvt_thread_mutex_lock( &ld->ld_conn_mutex );
609
#endif
Pierangelo Masarati's avatar
Pierangelo Masarati committed
610
611

		for ( prevlc = NULL, tmplc = ld->ld_conns;
612
613
614
			tmplc != NULL;
			tmplc = tmplc->lconn_next )
		{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
615
616
617
618
619
620
621
622
			if ( tmplc == lc ) {
				if ( prevlc == NULL ) {
				    ld->ld_conns = tmplc->lconn_next;
				} else {
				    prevlc->lconn_next = tmplc->lconn_next;
				}
				break;
			}
623
			prevlc = tmplc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
624
		}
625
#ifdef LDAP_R_COMPILE
Pierangelo Masarati's avatar
Pierangelo Masarati committed
626
		ldap_pvt_thread_mutex_unlock( &ld->ld_conn_mutex );
627
#endif
Pierangelo Masarati's avatar
Pierangelo Masarati committed
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642

		if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
			ldap_mark_select_clear( ld, lc->lconn_sb );
			if ( unbind ) {
				ldap_send_unbind( ld, lc->lconn_sb,
						NULL, NULL );
			}
		}

		if ( lc->lconn_ber != NULL ) {
			ber_free( lc->lconn_ber, 1 );
		}

		ldap_int_sasl_close( ld, lc );

643
		ldap_free_urllist( lc->lconn_server );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
644

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
645
646
647
648
		/* FIXME: is this at all possible?
		 * ldap_ld_free() in unbind.c calls ldap_free_connection()
		 * with force == 1 __after__ explicitly calling
		 * ldap_free_request() on all requests */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
649
650
651
652
653
654
655
656
657
658
659
660
661
		if ( force ) {
			LDAPRequest	*lr;

			for ( lr = ld->ld_requests; lr; ) {
				LDAPRequest	*lr_next = lr->lr_next;

				if ( lr->lr_conn == lc ) {
					ldap_free_request_int( ld, lr );
				}

				lr = lr_next;
			}
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
662

663
		if ( lc->lconn_sb != ld->ld_sb ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
664
			ber_sockbuf_free( lc->lconn_sb );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
665
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
666

Pierangelo Masarati's avatar
Pierangelo Masarati committed
667
		if ( lc->lconn_rebind_queue != NULL) {
668
			int i;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
669
670
			for( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) {
				LDAP_VFREE( lc->lconn_rebind_queue[i] );
671
			}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
672
			LDAP_FREE( lc->lconn_rebind_queue );
673
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
674

675
		LDAP_FREE( lc );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
676

Pierangelo Masarati's avatar
Pierangelo Masarati committed
677
678
679
		Debug( LDAP_DEBUG_TRACE,
			"ldap_free_connection: actually freed\n",
			0, 0, 0 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
680

Kurt Zeilenga's avatar
Kurt Zeilenga committed
681
	} else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
682
		lc->lconn_lastused = time( NULL );
683
		Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: refcnt %d\n",
Pierangelo Masarati's avatar
Pierangelo Masarati committed
684
				lc->lconn_refcnt, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
685
686
687
688
689
690
	}
}


#ifdef LDAP_DEBUG
void
691
ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
692
693
{
	LDAPConn	*lc;
694
   	char		timebuf[32];
Kurt Zeilenga's avatar
Kurt Zeilenga committed
695

696
	Debug( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "", 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
697
698
	for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
		if ( lc->lconn_server != NULL ) {
699
			Debug( LDAP_DEBUG_TRACE, "* host: %s  port: %d%s\n",
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
700
701
702
703
				( lc->lconn_server->lud_host == NULL ) ? "(null)"
				: lc->lconn_server->lud_host,
				lc->lconn_server->lud_port, ( lc->lconn_sb ==
				ld->ld_sb ) ? "  (default)" : "" );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
704
		}
705
706
		Debug( LDAP_DEBUG_TRACE, "  refcnt: %d  status: %s\n", lc->lconn_refcnt,
			( lc->lconn_status == LDAP_CONNST_NEEDSOCKET )
707
708
709
				? "NeedSocket" :
				( lc->lconn_status == LDAP_CONNST_CONNECTING )
					? "Connecting" : "Connected", 0 );
710
711
712
713
714
715
716
717
718
719
720
721
		Debug( LDAP_DEBUG_TRACE, "  last used: %s%s\n",
			ldap_pvt_ctime( &lc->lconn_lastused, timebuf ),
			lc->lconn_rebind_inprogress ? "  rebind in progress" : "", 0 );
		if ( lc->lconn_rebind_inprogress ) {
			if ( lc->lconn_rebind_queue != NULL) {
				int	i;

				for ( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) {
					int	j;
					for( j = 0; lc->lconn_rebind_queue[i][j] != 0; j++ ) {
						Debug( LDAP_DEBUG_TRACE, "    queue %d entry %d - %s\n",
							i, j, lc->lconn_rebind_queue[i][j] );
722
723
724
					}
				}
			} else {
725
				Debug( LDAP_DEBUG_TRACE, "    queue is empty\n", 0, 0, 0 );
726
727
			}
		}
728
		Debug( LDAP_DEBUG_TRACE, "\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
729
730
731
732
733
734
735
736
		if ( !all ) {
			break;
		}
	}
}


void
737
ldap_dump_requests_and_responses( LDAP *ld )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
738
739
740
{
	LDAPRequest	*lr;
	LDAPMessage	*lm, *l;
741
	int		i;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
742

743
744
	Debug( LDAP_DEBUG_TRACE, "** ld %p Outstanding Requests:\n",
		(void *)ld, 0, 0 );
745
746
	lr = ld->ld_requests;
	if ( lr == NULL ) {
747
		Debug( LDAP_DEBUG_TRACE, "   Empty\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
748
	}
749
	for ( i = 0; lr != NULL; lr = lr->lr_next, i++ ) {
750
		Debug( LDAP_DEBUG_TRACE, " * msgid %d,  origid %d, status %s\n",
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
751
752
753
754
755
756
			lr->lr_msgid, lr->lr_origid,
			( lr->lr_status == LDAP_REQST_INPROGRESS ) ? "InProgress" :
			( lr->lr_status == LDAP_REQST_CHASINGREFS ) ? "ChasingRefs" :
			( lr->lr_status == LDAP_REQST_NOTCONNECTED ) ? "NotConnected" :
			( lr->lr_status == LDAP_REQST_WRITING ) ? "Writing" :
			( lr->lr_status == LDAP_REQST_COMPLETED ) ? "RequestCompleted"
757
758
759
				: "InvalidStatus" );
		Debug( LDAP_DEBUG_TRACE, "   outstanding referrals %d, parent count %d\n",
			lr->lr_outrefcnt, lr->lr_parentcnt, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
760
	}
761
	Debug( LDAP_DEBUG_TRACE, "  ld %p request count %d (abandoned %lu)\n",
762
		(void *)ld, i, ld->ld_nabandoned );
763
	Debug( LDAP_DEBUG_TRACE, "** ld %p Response Queue:\n", (void *)ld, 0, 0 );
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
764
	if ( ( lm = ld->ld_responses ) == NULL ) {
765
		Debug( LDAP_DEBUG_TRACE, "   Empty\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
766
	}
767
	for ( i = 0; lm != NULL; lm = lm->lm_next, i++ ) {
768
769
		Debug( LDAP_DEBUG_TRACE, " * msgid %d,  type %lu\n",
		    lm->lm_msgid, (unsigned long)lm->lm_msgtype, 0 );
770
		if ( lm->lm_chain != NULL ) {
771
			Debug( LDAP_DEBUG_TRACE, "   chained responses:\n", 0, 0, 0 );
772
			for ( l = lm->lm_chain; l != NULL; l = l->lm_chain ) {
773
				Debug( LDAP_DEBUG_TRACE,
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
774
775
					"  * msgid %d,  type %lu\n",
					l->lm_msgid,
776
					(unsigned long)l->lm_msgtype, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
777
778
779
			}
		}
	}
780
	Debug( LDAP_DEBUG_TRACE, "  ld %p response count %d\n", (void *)ld, i, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
781
782
783
}
#endif /* LDAP_DEBUG */

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
784
static void
785
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
786
{
787
788
789
790
791
	/* if lr_refcnt > 0, the request has been looked up 
	 * by ldap_find_request_by_msgid(); if in the meanwhile
	 * the request is free()'d by someone else, just decrease
	 * the reference count and extract it from the request
	 * list; later on, it will be freed. */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
792
	if ( lr->lr_prev == NULL ) {
793
794
795
796
797
798
799
800
		if ( lr->lr_refcnt == 0 ) {
			/* free'ing the first request? */
			assert( ld->ld_requests == lr );
		}

		if ( ld->ld_requests == lr ) {
			ld->ld_requests = lr->lr_next;
		}
801

Kurt Zeilenga's avatar
Kurt Zeilenga committed
802
803
804
805
806
807
808
809
	} else {
		lr->lr_prev->lr_next = lr->lr_next;
	}

	if ( lr->lr_next != NULL ) {
		lr->lr_next->lr_prev = lr->lr_prev;
	}

810
811
812
813
814
815
816
817
818
	if ( lr->lr_refcnt > 0 ) {
		lr->lr_refcnt = -lr->lr_refcnt;

		lr->lr_prev = NULL;
		lr->lr_next = NULL;

		return;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
819
820
	if ( lr->lr_ber != NULL ) {
		ber_free( lr->lr_ber, 1 );
821
		lr->lr_ber = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
822
823
824
	}

	if ( lr->lr_res_error != NULL ) {
825
		LDAP_FREE( lr->lr_res_error );
826
		lr->lr_res_error = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
827
828
829
	}

	if ( lr->lr_res_matched != NULL ) {
830
		LDAP_FREE( lr->lr_res_matched );
831
		lr->lr_res_matched = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
832
833
	}

834
	LDAP_FREE( lr );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
835
836
}

837
838
839
void
ldap_free_request( LDAP *ld, LDAPRequest *lr )
{
Pierangelo Masarati's avatar
Pierangelo Masarati committed
840
841
842
#ifdef LDAP_R_COMPILE
	LDAP_PVT_THREAD_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
#endif
843
844
845
846

	Debug( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n",
		lr->lr_origid, lr->lr_msgid, 0 );

847
	/* free all referrals (child requests) */
848
	while ( lr->lr_child ) {
849
		ldap_free_request( ld, lr->lr_child );
850
	}
851

852
	if ( lr->lr_parent != NULL ) {
853
854
		LDAPRequest     **lrp;

855
		--lr->lr_parent->lr_outrefcnt;
856
857
858
859
860
861
862
		for ( lrp = &lr->lr_parent->lr_child;
			*lrp && *lrp != lr;
			lrp = &(*lrp)->lr_refnext );

		if ( *lrp == lr ) {
			*lrp = lr->lr_refnext;
		}
863
864
865
866
	}
	ldap_free_request_int( ld, lr );
}

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
/*
 * call first time with *cntp = -1
 * when returns *cntp == -1, no referrals are left
 *
 * NOTE: may replace *refsp, or shuffle the contents
 * of the original array.
 */
static int ldap_int_nextref(
	LDAP			*ld,
	char			***refsp,
	int			*cntp,
	void			*params )
{
	assert( refsp != NULL );
	assert( *refsp != NULL );
	assert( cntp != NULL );

	if ( *cntp < -1 ) {
		*cntp = -1;
		return -1;
	}

	(*cntp)++;

	if ( (*refsp)[ *cntp ] == NULL ) {
		*cntp = -1;
	}

	return 0;
}
897

898
899
900
901
902
903
904
905
/*
 * Chase v3 referrals
 *
 * Parameters:
 *  (IN) ld = LDAP connection handle
 *  (IN) lr = LDAP Request structure
 *  (IN) refs = array of pointers to referral strings that we will chase
 *              The array will be free'd by this function when no longer needed
906
 *  (IN) sref != 0 if following search reference
907
908
909
910
911
 *  (OUT) errstrp = Place to return a string of referrals which could not be followed
 *  (OUT) hadrefp = 1 if sucessfully followed referral
 *
 * Return value - number of referrals followed
 */
912
int
913
ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp )
914
915
{
	char		*unfollowed;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
916
	int		 unfollowedcnt = 0;
917
918
919
920
921
	LDAPRequest	*origreq;
	LDAPURLDesc	*srv = NULL;
	BerElement	*ber;
	char		**refarray = NULL;
	LDAPConn	*lc;
922
	int			 rc, count, i, j, id;
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
	LDAPreqinfo  rinfo;

	ld->ld_errno = LDAP_SUCCESS;	/* optimistic */
	*hadrefp = 0;

	Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 );

	unfollowed = NULL;
	rc = count = 0;

	/* If no referrals in array, return */
	if ( (refs == NULL) || ( (refs)[0] == NULL) ) {
		rc = 0;
		goto done;
	}

	/* Check for hop limit exceeded */
	if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) {
		Debug( LDAP_DEBUG_ANY,
		    "more than %d referral hops (dropping)\n", ld->ld_refhoplimit, 0, 0 );
		ld->ld_errno = LDAP_REFERRAL_LIMIT_EXCEEDED;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
944
		rc = -1;
945
946
947
948
		goto done;
	}

	/* find original request */
949
950
951
952
953
	for ( origreq = lr;
		origreq->lr_parent != NULL;
		origreq = origreq->lr_parent )
	{
		/* empty */ ;
954
955
956
957
	}

	refarray = refs;
	refs = NULL;
958
959
960
961
962

	if ( ld->ld_nextref_proc == NULL ) {
		ld->ld_nextref_proc = ldap_int_nextref;
	}

963
	/* parse out & follow referrals */
964
965
966
967
968
969
	i = -1;
	for ( ld->ld_nextref_proc( ld, &refarray, &i, ld->ld_nextref_params );
			i != -1;
			ld->ld_nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ) )
	{

970
		/* Parse the referral URL */
971
		rc = ldap_url_parse_ext( refarray[i], &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN );
972
973
974
975
		if ( rc != LDAP_URL_SUCCESS ) {
			/* ldap_url_parse_ext() returns LDAP_URL_* errors
			 * which do not map on API errors */
			ld->ld_errno = LDAP_PARAM_ERROR;
976
977
978
979
			rc = -1;
			goto done;
		}

980
981
982
983
984
985
986
		if( srv->lud_crit_exts ) {
			/* we do not support any extensions */
			ld->ld_errno = LDAP_NOT_SUPPORTED;
			rc = -1;
			goto done;
		}

987
988
		/* check connection for re-bind in progress */
		if (( lc = find_connection( ld, srv, 1 )) != NULL ) {
989
990
991
992
			/* See if we've already requested this DN with this conn */
			LDAPRequest *lp;
			int looped = 0;
			int len = srv->lud_dn ? strlen( srv->lud_dn ) : 0;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
993
			for ( lp = origreq; lp; ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
994
995
996
997
998
999
1000
				if ( lp->lr_conn == lc
					&& len == lp->lr_dn.bv_len
					&& len
					&& strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) == 0 )
				{
					looped = 1;
					break;
For faster browsing, not all history is shown. View entire blame