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