Home | History | Annotate | Line # | Download | only in libldap
      1 /*	$NetBSD: open.c,v 1.4 2025/09/05 21:16:21 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 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.4 2025/09/05 21:16:21 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 */
     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
     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 *
     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
    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 *
    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
    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
    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
    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 	if ( async && rc == -2) {
    510 		/* Need to let the connect complete asynchronously before we continue */
    511 		return -2;
    512 	}
    513 
    514 #ifdef HAVE_TLS
    515 	if ((rc == 0 || rc == -2) && ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
    516 		strcmp( srv->lud_scheme, "ldaps" ) == 0 ))
    517 	{
    518 		++conn->lconn_refcnt;	/* avoid premature free */
    519 
    520 		rc = ldap_int_tls_start( ld, conn, srv );
    521 
    522 		--conn->lconn_refcnt;
    523 
    524 		if (rc != LDAP_SUCCESS) {
    525 			/* process connection callbacks */
    526 			{
    527 				struct ldapoptions *lo;
    528 				ldaplist *ll;
    529 				ldap_conncb *cb;
    530 
    531 				lo = &ld->ld_options;
    532 				LDAP_MUTEX_LOCK( &lo->ldo_mutex );
    533 				if ( lo->ldo_conn_cbs ) {
    534 					for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
    535 						cb = ll->ll_data;
    536 						cb->lc_del( ld, conn->lconn_sb, cb );
    537 					}
    538 				}
    539 				LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
    540 				lo = LDAP_INT_GLOBAL_OPT();
    541 				LDAP_MUTEX_LOCK( &lo->ldo_mutex );
    542 				if ( lo->ldo_conn_cbs ) {
    543 					for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
    544 						cb = ll->ll_data;
    545 						cb->lc_del( ld, conn->lconn_sb, cb );
    546 					}
    547 				}
    548 				LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
    549 			}
    550 			ber_int_sb_close( conn->lconn_sb );
    551 			ber_int_sb_destroy( conn->lconn_sb );
    552 			return -1;
    553 		}
    554 	}
    555 #endif
    556 
    557 	return( 0 );
    558 }
    559 
    560 /*
    561  * ldap_open_internal_connection - open connection and set file descriptor
    562  *
    563  * note: ldap_init_fd() may be preferable
    564  */
    565 
    566 int
    567 ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
    568 {
    569 	int rc;
    570 	LDAPConn *c;
    571 	LDAPRequest *lr;
    572 	LDAP	*ld;
    573 
    574 	rc = ldap_create( &ld );
    575 	if( rc != LDAP_SUCCESS ) {
    576 		*ldp = NULL;
    577 		return( rc );
    578 	}
    579 
    580 	/* Make it appear that a search request, msgid 0, was sent */
    581 	lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
    582 	if( lr == NULL ) {
    583 		ldap_unbind_ext( ld, NULL, NULL );
    584 		*ldp = NULL;
    585 		return( LDAP_NO_MEMORY );
    586 	}
    587 	memset(lr, 0, sizeof( LDAPRequest ));
    588 	lr->lr_msgid = 0;
    589 	lr->lr_status = LDAP_REQST_INPROGRESS;
    590 	lr->lr_res_errno = LDAP_SUCCESS;
    591 	/* no mutex lock needed, we just created this ld here */
    592 	rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error );
    593 	assert( rc == LDAP_SUCCESS );
    594 
    595 	LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
    596 	/* Attach the passed socket as the *LDAP's connection */
    597 	c = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
    598 	if( c == NULL ) {
    599 		LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
    600 		ldap_unbind_ext( ld, NULL, NULL );
    601 		*ldp = NULL;
    602 		return( LDAP_NO_MEMORY );
    603 	}
    604 	ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
    605 #ifdef LDAP_DEBUG
    606 	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
    607 		LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
    608 #endif
    609 	ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
    610 	  LBER_SBIOD_LEVEL_PROVIDER, NULL );
    611 	ld->ld_defconn = c;
    612 	LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
    613 
    614 	/* Add the connection to the *LDAP's select pool */
    615 	ldap_mark_select_read( ld, c->lconn_sb );
    616 
    617 	/* Make this connection an LDAP V3 protocol connection */
    618 	rc = LDAP_VERSION3;
    619 	ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &rc );
    620 	*ldp = ld;
    621 
    622 	++ld->ld_defconn->lconn_refcnt;	/* so it never gets closed/freed */
    623 
    624 	return( LDAP_SUCCESS );
    625 }
    626 
    627 LDAP *
    628 ldap_dup( LDAP *old )
    629 {
    630 	LDAP			*ld;
    631 
    632 	if ( old == NULL ) {
    633 		return( NULL );
    634 	}
    635 
    636 	Debug0( LDAP_DEBUG_TRACE, "ldap_dup\n" );
    637 
    638 	if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
    639 		return( NULL );
    640 	}
    641 
    642 	LDAP_MUTEX_LOCK( &old->ld_ldcmutex );
    643 	ld->ldc = old->ldc;
    644 	old->ld_ldcrefcnt++;
    645 	LDAP_MUTEX_UNLOCK( &old->ld_ldcmutex );
    646 	return ( ld );
    647 }
    648 
    649 int
    650 ldap_int_check_async_open( LDAP *ld, ber_socket_t sd )
    651 {
    652 	struct timeval tv = { 0 };
    653 	int rc;
    654 
    655 	rc = ldap_int_poll( ld, sd, &tv, 1 );
    656 	switch ( rc ) {
    657 	case 0:
    658 		/* now ready to start tls */
    659 		ld->ld_defconn->lconn_status = LDAP_CONNST_CONNECTED;
    660 		break;
    661 
    662 	default:
    663 		ld->ld_errno = LDAP_CONNECT_ERROR;
    664 		return -1;
    665 
    666 	case -2:
    667 		/* connect not completed yet */
    668 		ld->ld_errno = LDAP_X_CONNECTING;
    669 		return rc;
    670 	}
    671 
    672 #ifdef HAVE_TLS
    673 	if ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
    674 		!strcmp( ld->ld_defconn->lconn_server->lud_scheme, "ldaps" )) {
    675 
    676 		++ld->ld_defconn->lconn_refcnt;	/* avoid premature free */
    677 
    678 		rc = ldap_int_tls_start( ld, ld->ld_defconn, ld->ld_defconn->lconn_server );
    679 
    680 		--ld->ld_defconn->lconn_refcnt;
    681 	}
    682 #endif
    683 	return rc;
    684 }
    685