1*549b59edSchristos /* $NetBSD: open.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */
24e6df137Slukem
3d11b170bStron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem *
6*549b59edSchristos * Copyright 1998-2021 The OpenLDAP Foundation.
72de962bdSlukem * All rights reserved.
82de962bdSlukem *
92de962bdSlukem * Redistribution and use in source and binary forms, with or without
102de962bdSlukem * modification, are permitted only as authorized by the OpenLDAP
112de962bdSlukem * Public License.
122de962bdSlukem *
132de962bdSlukem * A copy of this license is available in the file LICENSE in the
142de962bdSlukem * top-level directory of the distribution or, alternatively, at
152de962bdSlukem * <http://www.OpenLDAP.org/license.html>.
162de962bdSlukem */
172de962bdSlukem /* Portions Copyright (c) 1995 Regents of the University of Michigan.
182de962bdSlukem * All rights reserved.
192de962bdSlukem */
202de962bdSlukem
21376af7d7Schristos #include <sys/cdefs.h>
22*549b59edSchristos __RCSID("$NetBSD: open.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
23376af7d7Schristos
242de962bdSlukem #include "portable.h"
252de962bdSlukem
262de962bdSlukem #include <stdio.h>
272de962bdSlukem #ifdef HAVE_LIMITS_H
282de962bdSlukem #include <limits.h>
292de962bdSlukem #endif
302de962bdSlukem
312de962bdSlukem #include <ac/stdlib.h>
322de962bdSlukem
332de962bdSlukem #include <ac/param.h>
342de962bdSlukem #include <ac/socket.h>
352de962bdSlukem #include <ac/string.h>
362de962bdSlukem #include <ac/time.h>
372de962bdSlukem
382de962bdSlukem #include <ac/unistd.h>
392de962bdSlukem
402de962bdSlukem #include "ldap-int.h"
414e27b3e8Schristos #include "ldap.h"
422de962bdSlukem #include "ldap_log.h"
432de962bdSlukem
44d11b170bStron /* Caller must hold the conn_mutex since simultaneous accesses are possible */
ldap_open_defconn(LDAP * ld)452de962bdSlukem int ldap_open_defconn( LDAP *ld )
462de962bdSlukem {
472de962bdSlukem ld->ld_defconn = ldap_new_connection( ld,
48d11b170bStron &ld->ld_options.ldo_defludp, 1, 1, NULL, 0, 0 );
492de962bdSlukem
502de962bdSlukem if( ld->ld_defconn == NULL ) {
512de962bdSlukem ld->ld_errno = LDAP_SERVER_DOWN;
522de962bdSlukem return -1;
532de962bdSlukem }
542de962bdSlukem
552de962bdSlukem ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
562de962bdSlukem return 0;
572de962bdSlukem }
582de962bdSlukem
592de962bdSlukem /*
60*549b59edSchristos * ldap_connect - Connect to an ldap server.
61*549b59edSchristos *
62*549b59edSchristos * Example:
63*549b59edSchristos * LDAP *ld;
64*549b59edSchristos * ldap_initialize( &ld, url );
65*549b59edSchristos * ldap_connect( ld );
66*549b59edSchristos */
67*549b59edSchristos int
ldap_connect(LDAP * ld)68*549b59edSchristos ldap_connect( LDAP *ld )
69*549b59edSchristos {
70*549b59edSchristos ber_socket_t sd = AC_SOCKET_INVALID;
71*549b59edSchristos int rc = LDAP_SUCCESS;
72*549b59edSchristos
73*549b59edSchristos LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
74*549b59edSchristos if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, &sd ) == -1 ) {
75*549b59edSchristos rc = ldap_open_defconn( ld );
76*549b59edSchristos }
77*549b59edSchristos LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
78*549b59edSchristos
79*549b59edSchristos return rc;
80*549b59edSchristos }
81*549b59edSchristos
82*549b59edSchristos /*
832de962bdSlukem * ldap_open - initialize and connect to an ldap server. A magic cookie to
842de962bdSlukem * be used for future communication is returned on success, NULL on failure.
852de962bdSlukem * "host" may be a space-separated list of hosts or IP addresses
862de962bdSlukem *
872de962bdSlukem * Example:
882de962bdSlukem * LDAP *ld;
892de962bdSlukem * ld = ldap_open( hostname, port );
902de962bdSlukem */
912de962bdSlukem
922de962bdSlukem LDAP *
ldap_open(LDAP_CONST char * host,int port)932de962bdSlukem ldap_open( LDAP_CONST char *host, int port )
942de962bdSlukem {
952de962bdSlukem int rc;
962de962bdSlukem LDAP *ld;
972de962bdSlukem
98*549b59edSchristos Debug2( LDAP_DEBUG_TRACE, "ldap_open(%s, %d)\n",
99*549b59edSchristos host, port );
1002de962bdSlukem
1012de962bdSlukem ld = ldap_init( host, port );
1022de962bdSlukem if ( ld == NULL ) {
1032de962bdSlukem return( NULL );
1042de962bdSlukem }
1052de962bdSlukem
106d11b170bStron LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
1072de962bdSlukem rc = ldap_open_defconn( ld );
108d11b170bStron LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
1092de962bdSlukem
1102de962bdSlukem if( rc < 0 ) {
1112de962bdSlukem ldap_ld_free( ld, 0, NULL, NULL );
1122de962bdSlukem ld = NULL;
1132de962bdSlukem }
1142de962bdSlukem
115*549b59edSchristos Debug1( LDAP_DEBUG_TRACE, "ldap_open: %s\n",
116*549b59edSchristos ld != NULL ? "succeeded" : "failed" );
1172de962bdSlukem
1182de962bdSlukem return ld;
1192de962bdSlukem }
1202de962bdSlukem
1212de962bdSlukem
1222de962bdSlukem
1232de962bdSlukem int
ldap_create(LDAP ** ldp)1242de962bdSlukem ldap_create( LDAP **ldp )
1252de962bdSlukem {
1262de962bdSlukem LDAP *ld;
1272de962bdSlukem struct ldapoptions *gopts;
1282de962bdSlukem
1292de962bdSlukem *ldp = NULL;
1302de962bdSlukem /* Get pointer to global option structure */
1312de962bdSlukem if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
1322de962bdSlukem return LDAP_NO_MEMORY;
1332de962bdSlukem }
1342de962bdSlukem
1352de962bdSlukem /* Initialize the global options, if not already done. */
1362de962bdSlukem if( gopts->ldo_valid != LDAP_INITIALIZED ) {
1372de962bdSlukem ldap_int_initialize(gopts, NULL);
1382de962bdSlukem if ( gopts->ldo_valid != LDAP_INITIALIZED )
1392de962bdSlukem return LDAP_LOCAL_ERROR;
1402de962bdSlukem }
1412de962bdSlukem
142*549b59edSchristos Debug0( LDAP_DEBUG_TRACE, "ldap_create\n" );
1432de962bdSlukem
1442de962bdSlukem if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
1452de962bdSlukem return( LDAP_NO_MEMORY );
1462de962bdSlukem }
1472de962bdSlukem
148d11b170bStron if ( (ld->ldc = (struct ldap_common *) LDAP_CALLOC( 1,
149d11b170bStron sizeof(struct ldap_common) )) == NULL ) {
150d11b170bStron LDAP_FREE( (char *)ld );
151d11b170bStron return( LDAP_NO_MEMORY );
152d11b170bStron }
1532de962bdSlukem /* copy the global options */
154d11b170bStron LDAP_MUTEX_LOCK( &gopts->ldo_mutex );
1552de962bdSlukem AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options));
156d11b170bStron #ifdef LDAP_R_COMPILE
157d11b170bStron /* Properly initialize the structs mutex */
158d11b170bStron ldap_pvt_thread_mutex_init( &(ld->ld_ldopts_mutex) );
159d11b170bStron #endif
160*549b59edSchristos
161*549b59edSchristos #ifdef HAVE_TLS
162*549b59edSchristos if ( ld->ld_options.ldo_tls_pin_hashalg ) {
163*549b59edSchristos int len = strlen( gopts->ldo_tls_pin_hashalg );
164*549b59edSchristos
165*549b59edSchristos ld->ld_options.ldo_tls_pin_hashalg =
166*549b59edSchristos LDAP_MALLOC( len + 1 + gopts->ldo_tls_pin.bv_len );
167*549b59edSchristos if ( !ld->ld_options.ldo_tls_pin_hashalg ) goto nomem;
168*549b59edSchristos
169*549b59edSchristos ld->ld_options.ldo_tls_pin.bv_val = ld->ld_options.ldo_tls_pin_hashalg
170*549b59edSchristos + len + 1;
171*549b59edSchristos AC_MEMCPY( ld->ld_options.ldo_tls_pin_hashalg, gopts->ldo_tls_pin_hashalg,
172*549b59edSchristos len + 1 + gopts->ldo_tls_pin.bv_len );
173*549b59edSchristos } else if ( !BER_BVISEMPTY(&ld->ld_options.ldo_tls_pin) ) {
174*549b59edSchristos ber_dupbv( &ld->ld_options.ldo_tls_pin, &gopts->ldo_tls_pin );
175*549b59edSchristos }
176*549b59edSchristos #endif
177d11b170bStron LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex );
1782de962bdSlukem
1792de962bdSlukem ld->ld_valid = LDAP_VALID_SESSION;
1802de962bdSlukem
1812de962bdSlukem /* but not pointers to malloc'ed items */
1822de962bdSlukem ld->ld_options.ldo_sctrls = NULL;
1832de962bdSlukem ld->ld_options.ldo_cctrls = NULL;
1842de962bdSlukem ld->ld_options.ldo_defludp = NULL;
1854e6df137Slukem ld->ld_options.ldo_conn_cbs = NULL;
1862de962bdSlukem
187*549b59edSchristos ld->ld_options.ldo_defbase = gopts->ldo_defbase
188*549b59edSchristos ? LDAP_STRDUP( gopts->ldo_defbase ) : NULL;
189*549b59edSchristos
1902de962bdSlukem #ifdef HAVE_CYRUS_SASL
1912de962bdSlukem ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech
1922de962bdSlukem ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL;
1932de962bdSlukem ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm
1942de962bdSlukem ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL;
1952de962bdSlukem ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid
1962de962bdSlukem ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL;
1972de962bdSlukem ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid
1982de962bdSlukem ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL;
1992de962bdSlukem #endif
2002de962bdSlukem
2012de962bdSlukem #ifdef HAVE_TLS
2022de962bdSlukem /* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave
2032de962bdSlukem * them empty to allow new SSL_CTX's to be created from scratch.
2042de962bdSlukem */
2052de962bdSlukem memset( &ld->ld_options.ldo_tls_info, 0,
2062de962bdSlukem sizeof( ld->ld_options.ldo_tls_info ));
2072de962bdSlukem ld->ld_options.ldo_tls_ctx = NULL;
2082de962bdSlukem #endif
2092de962bdSlukem
2102de962bdSlukem if ( gopts->ldo_defludp ) {
2112de962bdSlukem ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp);
2122de962bdSlukem
2132de962bdSlukem if ( ld->ld_options.ldo_defludp == NULL ) goto nomem;
2142de962bdSlukem }
2152de962bdSlukem
2162de962bdSlukem if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem;
2172de962bdSlukem
218*549b59edSchristos ld->ld_options.ldo_local_ip_addrs.local_ip_addrs = NULL;
219*549b59edSchristos if( gopts->ldo_local_ip_addrs.local_ip_addrs ) {
220*549b59edSchristos ld->ld_options.ldo_local_ip_addrs.local_ip_addrs =
221*549b59edSchristos LDAP_STRDUP( gopts->ldo_local_ip_addrs.local_ip_addrs );
222*549b59edSchristos if ( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs == NULL )
223*549b59edSchristos goto nomem;
224*549b59edSchristos }
225*549b59edSchristos
2262de962bdSlukem ld->ld_lberoptions = LBER_USE_DER;
2272de962bdSlukem
2282de962bdSlukem ld->ld_sb = ber_sockbuf_alloc( );
2292de962bdSlukem if ( ld->ld_sb == NULL ) goto nomem;
2302de962bdSlukem
2312de962bdSlukem #ifdef LDAP_R_COMPILE
232d11b170bStron ldap_pvt_thread_mutex_init( &ld->ld_msgid_mutex );
233d11b170bStron ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex );
2342de962bdSlukem ldap_pvt_thread_mutex_init( &ld->ld_req_mutex );
2352de962bdSlukem ldap_pvt_thread_mutex_init( &ld->ld_res_mutex );
236d11b170bStron ldap_pvt_thread_mutex_init( &ld->ld_abandon_mutex );
237d11b170bStron ldap_pvt_thread_mutex_init( &ld->ld_ldcmutex );
2382de962bdSlukem #endif
239d11b170bStron ld->ld_ldcrefcnt = 1;
2402de962bdSlukem *ldp = ld;
2412de962bdSlukem return LDAP_SUCCESS;
2422de962bdSlukem
2432de962bdSlukem nomem:
2442de962bdSlukem ldap_free_select_info( ld->ld_selectinfo );
2452de962bdSlukem ldap_free_urllist( ld->ld_options.ldo_defludp );
2462de962bdSlukem #ifdef HAVE_CYRUS_SASL
2472de962bdSlukem LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
2482de962bdSlukem LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
2492de962bdSlukem LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
2502de962bdSlukem LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
2512de962bdSlukem #endif
252*549b59edSchristos
253*549b59edSchristos #ifdef HAVE_TLS
254*549b59edSchristos /* tls_pin_hashalg and tls_pin share the same buffer */
255*549b59edSchristos if ( ld->ld_options.ldo_tls_pin_hashalg ) {
256*549b59edSchristos LDAP_FREE( ld->ld_options.ldo_tls_pin_hashalg );
257*549b59edSchristos } else {
258*549b59edSchristos LDAP_FREE( ld->ld_options.ldo_tls_pin.bv_val );
259*549b59edSchristos }
260*549b59edSchristos #endif
2612de962bdSlukem LDAP_FREE( (char *)ld );
2622de962bdSlukem return LDAP_NO_MEMORY;
2632de962bdSlukem }
2642de962bdSlukem
2652de962bdSlukem /*
2662de962bdSlukem * ldap_init - initialize the LDAP library. A magic cookie to be used for
2672de962bdSlukem * future communication is returned on success, NULL on failure.
2682de962bdSlukem * "host" may be a space-separated list of hosts or IP addresses
2692de962bdSlukem *
2702de962bdSlukem * Example:
2712de962bdSlukem * LDAP *ld;
2722de962bdSlukem * ld = ldap_init( host, port );
2732de962bdSlukem */
2742de962bdSlukem LDAP *
ldap_init(LDAP_CONST char * defhost,int defport)2752de962bdSlukem ldap_init( LDAP_CONST char *defhost, int defport )
2762de962bdSlukem {
2772de962bdSlukem LDAP *ld;
2782de962bdSlukem int rc;
2792de962bdSlukem
2802de962bdSlukem rc = ldap_create(&ld);
2812de962bdSlukem if ( rc != LDAP_SUCCESS )
2822de962bdSlukem return NULL;
2832de962bdSlukem
2842de962bdSlukem if (defport != 0)
2852de962bdSlukem ld->ld_options.ldo_defport = defport;
2862de962bdSlukem
2872de962bdSlukem if (defhost != NULL) {
2882de962bdSlukem rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, defhost);
2892de962bdSlukem if ( rc != LDAP_SUCCESS ) {
2902de962bdSlukem ldap_ld_free(ld, 1, NULL, NULL);
2912de962bdSlukem return NULL;
2922de962bdSlukem }
2932de962bdSlukem }
2942de962bdSlukem
2952de962bdSlukem return( ld );
2962de962bdSlukem }
2972de962bdSlukem
2982de962bdSlukem
2992de962bdSlukem int
ldap_initialize(LDAP ** ldp,LDAP_CONST char * url)3002de962bdSlukem ldap_initialize( LDAP **ldp, LDAP_CONST char *url )
3012de962bdSlukem {
3022de962bdSlukem int rc;
3032de962bdSlukem LDAP *ld;
3042de962bdSlukem
3052de962bdSlukem *ldp = NULL;
3062de962bdSlukem rc = ldap_create(&ld);
3072de962bdSlukem if ( rc != LDAP_SUCCESS )
3082de962bdSlukem return rc;
3092de962bdSlukem
3102de962bdSlukem if (url != NULL) {
3112de962bdSlukem rc = ldap_set_option(ld, LDAP_OPT_URI, url);
3122de962bdSlukem if ( rc != LDAP_SUCCESS ) {
3132de962bdSlukem ldap_ld_free(ld, 1, NULL, NULL);
3142de962bdSlukem return rc;
3152de962bdSlukem }
3162de962bdSlukem #ifdef LDAP_CONNECTIONLESS
3172de962bdSlukem if (ldap_is_ldapc_url(url))
3182de962bdSlukem LDAP_IS_UDP(ld) = 1;
3192de962bdSlukem #endif
3202de962bdSlukem }
3212de962bdSlukem
3222de962bdSlukem *ldp = ld;
3232de962bdSlukem return LDAP_SUCCESS;
3242de962bdSlukem }
3252de962bdSlukem
3262de962bdSlukem int
ldap_init_fd(ber_socket_t fd,int proto,LDAP_CONST char * url,LDAP ** ldp)3272de962bdSlukem ldap_init_fd(
3282de962bdSlukem ber_socket_t fd,
3292de962bdSlukem int proto,
3302de962bdSlukem LDAP_CONST char *url,
3312de962bdSlukem LDAP **ldp
3322de962bdSlukem )
3332de962bdSlukem {
3342de962bdSlukem int rc;
3352de962bdSlukem LDAP *ld;
3362de962bdSlukem LDAPConn *conn;
337d11b170bStron #ifdef LDAP_CONNECTIONLESS
338d11b170bStron ber_socklen_t len;
339d11b170bStron #endif
3402de962bdSlukem
3412de962bdSlukem *ldp = NULL;
3422de962bdSlukem rc = ldap_create( &ld );
3432de962bdSlukem if( rc != LDAP_SUCCESS )
3442de962bdSlukem return( rc );
3452de962bdSlukem
3462de962bdSlukem if (url != NULL) {
3472de962bdSlukem rc = ldap_set_option(ld, LDAP_OPT_URI, url);
3482de962bdSlukem if ( rc != LDAP_SUCCESS ) {
3492de962bdSlukem ldap_ld_free(ld, 1, NULL, NULL);
3502de962bdSlukem return rc;
3512de962bdSlukem }
3522de962bdSlukem }
3532de962bdSlukem
354d11b170bStron LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
3552de962bdSlukem /* Attach the passed socket as the LDAP's connection */
356d11b170bStron conn = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
3572de962bdSlukem if( conn == NULL ) {
358*549b59edSchristos LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
3592de962bdSlukem ldap_unbind_ext( ld, NULL, NULL );
3602de962bdSlukem return( LDAP_NO_MEMORY );
3612de962bdSlukem }
3624e6df137Slukem if( url )
3634e6df137Slukem conn->lconn_server = ldap_url_dup( ld->ld_options.ldo_defludp );
3642de962bdSlukem ber_sockbuf_ctrl( conn->lconn_sb, LBER_SB_OPT_SET_FD, &fd );
3652de962bdSlukem ld->ld_defconn = conn;
3662de962bdSlukem ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
367d11b170bStron LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
3682de962bdSlukem
3692de962bdSlukem switch( proto ) {
3702de962bdSlukem case LDAP_PROTO_TCP:
3712de962bdSlukem #ifdef LDAP_DEBUG
3722de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
3732de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
3742de962bdSlukem #endif
3752de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
3762de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
3772de962bdSlukem break;
3782de962bdSlukem
3792de962bdSlukem #ifdef LDAP_CONNECTIONLESS
3802de962bdSlukem case LDAP_PROTO_UDP:
381d11b170bStron LDAP_IS_UDP(ld) = 1;
382d11b170bStron if( ld->ld_options.ldo_peer )
383d11b170bStron ldap_memfree( ld->ld_options.ldo_peer );
384d11b170bStron ld->ld_options.ldo_peer = ldap_memcalloc( 1, sizeof( struct sockaddr_storage ) );
385d11b170bStron len = sizeof( struct sockaddr_storage );
386d11b170bStron if( getpeername ( fd, ld->ld_options.ldo_peer, &len ) < 0) {
387d11b170bStron ldap_unbind_ext( ld, NULL, NULL );
388d11b170bStron return( AC_SOCKET_ERROR );
389d11b170bStron }
3902de962bdSlukem #ifdef LDAP_DEBUG
3912de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
3922de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
3932de962bdSlukem #endif
3942de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
3952de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
3962de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
3972de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
3982de962bdSlukem break;
3992de962bdSlukem #endif /* LDAP_CONNECTIONLESS */
4002de962bdSlukem
4012de962bdSlukem case LDAP_PROTO_IPC:
4022de962bdSlukem #ifdef LDAP_DEBUG
4032de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
4042de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
4052de962bdSlukem #endif
4062de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
4072de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
4082de962bdSlukem break;
4092de962bdSlukem
4102de962bdSlukem case LDAP_PROTO_EXT:
4112de962bdSlukem /* caller must supply sockbuf handlers */
4122de962bdSlukem break;
4132de962bdSlukem
4142de962bdSlukem default:
4152de962bdSlukem ldap_unbind_ext( ld, NULL, NULL );
4162de962bdSlukem return LDAP_PARAM_ERROR;
4172de962bdSlukem }
4182de962bdSlukem
4192de962bdSlukem #ifdef LDAP_DEBUG
4202de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
4212de962bdSlukem INT_MAX, (void *)"ldap_" );
4222de962bdSlukem #endif
4232de962bdSlukem
4242de962bdSlukem /* Add the connection to the *LDAP's select pool */
4252de962bdSlukem ldap_mark_select_read( ld, conn->lconn_sb );
4262de962bdSlukem
4272de962bdSlukem *ldp = ld;
4282de962bdSlukem return LDAP_SUCCESS;
4292de962bdSlukem }
4302de962bdSlukem
431d11b170bStron /* Protected by ld_conn_mutex */
4322de962bdSlukem int
ldap_int_open_connection(LDAP * ld,LDAPConn * conn,LDAPURLDesc * srv,int async)4332de962bdSlukem ldap_int_open_connection(
4342de962bdSlukem LDAP *ld,
4352de962bdSlukem LDAPConn *conn,
4362de962bdSlukem LDAPURLDesc *srv,
4372de962bdSlukem int async )
4382de962bdSlukem {
4392de962bdSlukem int rc = -1;
4404e6df137Slukem int proto;
4412de962bdSlukem
442*549b59edSchristos Debug0( LDAP_DEBUG_TRACE, "ldap_int_open_connection\n" );
4432de962bdSlukem
4442de962bdSlukem switch ( proto = ldap_pvt_url_scheme2proto( srv->lud_scheme ) ) {
4452de962bdSlukem case LDAP_PROTO_TCP:
4462de962bdSlukem rc = ldap_connect_to_host( ld, conn->lconn_sb,
4474e6df137Slukem proto, srv, async );
4482de962bdSlukem
4492de962bdSlukem if ( rc == -1 ) return rc;
4502de962bdSlukem #ifdef LDAP_DEBUG
4512de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
4522de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, (void *)"tcp_" );
4532de962bdSlukem #endif
4542de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_tcp,
4552de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
4562de962bdSlukem
4572de962bdSlukem break;
4582de962bdSlukem
4592de962bdSlukem #ifdef LDAP_CONNECTIONLESS
4602de962bdSlukem case LDAP_PROTO_UDP:
4612de962bdSlukem LDAP_IS_UDP(ld) = 1;
4622de962bdSlukem rc = ldap_connect_to_host( ld, conn->lconn_sb,
4634e6df137Slukem proto, srv, async );
4642de962bdSlukem
4652de962bdSlukem if ( rc == -1 ) return rc;
4662de962bdSlukem #ifdef LDAP_DEBUG
4672de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
4682de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, (void *)"udp_" );
4692de962bdSlukem #endif
4702de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_udp,
4712de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
4722de962bdSlukem
4732de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_readahead,
4742de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
4752de962bdSlukem
4762de962bdSlukem break;
4772de962bdSlukem #endif
4782de962bdSlukem case LDAP_PROTO_IPC:
4792de962bdSlukem #ifdef LDAP_PF_LOCAL
4802de962bdSlukem /* only IPC mechanism supported is PF_LOCAL (PF_UNIX) */
4812de962bdSlukem rc = ldap_connect_to_path( ld, conn->lconn_sb,
4824e6df137Slukem srv, async );
4832de962bdSlukem if ( rc == -1 ) return rc;
4842de962bdSlukem #ifdef LDAP_DEBUG
4852de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
4862de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, (void *)"ipc_" );
4872de962bdSlukem #endif
4882de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_fd,
4892de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
4902de962bdSlukem
4912de962bdSlukem break;
4922de962bdSlukem #endif /* LDAP_PF_LOCAL */
4932de962bdSlukem default:
4942de962bdSlukem return -1;
4952de962bdSlukem break;
4962de962bdSlukem }
4972de962bdSlukem
4982de962bdSlukem conn->lconn_created = time( NULL );
4992de962bdSlukem
5002de962bdSlukem #ifdef LDAP_DEBUG
5012de962bdSlukem ber_sockbuf_add_io( conn->lconn_sb, &ber_sockbuf_io_debug,
5022de962bdSlukem INT_MAX, (void *)"ldap_" );
5032de962bdSlukem #endif
5042de962bdSlukem
5052de962bdSlukem #ifdef LDAP_CONNECTIONLESS
5062de962bdSlukem if( proto == LDAP_PROTO_UDP ) return 0;
5072de962bdSlukem #endif
5082de962bdSlukem
5092de962bdSlukem #ifdef HAVE_TLS
5104e27b3e8Schristos if ((rc == 0 || rc == -2) && ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
511d11b170bStron strcmp( srv->lud_scheme, "ldaps" ) == 0 ))
5122de962bdSlukem {
5132de962bdSlukem ++conn->lconn_refcnt; /* avoid premature free */
5142de962bdSlukem
5152de962bdSlukem rc = ldap_int_tls_start( ld, conn, srv );
5162de962bdSlukem
5172de962bdSlukem --conn->lconn_refcnt;
5182de962bdSlukem
5192de962bdSlukem if (rc != LDAP_SUCCESS) {
5204e27b3e8Schristos /* process connection callbacks */
5214e27b3e8Schristos {
5224e27b3e8Schristos struct ldapoptions *lo;
5234e27b3e8Schristos ldaplist *ll;
5244e27b3e8Schristos ldap_conncb *cb;
5254e27b3e8Schristos
5264e27b3e8Schristos lo = &ld->ld_options;
5274e27b3e8Schristos LDAP_MUTEX_LOCK( &lo->ldo_mutex );
5284e27b3e8Schristos if ( lo->ldo_conn_cbs ) {
5294e27b3e8Schristos for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
5304e27b3e8Schristos cb = ll->ll_data;
5314e27b3e8Schristos cb->lc_del( ld, conn->lconn_sb, cb );
5324e27b3e8Schristos }
5334e27b3e8Schristos }
5344e27b3e8Schristos LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
5354e27b3e8Schristos lo = LDAP_INT_GLOBAL_OPT();
5364e27b3e8Schristos LDAP_MUTEX_LOCK( &lo->ldo_mutex );
5374e27b3e8Schristos if ( lo->ldo_conn_cbs ) {
5384e27b3e8Schristos for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
5394e27b3e8Schristos cb = ll->ll_data;
5404e27b3e8Schristos cb->lc_del( ld, conn->lconn_sb, cb );
5414e27b3e8Schristos }
5424e27b3e8Schristos }
5434e27b3e8Schristos LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
5444e27b3e8Schristos }
545255afcfeSchristos ber_int_sb_close( conn->lconn_sb );
5462de962bdSlukem return -1;
5472de962bdSlukem }
5482de962bdSlukem }
5492de962bdSlukem #endif
5502de962bdSlukem
5512de962bdSlukem return( 0 );
5522de962bdSlukem }
5532de962bdSlukem
554d11b170bStron /*
555d11b170bStron * ldap_open_internal_connection - open connection and set file descriptor
556d11b170bStron *
557d11b170bStron * note: ldap_init_fd() may be preferable
558d11b170bStron */
5592de962bdSlukem
5602de962bdSlukem int
ldap_open_internal_connection(LDAP ** ldp,ber_socket_t * fdp)5612de962bdSlukem ldap_open_internal_connection( LDAP **ldp, ber_socket_t *fdp )
5622de962bdSlukem {
5632de962bdSlukem int rc;
5642de962bdSlukem LDAPConn *c;
5652de962bdSlukem LDAPRequest *lr;
566d11b170bStron LDAP *ld;
5672de962bdSlukem
568d11b170bStron rc = ldap_create( &ld );
5692de962bdSlukem if( rc != LDAP_SUCCESS ) {
5702de962bdSlukem *ldp = NULL;
5712de962bdSlukem return( rc );
5722de962bdSlukem }
5732de962bdSlukem
5742de962bdSlukem /* Make it appear that a search request, msgid 0, was sent */
5752de962bdSlukem lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ));
5762de962bdSlukem if( lr == NULL ) {
577d11b170bStron ldap_unbind_ext( ld, NULL, NULL );
5782de962bdSlukem *ldp = NULL;
5792de962bdSlukem return( LDAP_NO_MEMORY );
5802de962bdSlukem }
5812de962bdSlukem memset(lr, 0, sizeof( LDAPRequest ));
5822de962bdSlukem lr->lr_msgid = 0;
5832de962bdSlukem lr->lr_status = LDAP_REQST_INPROGRESS;
5842de962bdSlukem lr->lr_res_errno = LDAP_SUCCESS;
5852de962bdSlukem /* no mutex lock needed, we just created this ld here */
586*549b59edSchristos rc = ldap_tavl_insert( &ld->ld_requests, lr, ldap_req_cmp, ldap_avl_dup_error );
587*549b59edSchristos assert( rc == LDAP_SUCCESS );
5882de962bdSlukem
589d11b170bStron LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
5902de962bdSlukem /* Attach the passed socket as the *LDAP's connection */
591d11b170bStron c = ldap_new_connection( ld, NULL, 1, 0, NULL, 0, 0 );
5922de962bdSlukem if( c == NULL ) {
593d11b170bStron ldap_unbind_ext( ld, NULL, NULL );
5942de962bdSlukem *ldp = NULL;
595d11b170bStron LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
5962de962bdSlukem return( LDAP_NO_MEMORY );
5972de962bdSlukem }
5982de962bdSlukem ber_sockbuf_ctrl( c->lconn_sb, LBER_SB_OPT_SET_FD, fdp );
5992de962bdSlukem #ifdef LDAP_DEBUG
6002de962bdSlukem ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_debug,
6012de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, (void *)"int_" );
6022de962bdSlukem #endif
6032de962bdSlukem ber_sockbuf_add_io( c->lconn_sb, &ber_sockbuf_io_tcp,
6042de962bdSlukem LBER_SBIOD_LEVEL_PROVIDER, NULL );
605d11b170bStron ld->ld_defconn = c;
606d11b170bStron LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
6072de962bdSlukem
6082de962bdSlukem /* Add the connection to the *LDAP's select pool */
609d11b170bStron ldap_mark_select_read( ld, c->lconn_sb );
6102de962bdSlukem
6112de962bdSlukem /* Make this connection an LDAP V3 protocol connection */
6122de962bdSlukem rc = LDAP_VERSION3;
613d11b170bStron ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &rc );
614d11b170bStron *ldp = ld;
615d11b170bStron
616d11b170bStron ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */
6172de962bdSlukem
6182de962bdSlukem return( LDAP_SUCCESS );
6192de962bdSlukem }
620d11b170bStron
621d11b170bStron LDAP *
ldap_dup(LDAP * old)622d11b170bStron ldap_dup( LDAP *old )
623d11b170bStron {
624d11b170bStron LDAP *ld;
625d11b170bStron
626d11b170bStron if ( old == NULL ) {
627d11b170bStron return( NULL );
628d11b170bStron }
629d11b170bStron
630*549b59edSchristos Debug0( LDAP_DEBUG_TRACE, "ldap_dup\n" );
631d11b170bStron
632d11b170bStron if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
633d11b170bStron return( NULL );
634d11b170bStron }
635d11b170bStron
636d11b170bStron LDAP_MUTEX_LOCK( &old->ld_ldcmutex );
637d11b170bStron ld->ldc = old->ldc;
638d11b170bStron old->ld_ldcrefcnt++;
639d11b170bStron LDAP_MUTEX_UNLOCK( &old->ld_ldcmutex );
640d11b170bStron return ( ld );
641d11b170bStron }
642d11b170bStron
643d11b170bStron int
ldap_int_check_async_open(LDAP * ld,ber_socket_t sd)644d11b170bStron ldap_int_check_async_open( LDAP *ld, ber_socket_t sd )
645d11b170bStron {
646d11b170bStron struct timeval tv = { 0 };
647d11b170bStron int rc;
648d11b170bStron
649d11b170bStron rc = ldap_int_poll( ld, sd, &tv, 1 );
650d11b170bStron switch ( rc ) {
651d11b170bStron case 0:
652d11b170bStron /* now ready to start tls */
653d11b170bStron ld->ld_defconn->lconn_status = LDAP_CONNST_CONNECTED;
654d11b170bStron break;
655d11b170bStron
656d11b170bStron default:
657d11b170bStron ld->ld_errno = LDAP_CONNECT_ERROR;
658d11b170bStron return -1;
659d11b170bStron
660d11b170bStron case -2:
661d11b170bStron /* connect not completed yet */
662d11b170bStron ld->ld_errno = LDAP_X_CONNECTING;
663d11b170bStron return rc;
664d11b170bStron }
665d11b170bStron
666d11b170bStron #ifdef HAVE_TLS
667d11b170bStron if ( ld->ld_options.ldo_tls_mode == LDAP_OPT_X_TLS_HARD ||
668d11b170bStron !strcmp( ld->ld_defconn->lconn_server->lud_scheme, "ldaps" )) {
669d11b170bStron
670d11b170bStron ++ld->ld_defconn->lconn_refcnt; /* avoid premature free */
671d11b170bStron
672d11b170bStron rc = ldap_int_tls_start( ld, ld->ld_defconn, ld->ld_defconn->lconn_server );
673d11b170bStron
674d11b170bStron --ld->ld_defconn->lconn_refcnt;
675d11b170bStron }
676d11b170bStron #endif
677d11b170bStron return rc;
678d11b170bStron }
679