1 /*	$NetBSD: open.c,v 1.3 2021/08/14 16:14:56 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2021 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
18  * All rights reserved.
19  */
20 
21 #include <sys/cdefs.h>
22 __RCSID("$NetBSD: open.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
23 
24 #include "portable.h"
25 
26 #include <stdio.h>
27 #ifdef HAVE_LIMITS_H
28 #include <limits.h>
29 #endif
30 
31 #include <ac/stdlib.h>
32 
33 #include <ac/param.h>
34 #include <ac/socket.h>
35 #include <ac/string.h>
36 #include <ac/time.h>
37 
38 #include <ac/unistd.h>
39 
40 #include "ldap-int.h"
41 #include "ldap.h"
42 #include "ldap_log.h"
43 
44 /* Caller must hold the conn_mutex since simultaneous accesses are possible */
ldap_open_defconn(LDAP * ld)45 int ldap_open_defconn( LDAP *ld )
46 {
47 	ld->ld_defconn = ldap_new_connection( ld,
48 		&ld->ld_options.ldo_defludp, 1, 1, NULL, 0, 0 );
49 
50 	if( ld->ld_defconn == NULL ) {
51 		ld->ld_errno = LDAP_SERVER_DOWN;
52 		return -1;
53 	}
54 
55 	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */
56 	return 0;
57 }
58 
59 /*
60  * ldap_connect - Connect to an ldap server.
61  *
62  * Example:
63  *	LDAP	*ld;
64  *	ldap_initialize( &ld, url );
65  *	ldap_connect( ld );
66  */
67 int
ldap_connect(LDAP * ld)68 ldap_connect( LDAP *ld )
69 {
70 	ber_socket_t sd = AC_SOCKET_INVALID;
71 	int rc = LDAP_SUCCESS;
72 
73 	LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
74 	if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ) == -1 ) {
75 		rc = ldap_open_defconn( ld );
76 	}
77 	LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
78 
79 	return rc;
80 }
81 
82 /*
83  * ldap_open - initialize and connect to an ldap server.  A magic cookie to
84  * be used for future communication is returned on success, NULL on failure.
85  * "host" may be a space-separated list of hosts or IP addresses
86  *
87  * Example:
88  *	LDAP	*ld;
89  *	ld = ldap_open( hostname, port );
90  */
91 
92 LDAP *
ldap_open(LDAP_CONST char * host,int port)93 ldap_open( LDAP_CONST char *host, int port )
94 {
95 	int rc;
96 	LDAP		*ld;
97 
98 	Debug2( LDAP_DEBUG_TRACE, "ldap_open(%s, %d)\n",
99 		host, port );
100 
101 	ld = ldap_init( host, port );
102 	if ( ld == NULL ) {
103 		return( NULL );
104 	}
105 
106 	LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
107 	rc = ldap_open_defconn( ld );
108 	LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
109 
110 	if( rc < 0 ) {
111 		ldap_ld_free( ld, 0, NULL, NULL );
112 		ld = NULL;
113 	}
114 
115 	Debug1( LDAP_DEBUG_TRACE, "ldap_open: %s\n",
116 		ld != NULL ? "succeeded" : "failed" );
117 
118 	return ld;
119 }
120 
121 
122 
123 int
ldap_create(LDAP ** ldp)124 ldap_create( LDAP **ldp )
125 {
126 	LDAP			*ld;
127 	struct ldapoptions	*gopts;
128 
129 	*ldp = NULL;
130 	/* Get pointer to global option structure */
131 	if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
132 		return LDAP_NO_MEMORY;
133 	}
134 
135 	/* Initialize the global options, if not already done. */
136 	if( gopts->ldo_valid != LDAP_INITIALIZED ) {
137 		ldap_int_initialize(gopts, NULL);
138 		if ( gopts->ldo_valid != LDAP_INITIALIZED )
139 			return LDAP_LOCAL_ERROR;
140 	}
141 
142 	Debug0( LDAP_DEBUG_TRACE, "ldap_create\n" );
143 
144 	if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
145 		return( LDAP_NO_MEMORY );
146 	}
147 
148 	if ( (ld->ldc = (struct ldap_common *) LDAP_CALLOC( 1,
149 			sizeof(struct ldap_common) )) == NULL ) {
150 		LDAP_FREE( (char *)ld );
151 		return( LDAP_NO_MEMORY );
152 	}
153 	/* copy the global options */
154 	LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
155 	AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
156 #ifdef LDAP_R_COMPILE
157 	/* Properly initialize the structs mutex */
158 	ldap_pvt_thread_mutex_init( &(ld->ld_ldopts_mutex) );
159 #endif
160 
161 #ifdef HAVE_TLS
162 	if ( ld->ld_options.ldo_tls_pin_hashalg ) {
163 		int len = strlen( gopts->ldo_tls_pin_hashalg );
164 
165 		ld->ld_options.ldo_tls_pin_hashalg =
166 			LDAP_MALLOC( len + 1 + gopts->ldo_tls_pin.bv_len );
167 		if ( !ld->ld_options.ldo_tls_pin_hashalg ) goto nomem;
168 
169 		ld->ld_options.ldo_tls_pin.bv_val = ld->ld_options.ldo_tls_pin_hashalg
170 			+ len + 1;
171 		AC_MEMCPY( ld->ld_options.ldo_tls_pin_hashalg, gopts->ldo_tls_pin_hashalg,
172 				len + 1 + gopts->ldo_tls_pin.bv_len );
173 	} else if ( !BER_BVISEMPTY(&ld->ld_options.ldo_tls_pin) ) {
174 		ber_dupbv( &ld->ld_options.ldo_tls_pin, &gopts->ldo_tls_pin );
175 	}
176 #endif
177 	LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
178 
179 	ld->ld_valid = LDAP_VALID_SESSION;
180 
181 	/* but not pointers to malloc'ed items */
182 	ld->ld_options.ldo_sctrls = NULL;
183 	ld->ld_options.ldo_cctrls = NULL;
184 	ld->ld_options.ldo_defludp = NULL;
185 	ld->ld_options.ldo_conn_cbs = NULL;
186 
187 	ld->ld_options.ldo_defbase = gopts->ldo_defbase
188 		? LDAP_STRDUP( gopts->ldo_defbase ) : NULL;
189 
190 #ifdef HAVE_CYRUS_SASL
191 	ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
192 		? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
193 	ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
194 		? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
195 	ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
196 		? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
197 	ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
198 		? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
199 #endif
200 
201 #ifdef HAVE_TLS
202 	/* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave
203 	 * them empty to allow new SSL_CTX's to be created from scratch.
204 	 */
205 	memset( &ld->ld_options.ldo_tls_info, 0,
206 		sizeof( ld->ld_options.ldo_tls_info ));
207 	ld->ld_options.ldo_tls_ctx = NULL;
208 #endif
209 
210 	if ( gopts->ldo_defludp ) {
211 		ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp);
212 
213 		if ( ld->ld_options.ldo_defludp == NULL ) goto nomem;
214 	}
215 
216 	if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem;
217 
218 	ld->ld_options.ldo_local_ip_addrs.local_ip_addrs = NULL;
219 	if( gopts->ldo_local_ip_addrs.local_ip_addrs ) {
220 		ld->ld_options.ldo_local_ip_addrs.local_ip_addrs =
221 			LDAP_STRDUP( gopts->ldo_local_ip_addrs.local_ip_addrs );
222 		if ( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs == NULL )
223 			goto nomem;
224 	}
225 
226 	ld->ld_lberoptions = LBER_USE_DER;
227 
228 	ld->ld_sb = ber_sockbuf_alloc( );
229 	if ( ld->ld_sb == NULL ) goto nomem;
230 
231 #ifdef LDAP_R_COMPILE
232 	ldap_pvt_thread_mutex_init( &ld->ld_msgid_mutex );
233 	ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
234 	ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
235 	ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
236 	ldap_pvt_thread_mutex_init( &ld->ld_abandon_mutex );
237 	ldap_pvt_thread_mutex_init( &ld->ld_ldcmutex );
238 #endif
239 	ld->ld_ldcrefcnt = 1;
240 	*ldp = ld;
241 	return LDAP_SUCCESS;
242 
243 nomem:
244 	ldap_free_select_info( ld->ld_selectinfo );
245 	ldap_free_urllist( ld->ld_options.ldo_defludp );
246 #ifdef HAVE_CYRUS_SASL
247 	LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
248 	LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
249 	LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
250 	LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
251 #endif
252 
253 #ifdef HAVE_TLS
254 	/* tls_pin_hashalg and tls_pin share the same buffer */
255 	if ( ld->ld_options.ldo_tls_pin_hashalg ) {
256 		LDAP_FREE( ld->ld_options.ldo_tls_pin_hashalg );
257 	} else {
258 		LDAP_FREE( ld->ld_options.ldo_tls_pin.bv_val );
259 	}
260 #endif
261 	LDAP_FREE( (char *)ld );
262 	return LDAP_NO_MEMORY;
263 }
264 
265 /*
266  * ldap_init - initialize the LDAP library.  A magic cookie to be used for
267  * future communication is returned on success, NULL on failure.
268  * "host" may be a space-separated list of hosts or IP addresses
269  *
270  * Example:
271  *	LDAP	*ld;
272  *	ld = ldap_init( host, port );
273  */
274 LDAP *
ldap_init(LDAP_CONST char * defhost,int defport)275 ldap_init( LDAP_CONST char *defhost, int defport )
276 {
277 	LDAP *ld;
278 	int rc;
279 
280 	rc = ldap_create(&ld);
281 	if ( rc != LDAP_SUCCESS )
282 		return NULL;
283 
284 	if (defport != 0)
285 		ld->ld_options.ldo_defport = defport;
286 
287 	if (defhost != NULL) {
288 		rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost);
289 		if ( rc != LDAP_SUCCESS ) {
290 			ldap_ld_free(ld, 1, NULL, NULL);
291 			return NULL;
292 		}
293 	}
294 
295 	return( ld );
296 }
297 
298 
299 int
ldap_initialize(LDAP ** ldp,LDAP_CONST char * url)300 ldap_initialize( LDAP **ldp, LDAP_CONST char *url )
301 {
302 	int rc;
303 	LDAP *ld;
304 
305 	*ldp = NULL;
306 	rc = ldap_create(&ld);
307 	if ( rc != LDAP_SUCCESS )
308 		return rc;
309 
310 	if (url != NULL) {
311 		rc = ldap_set_option(ld, LDAP_OPT_URI, url);
312 		if ( rc != LDAP_SUCCESS ) {
313 			ldap_ld_free(ld, 1, NULL, NULL);
314 			return rc;
315 		}
316 #ifdef LDAP_CONNECTIONLESS
317 		if (ldap_is_ldapc_url(url))
318 			LDAP_IS_UDP(ld) = 1;
319 #endif
320 	}
321 
322 	*ldp = ld;
323 	return LDAP_SUCCESS;
324 }
325 
326 int
ldap_init_fd(ber_socket_t fd,int proto,LDAP_CONST char * url,LDAP ** ldp)327 ldap_init_fd(
328 	ber_socket_t fd,
329 	int proto,
330 	LDAP_CONST char *url,
331 	LDAP **ldp
332 )
333 {
334 	int rc;
335 	LDAP *ld;
336 	LDAPConn *conn;
337 #ifdef LDAP_CONNECTIONLESS
338 	ber_socklen_t	len;
339 #endif
340 
341 	*ldp = NULL;
342 	rc = ldap_create( &ld );
343 	if( rc != LDAP_SUCCESS )
344 		return( rc );
345 
346 	if (url != NULL) {
347 		rc = ldap_set_option(ld, LDAP_OPT_URI, url);
348 		if ( rc != LDAP_SUCCESS ) {
349 			ldap_ld_free(ld, 1, NULL, NULL);
350 			return rc;
351 		}
352 	}
353 
354 	LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
355 	/* Attach the passed socket as the LDAP's connection */
356 	conn = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
357 	if( conn == NULL ) {
358 		LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
359 		ldap_unbind_ext( ld, NULL, NULL );
360 		return( LDAP_NO_MEMORY );
361 	}
362 	if( url )
363 		conn->lconn_server = ldap_url_dup( ld->ld_options.ldo_defludp );
364 	ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
365 	ld->ld_defconn = conn;
366 	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */
367 	LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
368 
369 	switch( proto ) {
370 	case LDAP_PROTO_TCP:
371 #ifdef LDAP_DEBUG
372 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
373 			LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
374 #endif
375 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
376 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
377 		break;
378 
379 #ifdef LDAP_CONNECTIONLESS
380 	case LDAP_PROTO_UDP:
381 		LDAP_IS_UDP(ld) = 1;
382 		if( ld->ld_options.ldo_peer )
383 			ldap_memfree( ld->ld_options.ldo_peer );
384 		ld->ld_options.ldo_peer = ldap_memcalloc( 1, sizeof( struct sockaddr_storage ) );
385 		len = sizeof( struct sockaddr_storage );
386 		if( getpeername ( fd, ld->ld_options.ldo_peer, &len ) < 0) {
387 			ldap_unbind_ext( ld, NULL, NULL );
388 			return( AC_SOCKET_ERROR );
389 		}
390 #ifdef LDAP_DEBUG
391 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
392 			LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
393 #endif
394 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
395 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
396 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
397 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
398 		break;
399 #endif /* LDAP_CONNECTIONLESS */
400 
401 	case LDAP_PROTO_IPC:
402 #ifdef LDAP_DEBUG
403 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
404 			LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
405 #endif
406 		ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
407 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
408 		break;
409 
410 	case LDAP_PROTO_EXT:
411 		/* caller must supply sockbuf handlers */
412 		break;
413 
414 	default:
415 		ldap_unbind_ext( ld, NULL, NULL );
416 		return LDAP_PARAM_ERROR;
417 	}
418 
419 #ifdef LDAP_DEBUG
420 	ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
421 		INT_MAX, (void *)"ldap_" );
422 #endif
423 
424 	/* Add the connection to the *LDAP's select pool */
425 	ldap_mark_select_read( ld, conn->lconn_sb );
426 
427 	*ldp = ld;
428 	return LDAP_SUCCESS;
429 }
430 
431 /* Protected by ld_conn_mutex */
432 int
ldap_int_open_connection(LDAP * ld,LDAPConn * conn,LDAPURLDesc * srv,int async)433 ldap_int_open_connection(
434 	LDAP *ld,
435 	LDAPConn *conn,
436 	LDAPURLDesc *srv,
437 	int async )
438 {
439 	int rc = -1;
440 	int proto;
441 
442 	Debug0( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n" );
443 
444 	switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) {
445 		case LDAP_PROTO_TCP:
446 			rc = ldap_connect_to_host( ld, conn->lconn_sb,
447 				proto, srv, async );
448 
449 			if ( rc == -1 ) return rc;
450 #ifdef LDAP_DEBUG
451 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
452 				LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
453 #endif
454 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
455 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
456 
457 			break;
458 
459 #ifdef LDAP_CONNECTIONLESS
460 		case LDAP_PROTO_UDP:
461 			LDAP_IS_UDP(ld) = 1;
462 			rc = ldap_connect_to_host( ld, conn->lconn_sb,
463 				proto, srv, async );
464 
465 			if ( rc == -1 ) return rc;
466 #ifdef LDAP_DEBUG
467 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
468 				LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
469 #endif
470 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
471 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
472 
473 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
474 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
475 
476 			break;
477 #endif
478 		case LDAP_PROTO_IPC:
479 #ifdef LDAP_PF_LOCAL
480 			/* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
481 			rc = ldap_connect_to_path( ld, conn->lconn_sb,
482 				srv, async );
483 			if ( rc == -1 ) return rc;
484 #ifdef LDAP_DEBUG
485 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
486 				LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
487 #endif
488 			ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
489 				LBER_SBIOD_LEVEL_PROVIDER, NULL );
490 
491 			break;
492 #endif /* LDAP_PF_LOCAL */
493 		default:
494 			return -1;
495 			break;
496 	}
497 
498 	conn->lconn_created = time( NULL );
499 
500 #ifdef LDAP_DEBUG
501 	ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
502 		INT_MAX, (void *)"ldap_" );
503 #endif
504 
505 #ifdef LDAP_CONNECTIONLESS
506 	if( proto == LDAP_PROTO_UDP ) return 0;
507 #endif
508 
509 #ifdef HAVE_TLS
510 	if ((rc == 0 || rc == -2) && ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
511 		strcmp( srv->lud_scheme, "ldaps" ) == 0 ))
512 	{
513 		++conn->lconn_refcnt;	/* avoid premature free */
514 
515 		rc = ldap_int_tls_start( ld, conn, srv );
516 
517 		--conn->lconn_refcnt;
518 
519 		if (rc != LDAP_SUCCESS) {
520 			/* process connection callbacks */
521 			{
522 				struct ldapoptions *lo;
523 				ldaplist *ll;
524 				ldap_conncb *cb;
525 
526 				lo = &ld->ld_options;
527 				LDAP_MUTEX_LOCK( &lo->ldo_mutex );
528 				if ( lo->ldo_conn_cbs ) {
529 					for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
530 						cb = ll->ll_data;
531 						cb->lc_del( ld, conn->lconn_sb, cb );
532 					}
533 				}
534 				LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
535 				lo = LDAP_INT_GLOBAL_OPT();
536 				LDAP_MUTEX_LOCK( &lo->ldo_mutex );
537 				if ( lo->ldo_conn_cbs ) {
538 					for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
539 						cb = ll->ll_data;
540 						cb->lc_del( ld, conn->lconn_sb, cb );
541 					}
542 				}
543 				LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
544 			}
545 			ber_int_sb_close( conn->lconn_sb );
546 			return -1;
547 		}
548 	}
549 #endif
550 
551 	return( 0 );
552 }
553 
554 /*
555  * ldap_open_internal_connection - open connection and set file descriptor
556  *
557  * note: ldap_init_fd() may be preferable
558  */
559 
560 int
ldap_open_internal_connection(LDAP ** ldp,ber_socket_t * fdp)561 ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
562 {
563 	int rc;
564 	LDAPConn *c;
565 	LDAPRequest *lr;
566 	LDAP	*ld;
567 
568 	rc = ldap_create( &ld );
569 	if( rc != LDAP_SUCCESS ) {
570 		*ldp = NULL;
571 		return( rc );
572 	}
573 
574 	/* Make it appear that a search request, msgid 0, was sent */
575 	lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
576 	if( lr == NULL ) {
577 		ldap_unbind_ext( ld, NULL, NULL );
578 		*ldp = NULL;
579 		return( LDAP_NO_MEMORY );
580 	}
581 	memset(lr, 0, sizeof( LDAPRequest ));
582 	lr->lr_msgid = 0;
583 	lr->lr_status = LDAP_REQST_INPROGRESS;
584 	lr->lr_res_errno = LDAP_SUCCESS;
585 	/* no mutex lock needed, we just created this ld here */
586 	rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error );
587 	assert( rc == LDAP_SUCCESS );
588 
589 	LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
590 	/* Attach the passed socket as the *LDAP's connection */
591 	c = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
592 	if( c == NULL ) {
593 		ldap_unbind_ext( ld, NULL, NULL );
594 		*ldp = NULL;
595 		LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
596 		return( LDAP_NO_MEMORY );
597 	}
598 	ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
599 #ifdef LDAP_DEBUG
600 	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
601 		LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
602 #endif
603 	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
604 	  LBER_SBIOD_LEVEL_PROVIDER, NULL );
605 	ld->ld_defconn = c;
606 	LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
607 
608 	/* Add the connection to the *LDAP's select pool */
609 	ldap_mark_select_read( ld, c->lconn_sb );
610 
611 	/* Make this connection an LDAP V3 protocol connection */
612 	rc = LDAP_VERSION3;
613 	ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &rc );
614 	*ldp = ld;
615 
616 	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */
617 
618 	return( LDAP_SUCCESS );
619 }
620 
621 LDAP *
ldap_dup(LDAP * old)622 ldap_dup( LDAP *old )
623 {
624 	LDAP			*ld;
625 
626 	if ( old == NULL ) {
627 		return( NULL );
628 	}
629 
630 	Debug0( LDAP_DEBUG_TRACE, "ldap_dup\n" );
631 
632 	if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
633 		return( NULL );
634 	}
635 
636 	LDAP_MUTEX_LOCK( &old->ld_ldcmutex );
637 	ld->ldc = old->ldc;
638 	old->ld_ldcrefcnt++;
639 	LDAP_MUTEX_UNLOCK( &old->ld_ldcmutex );
640 	return ( ld );
641 }
642 
643 int
ldap_int_check_async_open(LDAP * ld,ber_socket_t sd)644 ldap_int_check_async_open( LDAP *ld, ber_socket_t sd )
645 {
646 	struct timeval tv = { 0 };
647 	int rc;
648 
649 	rc = ldap_int_poll( ld, sd, &tv, 1 );
650 	switch ( rc ) {
651 	case 0:
652 		/* now ready to start tls */
653 		ld->ld_defconn->lconn_status = LDAP_CONNST_CONNECTED;
654 		break;
655 
656 	default:
657 		ld->ld_errno = LDAP_CONNECT_ERROR;
658 		return -1;
659 
660 	case -2:
661 		/* connect not completed yet */
662 		ld->ld_errno = LDAP_X_CONNECTING;
663 		return rc;
664 	}
665 
666 #ifdef HAVE_TLS
667 	if ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
668 		!strcmp( ld->ld_defconn->lconn_server->lud_scheme, "ldaps" )) {
669 
670 		++ld->ld_defconn->lconn_refcnt;	/* avoid premature free */
671 
672 		rc = ldap_int_tls_start( ld, ld->ld_defconn, ld->ld_defconn->lconn_server );
673 
674 		--ld->ld_defconn->lconn_refcnt;
675 	}
676 #endif
677 	return rc;
678 }
679