Exemple #1
0
int
ldap_ld_free(
	LDAP *ld,
	int close,
	LDAPControl **sctrls,
	LDAPControl **cctrls )
{
	LDAPMessage	*lm, *next;
	int		err = LDAP_SUCCESS;

	LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
	/* Someone else is still using this ld. */
	if (ld->ld_ldcrefcnt > 1) {	/* but not last thread */
		/* clean up self only */
		ld->ld_ldcrefcnt--;
		if ( ld->ld_error != NULL ) {
			LDAP_FREE( ld->ld_error );
			ld->ld_error = NULL;
		}

		if ( ld->ld_matched != NULL ) {
			LDAP_FREE( ld->ld_matched );
			ld->ld_matched = NULL;
		}
		if ( ld->ld_referrals != NULL) {
			LDAP_VFREE(ld->ld_referrals);
			ld->ld_referrals = NULL;
		}  
		LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
		LDAP_FREE( (char *) ld );
		return( err );
	}

	/* This ld is the last thread. */

	/* free LDAP structure and outstanding requests/responses */
	LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
	while ( ld->ld_requests != NULL ) {
		ldap_free_request( ld, ld->ld_requests );
	}
	LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
	LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );

	/* free and unbind from all open connections */
	while ( ld->ld_conns != NULL ) {
		ldap_free_connection( ld, ld->ld_conns, 1, close );
	}
	LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
	LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
	for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
		next = lm->lm_next;
		ldap_msgfree( lm );
	}
    
	if ( ld->ld_abandoned != NULL ) {
		LDAP_FREE( ld->ld_abandoned );
		ld->ld_abandoned = NULL;
	}
	LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
	LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex );

	/* final close callbacks */
	{
		ldaplist *ll, *next;

		for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) {
			ldap_conncb *cb = ll->ll_data;
			next = ll->ll_next;
			cb->lc_del( ld, NULL, cb );
			LDAP_FREE( ll );
		}
	}

	if ( ld->ld_error != NULL ) {
		LDAP_FREE( ld->ld_error );
		ld->ld_error = NULL;
	}

	if ( ld->ld_matched != NULL ) {
		LDAP_FREE( ld->ld_matched );
		ld->ld_matched = NULL;
	}

	if ( ld->ld_referrals != NULL) {
		LDAP_VFREE(ld->ld_referrals);
		ld->ld_referrals = NULL;
	}  
    
	if ( ld->ld_selectinfo != NULL ) {
		ldap_free_select_info( ld->ld_selectinfo );
		ld->ld_selectinfo = NULL;
	}

	if ( ld->ld_options.ldo_defludp != NULL ) {
		ldap_free_urllist( ld->ld_options.ldo_defludp );
		ld->ld_options.ldo_defludp = NULL;
	}

#ifdef LDAP_CONNECTIONLESS
	if ( ld->ld_options.ldo_peer != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_peer );
		ld->ld_options.ldo_peer = NULL;
	}

	if ( ld->ld_options.ldo_cldapdn != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_cldapdn );
		ld->ld_options.ldo_cldapdn = NULL;
	}
#endif

#ifdef HAVE_CYRUS_SASL
	if ( ld->ld_options.ldo_def_sasl_mech != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
		ld->ld_options.ldo_def_sasl_mech = NULL;
	}

	if ( ld->ld_options.ldo_def_sasl_realm != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
		ld->ld_options.ldo_def_sasl_realm = NULL;
	}

	if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
		ld->ld_options.ldo_def_sasl_authcid = NULL;
	}

	if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
		ld->ld_options.ldo_def_sasl_authzid = NULL;
	}
#endif

#ifdef HAVE_TLS
	ldap_int_tls_destroy( &ld->ld_options );
#endif

	if ( ld->ld_options.ldo_sctrls != NULL ) {
		ldap_controls_free( ld->ld_options.ldo_sctrls );
		ld->ld_options.ldo_sctrls = NULL;
	}

	if ( ld->ld_options.ldo_cctrls != NULL ) {
		ldap_controls_free( ld->ld_options.ldo_cctrls );
		ld->ld_options.ldo_cctrls = NULL;
	}
	LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex );

	ber_sockbuf_free( ld->ld_sb );   
   
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex );
	ldap_pvt_thread_mutex_unlock( &ld->ld_ldcmutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex );
#endif
#ifndef NDEBUG
	LDAP_TRASH(ld);
#endif
	LDAP_FREE( (char *) ld->ldc );
	LDAP_FREE( (char *) ld );
   
	return( err );
}
int
ldap_ld_free(
	LDAP *ld,
	int close,
	LDAPControl **sctrls,
	LDAPControl **cctrls )
{
	LDAPMessage	*lm, *next;
	int		err = LDAP_SUCCESS;
    LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
	/* Someone else is still using this ld. */
	if (ld->ld_ldcrefcnt > 1) {	/* but not last thread */
		/* clean up self only */
		ld->ld_ldcrefcnt--;
		if ( ld->ld_error != NULL ) {
			LDAP_FREE( ld->ld_error );
			ld->ld_error = NULL;
		}

		if ( ld->ld_matched != NULL ) {
			LDAP_FREE( ld->ld_matched );
			ld->ld_matched = NULL;
		}
		if ( ld->ld_referrals != NULL) {
			LDAP_VFREE(ld->ld_referrals);
			ld->ld_referrals = NULL;
		}  
		LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
		LDAP_FREE( (char *) ld );
		return( err );
	}

	/* This ld is the last thread. */

	/* free LDAP structure and outstanding requests/responses */
#ifdef LDAP_R_COMPILE
#ifdef __APPLE__
	/* If the ld is in async mode, this will stop the thread that's handling
	 * the results messages.  This *must* be done before anything is torn
	 * down to prevent the thread from using deallocated structs.  This is a
	 * blocking call; it won't exit until the thread exits.	 If not in
	 * async mode, this call does nothing.
	 */
	ldap_pvt_clear_search_results_callback( ld );
#endif
#endif
	LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
	while ( ld->ld_requests != NULL ) {
		ldap_free_request( ld, ld->ld_requests );
	}
	LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
	LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );

	/* free and unbind from all open connections */
	while ( ld->ld_conns != NULL ) {
		ldap_free_connection( ld, ld->ld_conns, 1, close );
	}
	LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
	LDAP_MUTEX_LOCK( &ld->ld_res_mutex );

#ifdef LDAP_RESPONSE_RB_TREE
    ldap_resp_rbt_free( ld );
#else
	for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
		next = lm->lm_next;
		ldap_msgfree( lm );
	}
#endif

	if ( ld->ld_abandoned != NULL ) {
		LDAP_FREE( ld->ld_abandoned );
		ld->ld_abandoned = NULL;
	}
	LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
	LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex );

	/* final close callbacks */
	{
		ldaplist *ll, *next;

		for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) {
			ldap_conncb *cb = ll->ll_data;
			next = ll->ll_next;
			cb->lc_del( ld, NULL, cb );
			LDAP_FREE( ll );
		}
	}

	if ( ld->ld_error != NULL ) {
		LDAP_FREE( ld->ld_error );
		ld->ld_error = NULL;
	}

	if ( ld->ld_matched != NULL ) {
		LDAP_FREE( ld->ld_matched );
		ld->ld_matched = NULL;
	}

	if ( ld->ld_referrals != NULL) {
		LDAP_VFREE(ld->ld_referrals);
		ld->ld_referrals = NULL;
	}  
    
	if ( ld->ld_selectinfo != NULL ) {
		ldap_free_select_info( ld->ld_selectinfo );
		ld->ld_selectinfo = NULL;
	}

	if ( ld->ld_options.ldo_defludp != NULL ) {
		ldap_free_urllist( ld->ld_options.ldo_defludp );
		ld->ld_options.ldo_defludp = NULL;
	}

#ifdef LDAP_CONNECTIONLESS
	if ( ld->ld_options.ldo_peer != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_peer );
		ld->ld_options.ldo_peer = NULL;
	}

	if ( ld->ld_options.ldo_cldapdn != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_cldapdn );
		ld->ld_options.ldo_cldapdn = NULL;
	}
#endif

#ifdef HAVE_CYRUS_SASL
	if ( ld->ld_options.ldo_def_sasl_mech != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
		ld->ld_options.ldo_def_sasl_mech = NULL;
	}

	if ( ld->ld_options.ldo_def_sasl_realm != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
		ld->ld_options.ldo_def_sasl_realm = NULL;
	}

	if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
		ld->ld_options.ldo_def_sasl_authcid = NULL;
	}

	if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
		ld->ld_options.ldo_def_sasl_authzid = NULL;
	}
#endif

#ifdef HAVE_TLS
	ldap_int_tls_destroy( &ld->ld_options );
#endif

	if ( ld->ld_options.ldo_sctrls != NULL ) {
		ldap_controls_free( ld->ld_options.ldo_sctrls );
		ld->ld_options.ldo_sctrls = NULL;
	}

	if ( ld->ld_options.ldo_cctrls != NULL ) {
		ldap_controls_free( ld->ld_options.ldo_cctrls );
		ld->ld_options.ldo_cctrls = NULL;
	}
	
	if ( ld->ld_options.ldo_sasl_secprops.property_names != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_sasl_secprops.property_names );
		ld->ld_options.ldo_sasl_secprops.property_names = NULL;
	}

	if ( ld->ld_options.ldo_sasl_secprops.property_values != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_sasl_secprops.property_values );
		ld->ld_options.ldo_sasl_secprops.property_values = NULL;
	}

	if ( ld->ld_options.ldo_sasl_fqdn != NULL ) {
		LDAP_FREE( ld->ld_options.ldo_sasl_fqdn );
		ld->ld_options.ldo_sasl_fqdn = NULL;
	}
    LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex );	
	ber_sockbuf_free( ld->ld_sb );   
   
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex );
	ldap_pvt_thread_mutex_unlock( &ld->ld_ldcmutex );
	ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex );
#endif
#ifndef NDEBUG
	LDAP_TRASH(ld);
#endif
	LDAP_FREE( (char *) ld->ldc );
	LDAP_FREE( (char *) ld );
   
	return( err );
}
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_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;
}