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