/* * Initialize TLS subsystem. Should be called only once. */ static int tlso_init( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); #ifdef HAVE_EBCDIC { char *file = LDAP_STRDUP( lo->ldo_tls_randfile ); if ( file ) __atoe( file ); (void) tlso_seed_PRNG( file ); LDAP_FREE( file ); } #else (void) tlso_seed_PRNG( lo->ldo_tls_randfile ); #endif #if OPENSSL_VERSION_NUMBER < 0x10100000 SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_digests(); #else OPENSSL_init_ssl(0, NULL); #endif /* FIXME: mod_ssl does this */ X509V3_add_standard_extensions(); return 0; }
/* * Tear down the TLS subsystem. Should only be called once. */ void ldap_pvt_tls_destroy( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); ldap_int_tls_destroy( lo ); tls_imp->ti_tls_destroy(); }
/* * initialize the default context */ int ldap_pvt_tls_init_def_ctx( int is_server ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); int rc; LDAP_MUTEX_LOCK( &tls_def_ctx_mutex ); rc = ldap_int_tls_init_ctx( lo, is_server ); LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex ); return rc; }
/* * Tear down the TLS subsystem. Should only be called once. */ static void tlso_destroy( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); EVP_cleanup(); ERR_remove_state(0); ERR_free_strings(); if ( lo->ldo_tls_randfile ) { LDAP_FREE( lo->ldo_tls_randfile ); lo->ldo_tls_randfile = NULL; } }
/* * initialize the default context */ int ldap_pvt_tls_init_def_ctx( int is_server ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); int rc; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_lock( &tls_def_ctx_mutex ); #endif rc = ldap_int_tls_init_ctx( lo, is_server ); #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_unlock( &tls_def_ctx_mutex ); #endif return rc; }
/* * Initialize TLS subsystem. Should be called only once. */ static int tlsg_init( void ) { #ifdef HAVE_GCRYPT_RAND struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); if ( lo->ldo_tls_randfile && gcry_control( GCRYCTL_SET_RNDEGD_SOCKET, lo->ldo_tls_randfile )) { Debug( LDAP_DEBUG_ANY, "TLS: gcry_control GCRYCTL_SET_RNDEGD_SOCKET failed\n", 0, 0, 0); return -1; } #endif gnutls_global_init(); #ifndef HAVE_CIPHERSUITES /* GNUtls cipher suite handling: The library ought to parse suite * names for us, but it doesn't. It will return a list of suite names * that it supports, so we can do parsing ourselves. It ought to tell * us how long the list is, but it doesn't do that either, so we just * have to count it manually... */ { int i = 0; tls_cipher_suite *ptr, tmp; char cs_id[2]; while ( gnutls_cipher_suite_info( i, cs_id, &tmp.kx, &tmp.cipher, &tmp.mac, &tmp.version )) i++; tlsg_n_ciphers = i; /* Store a copy */ tlsg_ciphers = LDAP_MALLOC(tlsg_n_ciphers * sizeof(tls_cipher_suite)); if ( !tlsg_ciphers ) return -1; for ( i=0; i<tlsg_n_ciphers; i++ ) { tlsg_ciphers[i].name = gnutls_cipher_suite_info( i, cs_id, &tlsg_ciphers[i].kx, &tlsg_ciphers[i].cipher, &tlsg_ciphers[i].mac, &tlsg_ciphers[i].version ); } } #endif return 0; }
/* * Tear down the TLS subsystem. Should only be called once. */ static void tlso_destroy( void ) { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); EVP_cleanup(); #if OPENSSL_VERSION_NUMBER < 0x10000000 ERR_remove_state(0); #else ERR_remove_thread_state(NULL); #endif ERR_free_strings(); if ( lo->ldo_tls_randfile ) { LDAP_FREE( lo->ldo_tls_randfile ); lo->ldo_tls_randfile = NULL; } }
static tls_session * alloc_handle( void *ctx_arg, int is_server ) { tls_ctx *ctx; tls_session *ssl; if ( ctx_arg ) { ctx = ctx_arg; } else { struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL; ctx = lo->ldo_tls_ctx; } ssl = tls_imp->ti_session_new( ctx, is_server ); if ( ssl == NULL ) { Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0); return NULL; } return ssl; }
/* protected by ld_conn_mutex */ void ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind ) { LDAPConn *tmplc, *prevlc; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection %d %d\n", force, unbind, 0 ); if ( force || --lc->lconn_refcnt <= 0 ) { /* remove from connections list first */ for ( prevlc = NULL, tmplc = ld->ld_conns; tmplc != NULL; tmplc = tmplc->lconn_next ) { if ( tmplc == lc ) { if ( prevlc == NULL ) { ld->ld_conns = tmplc->lconn_next; } else { prevlc->lconn_next = tmplc->lconn_next; } if ( ld->ld_defconn == lc ) { ld->ld_defconn = NULL; } break; } prevlc = tmplc; } /* process connection callbacks */ { struct ldapoptions *lo; ldaplist *ll; ldap_conncb *cb; lo = &ld->ld_options; LDAP_MUTEX_LOCK( &lo->ldo_mutex ); if ( lo->ldo_conn_cbs ) { for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { cb = ll->ll_data; cb->lc_del( ld, lc->lconn_sb, cb ); } } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); lo = LDAP_INT_GLOBAL_OPT(); LDAP_MUTEX_LOCK( &lo->ldo_mutex ); if ( lo->ldo_conn_cbs ) { for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) { cb = ll->ll_data; cb->lc_del( ld, lc->lconn_sb, cb ); } } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); } if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) { ldap_mark_select_clear( ld, lc->lconn_sb ); if ( unbind ) { ldap_send_unbind( ld, lc->lconn_sb, NULL, NULL ); } } if ( lc->lconn_ber != NULL ) { ber_free( lc->lconn_ber, 1 ); } ldap_int_sasl_close( ld, lc ); #ifdef HAVE_GSSAPI ldap_int_gssapi_close( ld, lc ); #endif ldap_free_urllist( lc->lconn_server ); /* FIXME: is this at all possible? * ldap_ld_free() in unbind.c calls ldap_free_connection() * with force == 1 __after__ explicitly calling * ldap_free_request() on all requests */ if ( force ) { LDAPRequest *lr; for ( lr = ld->ld_requests; lr; ) { LDAPRequest *lr_next = lr->lr_next; if ( lr->lr_conn == lc ) { ldap_free_request_int( ld, lr ); } lr = lr_next; } } if ( lc->lconn_sb != ld->ld_sb ) { ber_sockbuf_free( lc->lconn_sb ); } else { ber_int_sb_close( lc->lconn_sb ); } if ( lc->lconn_rebind_queue != NULL) { int i; for( i = 0; lc->lconn_rebind_queue[i] != NULL; i++ ) { LDAP_VFREE( lc->lconn_rebind_queue[i] ); } LDAP_FREE( lc->lconn_rebind_queue ); } LDAP_FREE( lc ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: actually freed\n", 0, 0, 0 ); } else { lc->lconn_lastused = time( NULL ); Debug( LDAP_DEBUG_TRACE, "ldap_free_connection: refcnt %d\n", lc->lconn_refcnt, 0, 0 ); } }
int ldap_get_option( LDAP *ld, int option, void *outvalue) { struct ldapoptions *lo; int rc = LDAP_OPT_ERROR; /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if (NULL == lo) { return LDAP_NO_MEMORY; } if( lo->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(lo, NULL); if ( lo->ldo_valid != LDAP_INITIALIZED ) return LDAP_LOCAL_ERROR; } if(ld != NULL) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } if(outvalue == NULL) { /* no place to get to */ return LDAP_OPT_ERROR; } LDAP_MUTEX_LOCK( &lo->ldo_mutex ); switch(option) { case LDAP_OPT_API_INFO: { struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue; if(info == NULL) { /* outvalue must point to an apiinfo structure */ break; /* LDAP_OPT_ERROR */ } if(info->ldapai_info_version != LDAP_API_INFO_VERSION) { /* api info version mismatch */ info->ldapai_info_version = LDAP_API_INFO_VERSION; break; /* LDAP_OPT_ERROR */ } info->ldapai_api_version = LDAP_API_VERSION; info->ldapai_protocol_version = LDAP_VERSION_MAX; if(features[0].ldapaif_name == NULL) { info->ldapai_extensions = NULL; } else { int i; info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) * sizeof(features)/sizeof(LDAPAPIFeatureInfo)); for(i=0; features[i].ldapaif_name != NULL; i++) { info->ldapai_extensions[i] = LDAP_STRDUP(features[i].ldapaif_name); } info->ldapai_extensions[i] = NULL; } info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME); info->ldapai_vendor_version = LDAP_VENDOR_VERSION; rc = LDAP_OPT_SUCCESS; break; } break; case LDAP_OPT_DESC: if( ld == NULL || ld->ld_sb == NULL ) { /* bad param */ break; } ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SOCKBUF: if( ld == NULL ) break; *(Sockbuf **)outvalue = ld->ld_sb; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMEOUT: /* the caller has to free outvalue ! */ if ( lo->ldo_tm_api.tv_sec < 0 ) { *(void **)outvalue = NULL; } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) { break; /* LDAP_OPT_ERROR */ } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NETWORK_TIMEOUT: /* the caller has to free outvalue ! */ if ( lo->ldo_tm_net.tv_sec < 0 ) { *(void **)outvalue = NULL; } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) { break; /* LDAP_OPT_ERROR */ } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DEREF: * (int *) outvalue = lo->ldo_deref; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SIZELIMIT: * (int *) outvalue = lo->ldo_sizelimit; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMELIMIT: * (int *) outvalue = lo->ldo_timelimit; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REFERRALS: * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESTART: * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_PROTOCOL_VERSION: * (int *) outvalue = lo->ldo_version; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SERVER_CONTROLS: * (LDAPControl ***) outvalue = ldap_controls_dup( lo->ldo_sctrls ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CLIENT_CONTROLS: * (LDAPControl ***) outvalue = ldap_controls_dup( lo->ldo_cctrls ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_HOST_NAME: * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_URI: * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DEFBASE: if( lo->ldo_defbase == NULL ) { * (char **) outvalue = NULL; } else { * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_ASYNC: * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_CB: { /* Getting deletes the specified callback */ ldaplist **ll = &lo->ldo_conn_cbs; for (;*ll;ll = &(*ll)->ll_next) { if ((*ll)->ll_data == outvalue) { ldaplist *lc = *ll; *ll = lc->ll_next; LDAP_FREE(lc); break; } } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESULT_CODE: if(ld == NULL) { /* bad param */ break; } * (int *) outvalue = ld->ld_errno; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DIAGNOSTIC_MESSAGE: if(ld == NULL) { /* bad param */ break; } if( ld->ld_error == NULL ) { * (char **) outvalue = NULL; } else { * (char **) outvalue = LDAP_STRDUP(ld->ld_error); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_MATCHED_DN: if(ld == NULL) { /* bad param */ break; } if( ld->ld_matched == NULL ) { * (char **) outvalue = NULL; } else { * (char **) outvalue = LDAP_STRDUP( ld->ld_matched ); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REFERRAL_URLS: if(ld == NULL) { /* bad param */ break; } if( ld->ld_referrals == NULL ) { * (char ***) outvalue = NULL; } else { * (char ***) outvalue = ldap_value_dup(ld->ld_referrals); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_API_FEATURE_INFO: { LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue; int i; if(info == NULL) break; /* LDAP_OPT_ERROR */ if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) { /* api info version mismatch */ info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; break; /* LDAP_OPT_ERROR */ } if(info->ldapaif_name == NULL) break; /* LDAP_OPT_ERROR */ for(i=0; features[i].ldapaif_name != NULL; i++) { if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) { info->ldapaif_version = features[i].ldapaif_version; rc = LDAP_OPT_SUCCESS; break; } } } break; case LDAP_OPT_DEBUG_LEVEL: * (int *) outvalue = lo->ldo_debug; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SESSION_REFCNT: if(ld == NULL) { /* bad param */ break; } LDAP_MUTEX_LOCK( &ld->ld_ldcmutex ); * (int *) outvalue = ld->ld_ldcrefcnt; LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex ); rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_IDLE: * (int *) outvalue = lo->ldo_keepalive_idle; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_PROBES: * (int *) outvalue = lo->ldo_keepalive_probes; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_INTERVAL: * (int *) outvalue = lo->ldo_keepalive_interval; rc = LDAP_OPT_SUCCESS; break; default: #ifdef HAVE_TLS if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) { rc = LDAP_OPT_SUCCESS; break; } #endif #ifdef HAVE_CYRUS_SASL if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) { rc = LDAP_OPT_SUCCESS; break; } #endif #ifdef HAVE_GSSAPI if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) { rc = LDAP_OPT_SUCCESS; break; } #endif /* bad param */ break; } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( rc ); }
int ldap_set_option( LDAP *ld, int option, LDAP_CONST void *invalue) { struct ldapoptions *lo; int *dbglvl = NULL; int rc = LDAP_OPT_ERROR; /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if (lo == NULL) { return LDAP_NO_MEMORY; } /* * The architecture to turn on debugging has a chicken and egg * problem. Thus, we introduce a fix here. */ if (option == LDAP_OPT_DEBUG_LEVEL) { dbglvl = (int *) invalue; } if( lo->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(lo, dbglvl); if ( lo->ldo_valid != LDAP_INITIALIZED ) return LDAP_LOCAL_ERROR; } if(ld != NULL) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } LDAP_MUTEX_LOCK( &lo->ldo_mutex ); switch ( option ) { /* options with boolean values */ case LDAP_OPT_REFERRALS: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESTART: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART); } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_ASYNC: if(invalue == LDAP_OPT_OFF) { LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC); } else { LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC); } rc = LDAP_OPT_SUCCESS; break; /* options which can withstand invalue == NULL */ case LDAP_OPT_SERVER_CONTROLS: { LDAPControl *const *controls = (LDAPControl *const *) invalue; if( lo->ldo_sctrls ) ldap_controls_free( lo->ldo_sctrls ); if( controls == NULL || *controls == NULL ) { lo->ldo_sctrls = NULL; rc = LDAP_OPT_SUCCESS; break; } lo->ldo_sctrls = ldap_controls_dup( controls ); if(lo->ldo_sctrls == NULL) { /* memory allocation error ? */ break; /* LDAP_OPT_ERROR */ } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CLIENT_CONTROLS: { LDAPControl *const *controls = (LDAPControl *const *) invalue; if( lo->ldo_cctrls ) ldap_controls_free( lo->ldo_cctrls ); if( controls == NULL || *controls == NULL ) { lo->ldo_cctrls = NULL; rc = LDAP_OPT_SUCCESS; break; } lo->ldo_cctrls = ldap_controls_dup( controls ); if(lo->ldo_cctrls == NULL) { /* memory allocation error ? */ break; /* LDAP_OPT_ERROR */ } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_HOST_NAME: { const char *host = (const char *) invalue; LDAPURLDesc *ludlist = NULL; rc = LDAP_OPT_SUCCESS; if(host != NULL) { rc = ldap_url_parsehosts( &ludlist, host, lo->ldo_defport ? lo->ldo_defport : LDAP_PORT ); } else if(ld == NULL) { /* * must want global default returned * to initial condition. */ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else { /* * must want the session default * updated to the current global default */ ludlist = ldap_url_duplist( ldap_int_global_options.ldo_defludp); if (ludlist == NULL) rc = LDAP_NO_MEMORY; } if (rc == LDAP_OPT_SUCCESS) { if (lo->ldo_defludp != NULL) ldap_free_urllist(lo->ldo_defludp); lo->ldo_defludp = ludlist; } break; } case LDAP_OPT_URI: { const char *urls = (const char *) invalue; LDAPURLDesc *ludlist = NULL; rc = LDAP_OPT_SUCCESS; if(urls != NULL) { rc = ldap_url_parselist_ext(&ludlist, urls, NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else if(ld == NULL) { /* * must want global default returned * to initial condition. */ rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); } else { /* * must want the session default * updated to the current global default */ ludlist = ldap_url_duplist( ldap_int_global_options.ldo_defludp); if (ludlist == NULL) rc = LDAP_URL_ERR_MEM; } switch (rc) { case LDAP_URL_SUCCESS: /* Success */ rc = LDAP_SUCCESS; break; case LDAP_URL_ERR_MEM: /* can't allocate memory space */ rc = LDAP_NO_MEMORY; break; case LDAP_URL_ERR_PARAM: /* parameter is bad */ case LDAP_URL_ERR_BADSCHEME: /* URL doesn't begin with "ldap[si]://" */ case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */ case LDAP_URL_ERR_BADURL: /* URL is bad */ case LDAP_URL_ERR_BADHOST: /* host port is bad */ case LDAP_URL_ERR_BADATTRS: /* bad (or missing) attributes */ case LDAP_URL_ERR_BADSCOPE: /* scope string is invalid (or missing) */ case LDAP_URL_ERR_BADFILTER: /* bad or missing filter */ case LDAP_URL_ERR_BADEXTS: /* bad or missing extensions */ rc = LDAP_PARAM_ERROR; break; } if (rc == LDAP_SUCCESS) { if (lo->ldo_defludp != NULL) ldap_free_urllist(lo->ldo_defludp); lo->ldo_defludp = ludlist; } break; } case LDAP_OPT_DEFBASE: { const char *newbase = (const char *) invalue; char *defbase = NULL; if ( newbase != NULL ) { defbase = LDAP_STRDUP( newbase ); if ( defbase == NULL ) { rc = LDAP_NO_MEMORY; break; } } else if ( ld != NULL ) { defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase ); if ( defbase == NULL ) { rc = LDAP_NO_MEMORY; break; } } if ( lo->ldo_defbase != NULL ) LDAP_FREE( lo->ldo_defbase ); lo->ldo_defbase = defbase; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DIAGNOSTIC_MESSAGE: { const char *err = (const char *) invalue; if(ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_error ) { LDAP_FREE(ld->ld_error); ld->ld_error = NULL; } if ( err ) { ld->ld_error = LDAP_STRDUP(err); } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_MATCHED_DN: { const char *matched = (const char *) invalue; if (ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_matched ) { LDAP_FREE(ld->ld_matched); ld->ld_matched = NULL; } if ( matched ) { ld->ld_matched = LDAP_STRDUP( matched ); } } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REFERRAL_URLS: { char *const *referrals = (char *const *) invalue; if(ld == NULL) { /* need a struct ldap */ break; /* LDAP_OPT_ERROR */ } if( ld->ld_referrals ) { LDAP_VFREE(ld->ld_referrals); } if ( referrals ) { ld->ld_referrals = ldap_value_dup(referrals); } } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_rebind_proc() */ case LDAP_OPT_REBIND_PROC: { lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_REBIND_PARAMS: { lo->ldo_rebind_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_nextref_proc() */ case LDAP_OPT_NEXTREF_PROC: { lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NEXTREF_PARAMS: { lo->ldo_nextref_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* Only accessed from inside this function by ldap_set_urllist_proc() */ case LDAP_OPT_URLLIST_PROC: { lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_URLLIST_PARAMS: { lo->ldo_urllist_params = (void *)invalue; } rc = LDAP_OPT_SUCCESS; break; /* read-only options */ case LDAP_OPT_API_INFO: case LDAP_OPT_DESC: case LDAP_OPT_SOCKBUF: case LDAP_OPT_API_FEATURE_INFO: break; /* LDAP_OPT_ERROR */ /* options which cannot withstand invalue == NULL */ case LDAP_OPT_DEREF: case LDAP_OPT_SIZELIMIT: case LDAP_OPT_TIMELIMIT: case LDAP_OPT_PROTOCOL_VERSION: case LDAP_OPT_RESULT_CODE: case LDAP_OPT_DEBUG_LEVEL: case LDAP_OPT_TIMEOUT: case LDAP_OPT_NETWORK_TIMEOUT: case LDAP_OPT_CONNECT_CB: case LDAP_OPT_X_KEEPALIVE_IDLE: case LDAP_OPT_X_KEEPALIVE_PROBES : case LDAP_OPT_X_KEEPALIVE_INTERVAL : if(invalue == NULL) { /* no place to set from */ LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_ERROR ); } break; default: #ifdef HAVE_TLS if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif #ifdef HAVE_CYRUS_SASL if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif #ifdef HAVE_GSSAPI if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 ) { LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( LDAP_OPT_SUCCESS ); } #endif /* bad param */ break; /* LDAP_OPT_ERROR */ } /* options which cannot withstand invalue == NULL */ switch(option) { case LDAP_OPT_DEREF: /* FIXME: check value for protocol compliance? */ lo->ldo_deref = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_SIZELIMIT: /* FIXME: check value for protocol compliance? */ lo->ldo_sizelimit = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMELIMIT: /* FIXME: check value for protocol compliance? */ lo->ldo_timelimit = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_TIMEOUT: { const struct timeval *tv = (const struct timeval *) invalue; lo->ldo_tm_api = *tv; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_NETWORK_TIMEOUT: { const struct timeval *tv = (const struct timeval *) invalue; lo->ldo_tm_net = *tv; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_PROTOCOL_VERSION: { int vers = * (const int *) invalue; if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) { /* not supported */ break; } lo->ldo_version = vers; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_RESULT_CODE: { int err = * (const int *) invalue; if(ld == NULL) { /* need a struct ldap */ break; } ld->ld_errno = err; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_DEBUG_LEVEL: lo->ldo_debug = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_CONNECT_CB: { /* setting pushes the callback */ ldaplist *ll; ll = LDAP_MALLOC( sizeof( *ll )); ll->ll_data = (void *)invalue; ll->ll_next = lo->ldo_conn_cbs; lo->ldo_conn_cbs = ll; } rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_IDLE: lo->ldo_keepalive_idle = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_PROBES : lo->ldo_keepalive_probes = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; case LDAP_OPT_X_KEEPALIVE_INTERVAL : lo->ldo_keepalive_interval = * (const int *) invalue; rc = LDAP_OPT_SUCCESS; break; } LDAP_MUTEX_UNLOCK( &lo->ldo_mutex ); return ( rc ); }
int ldap_create( LDAP **ldp ) { LDAP *ld; struct ldapoptions *gopts; *ldp = NULL; /* Get pointer to global option structure */ if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { return LDAP_NO_MEMORY; } /* Initialize the global options, if not already done. */ if( gopts->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(gopts, NULL); if ( gopts->ldo_valid != LDAP_INITIALIZED ) return LDAP_LOCAL_ERROR; } Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 ); if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { return( LDAP_NO_MEMORY ); } /* copy the global options */ AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options)); ld->ld_valid = LDAP_VALID_SESSION; /* but not pointers to malloc'ed items */ ld->ld_options.ldo_sctrls = NULL; ld->ld_options.ldo_cctrls = NULL; ld->ld_options.ldo_defludp = NULL; #ifdef HAVE_CYRUS_SASL ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL; ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL; ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL; ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL; #endif #ifdef HAVE_TLS /* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave * them empty to allow new SSL_CTX's to be created from scratch. */ memset( &ld->ld_options.ldo_tls_info, 0, sizeof( ld->ld_options.ldo_tls_info )); ld->ld_options.ldo_tls_ctx = NULL; #endif if ( gopts->ldo_defludp ) { ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); if ( ld->ld_options.ldo_defludp == NULL ) goto nomem; } if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem; ld->ld_lberoptions = LBER_USE_DER; ld->ld_sb = ber_sockbuf_alloc( ); if ( ld->ld_sb == NULL ) goto nomem; #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &ld->ld_req_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_res_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex ); #endif *ldp = ld; return LDAP_SUCCESS; nomem: ldap_free_select_info( ld->ld_selectinfo ); ldap_free_urllist( ld->ld_options.ldo_defludp ); #ifdef HAVE_CYRUS_SASL LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); #endif LDAP_FREE( (char *)ld ); return LDAP_NO_MEMORY; }
int ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) { struct ldapoptions *lo; if( ld != NULL ) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } else { /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if ( lo == NULL ) { return LDAP_NO_MEMORY; } } switch( option ) { case LDAP_OPT_X_TLS: if ( !arg ) return -1; switch( *(int *) arg ) { case LDAP_OPT_X_TLS_NEVER: case LDAP_OPT_X_TLS_DEMAND: case LDAP_OPT_X_TLS_ALLOW: case LDAP_OPT_X_TLS_TRY: case LDAP_OPT_X_TLS_HARD: if (lo != NULL) { lo->ldo_tls_mode = *(int *)arg; } return 0; } return -1; case LDAP_OPT_X_TLS_CTX: if ( lo->ldo_tls_ctx ) ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); lo->ldo_tls_ctx = arg; tls_ctx_ref( lo->ldo_tls_ctx ); return 0; case LDAP_OPT_X_TLS_CONNECT_CB: lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg; return 0; case LDAP_OPT_X_TLS_CONNECT_ARG: lo->ldo_tls_connect_arg = arg; return 0; case LDAP_OPT_X_TLS_CACERTFILE: if ( lo->ldo_tls_cacertfile ) LDAP_FREE( lo->ldo_tls_cacertfile ); lo->ldo_tls_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_CACERTDIR: if ( lo->ldo_tls_cacertdir ) LDAP_FREE( lo->ldo_tls_cacertdir ); lo->ldo_tls_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_CERTFILE: if ( lo->ldo_tls_certfile ) LDAP_FREE( lo->ldo_tls_certfile ); lo->ldo_tls_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_KEYFILE: if ( lo->ldo_tls_keyfile ) LDAP_FREE( lo->ldo_tls_keyfile ); lo->ldo_tls_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_DHFILE: if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile ); lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile ); lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_REQUIRE_CERT: if ( !arg ) return -1; switch( *(int *) arg ) { case LDAP_OPT_X_TLS_NEVER: case LDAP_OPT_X_TLS_DEMAND: case LDAP_OPT_X_TLS_ALLOW: case LDAP_OPT_X_TLS_TRY: case LDAP_OPT_X_TLS_HARD: lo->ldo_tls_require_cert = * (int *) arg; return 0; } return -1; #ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ if ( !arg ) return -1; switch( *(int *) arg ) { case LDAP_OPT_X_TLS_CRL_NONE: case LDAP_OPT_X_TLS_CRL_PEER: case LDAP_OPT_X_TLS_CRL_ALL: lo->ldo_tls_crlcheck = * (int *) arg; return 0; } return -1; #endif case LDAP_OPT_X_TLS_CIPHER_SUITE: if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite ); lo->ldo_tls_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL; return 0; case LDAP_OPT_X_TLS_PROTOCOL_MIN: if ( !arg ) return -1; lo->ldo_tls_protocol_min = *(int *)arg; return 0; case LDAP_OPT_X_TLS_RANDOM_FILE: if ( ld != NULL ) return -1; if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile ); lo->ldo_tls_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; break; case LDAP_OPT_X_TLS_NEWCTX: if ( !arg ) return -1; if ( lo->ldo_tls_ctx ) ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); lo->ldo_tls_ctx = NULL; return ldap_int_tls_init_ctx( lo, *(int *)arg ); default: return -1; } return 0; }
int ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) { struct ldapoptions *lo; if( option == LDAP_OPT_X_TLS_PACKAGE ) { *(char **)arg = LDAP_STRDUP( tls_imp->ti_name ); return 0; } if( ld != NULL ) { assert( LDAP_VALID( ld ) ); if( !LDAP_VALID( ld ) ) { return LDAP_OPT_ERROR; } lo = &ld->ld_options; } else { /* Get pointer to global option structure */ lo = LDAP_INT_GLOBAL_OPT(); if ( lo == NULL ) { return LDAP_NO_MEMORY; } } switch( option ) { case LDAP_OPT_X_TLS: *(int *)arg = lo->ldo_tls_mode; break; case LDAP_OPT_X_TLS_CTX: *(void **)arg = lo->ldo_tls_ctx; if ( lo->ldo_tls_ctx ) { tls_ctx_ref( lo->ldo_tls_ctx ); } break; case LDAP_OPT_X_TLS_CACERTFILE: *(char **)arg = lo->ldo_tls_cacertfile ? LDAP_STRDUP( lo->ldo_tls_cacertfile ) : NULL; break; case LDAP_OPT_X_TLS_CACERTDIR: *(char **)arg = lo->ldo_tls_cacertdir ? LDAP_STRDUP( lo->ldo_tls_cacertdir ) : NULL; break; case LDAP_OPT_X_TLS_CERTFILE: *(char **)arg = lo->ldo_tls_certfile ? LDAP_STRDUP( lo->ldo_tls_certfile ) : NULL; break; case LDAP_OPT_X_TLS_KEYFILE: *(char **)arg = lo->ldo_tls_keyfile ? LDAP_STRDUP( lo->ldo_tls_keyfile ) : NULL; break; case LDAP_OPT_X_TLS_DHFILE: *(char **)arg = lo->ldo_tls_dhfile ? LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL; break; case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ *(char **)arg = lo->ldo_tls_crlfile ? LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL; break; case LDAP_OPT_X_TLS_REQUIRE_CERT: *(int *)arg = lo->ldo_tls_require_cert; break; #ifdef HAVE_OPENSSL_CRL case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ *(int *)arg = lo->ldo_tls_crlcheck; break; #endif case LDAP_OPT_X_TLS_CIPHER_SUITE: *(char **)arg = lo->ldo_tls_ciphersuite ? LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL; break; case LDAP_OPT_X_TLS_PROTOCOL_MIN: *(int *)arg = lo->ldo_tls_protocol_min; break; case LDAP_OPT_X_TLS_RANDOM_FILE: *(char **)arg = lo->ldo_tls_randfile ? LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL; break; case LDAP_OPT_X_TLS_SSL_CTX: { void *retval = 0; if ( ld != NULL ) { LDAPConn *conn = ld->ld_defconn; if ( conn != NULL ) { Sockbuf *sb = conn->lconn_sb; retval = ldap_pvt_tls_sb_ctx( sb ); } } *(void **)arg = retval; break; } case LDAP_OPT_X_TLS_CONNECT_CB: *(LDAP_TLS_CONNECT_CB **)arg = lo->ldo_tls_connect_cb; break; case LDAP_OPT_X_TLS_CONNECT_ARG: *(void **)arg = lo->ldo_tls_connect_arg; break; default: return -1; } return 0; }
static int ldap_int_tls_connect( LDAP *ld, LDAPConn *conn ) { Sockbuf *sb = conn->lconn_sb; int err; tls_session *ssl = NULL; if ( HAS_TLS( sb )) { ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); } else { struct ldapoptions *lo; tls_ctx *ctx; ctx = ld->ld_options.ldo_tls_ctx; ssl = alloc_handle( ctx, 0 ); if ( ssl == NULL ) return -1; #ifdef LDAP_DEBUG ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); #endif ber_sockbuf_add_io( sb, tls_imp->ti_sbio, LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); lo = LDAP_INT_GLOBAL_OPT(); if( ctx == NULL ) { ctx = lo->ldo_tls_ctx; ld->ld_options.ldo_tls_ctx = ctx; tls_ctx_ref( ctx ); } if ( ld->ld_options.ldo_tls_connect_cb ) ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx, ld->ld_options.ldo_tls_connect_arg ); if ( lo && lo->ldo_tls_connect_cb && lo->ldo_tls_connect_cb != ld->ld_options.ldo_tls_connect_cb ) lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg ); } err = tls_imp->ti_session_connect( ld, ssl ); #ifdef HAVE_WINSOCK errno = WSAGetLastError(); #endif if ( err < 0 ) { char buf[256], *msg; if ( update_flags( sb, ssl, err )) { return 1; } msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); if ( msg ) { if ( ld->ld_error ) { LDAP_FREE( ld->ld_error ); } ld->ld_error = LDAP_STRDUP( msg ); #ifdef HAVE_EBCDIC if ( ld->ld_error ) __etoa(ld->ld_error); #endif } Debug( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n", ld->ld_error ? ld->ld_error : "" ,0,0); ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, LBER_SBIOD_LEVEL_TRANSPORT ); #ifdef LDAP_DEBUG ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, LBER_SBIOD_LEVEL_TRANSPORT ); #endif return -1; } return 0; }
int ldap_create( LDAP **ldp ) { LDAP *ld; struct ldapoptions *gopts; #if defined(__APPLE__) && defined(LDAP_R_COMPILE) /* Init the global options in a nice thread-safe manner. */ dispatch_once_f(&ldap_global_opts_initialized, NULL, ldap_int_init_global_opts); #endif *ldp = NULL; /* Get pointer to global option structure */ if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) { return LDAP_NO_MEMORY; } #if defined(__APPLE__) && defined(LDAP_R_COMPILE) /* Global options should have been initialized by pthread_once() */ if( gopts->ldo_valid != LDAP_INITIALIZED ) { return LDAP_LOCAL_ERROR; } #else /* Initialize the global options, if not already done. */ if( gopts->ldo_valid != LDAP_INITIALIZED ) { ldap_int_initialize(gopts, NULL); if ( gopts->ldo_valid != LDAP_INITIALIZED ) return LDAP_LOCAL_ERROR; } #endif Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 ); if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) { return( LDAP_NO_MEMORY ); } if ( (ld->ldc = (struct ldap_common *) LDAP_CALLOC( 1, sizeof(struct ldap_common) )) == NULL ) { LDAP_FREE( (char *)ld ); return( LDAP_NO_MEMORY ); } /* copy the global options */ LDAP_MUTEX_LOCK( &gopts->ldo_mutex ); AC_MEMCPY(&ld->ld_options, gopts, sizeof(ld->ld_options)); #ifdef LDAP_R_COMPILE /* Properly initialize the structs mutex */ ldap_pvt_thread_mutex_init( &(ld->ld_ldopts_mutex) ); #endif LDAP_MUTEX_UNLOCK( &gopts->ldo_mutex ); ld->ld_valid = LDAP_VALID_SESSION; /* but not pointers to malloc'ed items */ ld->ld_options.ldo_sctrls = NULL; ld->ld_options.ldo_cctrls = NULL; ld->ld_options.ldo_defludp = NULL; ld->ld_options.ldo_conn_cbs = NULL; ld->ld_options.ldo_noaddr_option = 0; ld->ld_options.ldo_sasl_fqdn = NULL; #ifdef HAVE_CYRUS_SASL ld->ld_options.ldo_def_sasl_mech = gopts->ldo_def_sasl_mech ? LDAP_STRDUP( gopts->ldo_def_sasl_mech ) : NULL; ld->ld_options.ldo_def_sasl_realm = gopts->ldo_def_sasl_realm ? LDAP_STRDUP( gopts->ldo_def_sasl_realm ) : NULL; ld->ld_options.ldo_def_sasl_authcid = gopts->ldo_def_sasl_authcid ? LDAP_STRDUP( gopts->ldo_def_sasl_authcid ) : NULL; ld->ld_options.ldo_def_sasl_authzid = gopts->ldo_def_sasl_authzid ? LDAP_STRDUP( gopts->ldo_def_sasl_authzid ) : NULL; #endif #ifdef HAVE_TLS /* We explicitly inherit the SSL_CTX, don't need the names/paths. Leave * them empty to allow new SSL_CTX's to be created from scratch. */ memset( &ld->ld_options.ldo_tls_info, 0, sizeof( ld->ld_options.ldo_tls_info )); ld->ld_options.ldo_tls_ctx = NULL; #endif if ( gopts->ldo_defludp ) { ld->ld_options.ldo_defludp = ldap_url_duplist(gopts->ldo_defludp); if ( ld->ld_options.ldo_defludp == NULL ) goto nomem; } if (( ld->ld_selectinfo = ldap_new_select_info()) == NULL ) goto nomem; ld->ld_lberoptions = LBER_USE_DER; ld->ld_sb = ber_sockbuf_alloc( ); if ( ld->ld_sb == NULL ) goto nomem; #ifdef LDAP_RESPONSE_RB_TREE ldap_resp_rbt_create( ld ); if ( ld->ld_rbt_responses == NULL ) { goto nomem; } #endif #ifdef LDAP_R_COMPILE ldap_pvt_thread_mutex_init( &ld->ld_msgid_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_conn_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_req_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_res_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_abandon_mutex ); ldap_pvt_thread_mutex_init( &ld->ld_ldcmutex ); #endif ld->ld_ldcrefcnt = 1; *ldp = ld; return LDAP_SUCCESS; nomem: ldap_free_select_info( ld->ld_selectinfo ); ldap_free_urllist( ld->ld_options.ldo_defludp ); #ifdef HAVE_CYRUS_SASL LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); #endif LDAP_FREE( (char *)ld ); return LDAP_NO_MEMORY; }
static void tls_get_cert_from_keychain( char *host ) { /* Cert info is kept in the global options. */ struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); if ( !lo ) return; /* If the server identity option is set, don't need to do anything * as the certificate will get set in the SSL context during context * initialization. */ if (lo->ldo_tls_server_ident_ref_name) { return; } /* If the cert is set in the options, don't override it. */ if ( lo->ldo_tls_cacertfile || lo->ldo_tls_certfile ) { Debug( LDAP_DEBUG_ANY, "TLS: not reading certificate from keychain, option %s is set\n", lo->ldo_tls_cacertfile ? "cacertfile" : "certfile", 0, 0 ); return; } SecKeychainRef keychainRef = NULL; OSStatus status = SecKeychainOpen( SYSTEM_KEYCHAIN_PATH, &keychainRef ); if ( status != errSecSuccess ) { Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainOpen failed for keychain %s: %d", SYSTEM_KEYCHAIN_PATH, (int)status, 0 ); syslog( LOG_ERR, "TLS: SecKeychainOpen failed for keychain %s: %d", SYSTEM_KEYCHAIN_PATH, (int)status, 0 ); cssmPerror( "SecKeychainOpen", status ); return; } SecKeychainSearchRef searchRef = NULL; status = SecKeychainSearchCreateFromAttributes( keychainRef, kSecCertificateItemClass, NULL, &searchRef ); if ( status != errSecSuccess ) { Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainSearchCreateFromAttributes failed: %d", (int)status, 0, 0 ); syslog( LOG_ERR, "TLS: SecKeychainSearchCreateFromAttributes failed: %d", (int)status ); cssmPerror( "SecKeychainSearchCreateFromAttributes", status ); } while ( status == errSecSuccess ) { SecCertificateRef certificateRef = NULL; status = SecKeychainSearchCopyNext( searchRef, (SecKeychainItemRef*)&certificateRef ); /* Bail on any error. */ if ( status != errSecSuccess ) { /* Only complain if the error is something other than * the normal search end. */ if ( status != errSecItemNotFound ) { Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainSearchCopyNext failed: %d", (int)status, 0, 0 ); syslog( LOG_ERR, "SecKeychainSearchCopyNext failed: %d", (int)status ); cssmPerror( "SecKeychainSearchCopyNext", status ); } break; } /* Extract the name from the certificate. Will check against the host * name passed in. */ CFStringRef commonName = NULL; status = SecCertificateCopyCommonName( certificateRef, &commonName ); if ( status != errSecSuccess || !commonName ) { Debug( LDAP_DEBUG_ANY, "TLS: SecCertificateCopyCommonName failed: %d", (int)status, 0, 0 ); cssmPerror( "SecCertificateCopyCommonName", status ); /* Reset 'status' to allow the loop to continue. No need to * stop just because we can't get the name from one of the * certs. */ status = errSecSuccess; } else { /* If the common name in the certificate matches the host name, save * the certificate reference in the options data for later use. */ char commonNameCStr[PATH_MAX]; if ( !CFStringGetCString( commonName, commonNameCStr, sizeof(commonNameCStr), kCFStringEncodingUTF8 ) ) { Debug( LDAP_DEBUG_ANY, "TLS: Unable to convert certificate common name CFString into C String", 0, 0, 0); } CFRelease( commonName ); if ( commonNameCStr && strcmp( commonNameCStr, host ) == 0 ) { if ( lo->ldo_tls_cert_ref ) { CFRelease( lo->ldo_tls_cert_ref ); } lo->ldo_tls_cert_ref = certificateRef; status = !errSecSuccess; /* cert found - terminate the loop */ } } /* Only release the ref if we don't care about it. Refs we care * about get released later (when the connection is closed). */ if ( lo->ldo_tls_cert_ref != certificateRef ) { CFRelease( certificateRef ); } } if ( searchRef ) { CFRelease( searchRef ); } CFRelease( keychainRef ); Debug( LDAP_DEBUG_ANY, "TLS: %s certificate in keychain for host \"%s\"\n", lo->ldo_tls_cert_ref ? "found" : "did not find", host, 0 ); }