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 */ 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 #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 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 * 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 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