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