Back to index

openldap  2.4.31
unbind.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* Portions Copyright (c) 1990 Regents of the University of Michigan.
00016  * All rights reserved.
00017  */
00018 
00019 #include "portable.h"
00020 
00021 #include <stdio.h>
00022 #include <ac/stdlib.h>
00023 
00024 #include <ac/socket.h>
00025 #include <ac/string.h>
00026 #include <ac/time.h>
00027 
00028 #include "ldap-int.h"
00029 
00030 /* An Unbind Request looks like this:
00031  *
00032  *     UnbindRequest ::= [APPLICATION 2] NULL
00033  *
00034  * and has no response.  (Source: RFC 4511)
00035  */
00036 
00037 int
00038 ldap_unbind_ext(
00039        LDAP *ld,
00040        LDAPControl **sctrls,
00041        LDAPControl **cctrls )
00042 {
00043        int rc;
00044 
00045        assert( ld != NULL );
00046        assert( LDAP_VALID( ld ) );
00047 
00048        /* check client controls */
00049        rc = ldap_int_client_controls( ld, cctrls );
00050        if( rc != LDAP_SUCCESS ) return rc;
00051 
00052        return ldap_ld_free( ld, 1, sctrls, cctrls );
00053 }
00054 
00055 int
00056 ldap_unbind_ext_s(
00057        LDAP *ld,
00058        LDAPControl **sctrls,
00059        LDAPControl **cctrls )
00060 {
00061        return ldap_unbind_ext( ld, sctrls, cctrls );
00062 }
00063 
00064 int
00065 ldap_unbind( LDAP *ld )
00066 {
00067        Debug( LDAP_DEBUG_TRACE, "ldap_unbind\n", 0, 0, 0 );
00068 
00069        return( ldap_unbind_ext( ld, NULL, NULL ) );
00070 }
00071 
00072 
00073 int
00074 ldap_ld_free(
00075        LDAP *ld,
00076        int close,
00077        LDAPControl **sctrls,
00078        LDAPControl **cctrls )
00079 {
00080        LDAPMessage   *lm, *next;
00081        int           err = LDAP_SUCCESS;
00082 
00083        LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
00084        /* Someone else is still using this ld. */
00085        if (ld->ld_ldcrefcnt > 1) { /* but not last thread */
00086               /* clean up self only */
00087               ld->ld_ldcrefcnt--;
00088               if ( ld->ld_error != NULL ) {
00089                      LDAP_FREE( ld->ld_error );
00090                      ld->ld_error = NULL;
00091               }
00092 
00093               if ( ld->ld_matched != NULL ) {
00094                      LDAP_FREE( ld->ld_matched );
00095                      ld->ld_matched = NULL;
00096               }
00097               if ( ld->ld_referrals != NULL) {
00098                      LDAP_VFREE(ld->ld_referrals);
00099                      ld->ld_referrals = NULL;
00100               }  
00101               LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
00102               LDAP_FREE( (char *) ld );
00103               return( err );
00104        }
00105 
00106        /* This ld is the last thread. */
00107 
00108        /* free LDAP structure and outstanding requests/responses */
00109        LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
00110        while ( ld->ld_requests != NULL ) {
00111               ldap_free_request( ld, ld->ld_requests );
00112        }
00113        LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
00114        LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
00115 
00116        /* free and unbind from all open connections */
00117        while ( ld->ld_conns != NULL ) {
00118               ldap_free_connection( ld, ld->ld_conns, 1, close );
00119        }
00120        LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
00121        LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
00122        for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
00123               next = lm->lm_next;
00124               ldap_msgfree( lm );
00125        }
00126     
00127        if ( ld->ld_abandoned != NULL ) {
00128               LDAP_FREE( ld->ld_abandoned );
00129               ld->ld_abandoned = NULL;
00130        }
00131        LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
00132        LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex );
00133 
00134        /* final close callbacks */
00135        {
00136               ldaplist *ll, *next;
00137 
00138               for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) {
00139                      ldap_conncb *cb = ll->ll_data;
00140                      next = ll->ll_next;
00141                      cb->lc_del( ld, NULL, cb );
00142                      LDAP_FREE( ll );
00143               }
00144        }
00145 
00146        if ( ld->ld_error != NULL ) {
00147               LDAP_FREE( ld->ld_error );
00148               ld->ld_error = NULL;
00149        }
00150 
00151        if ( ld->ld_matched != NULL ) {
00152               LDAP_FREE( ld->ld_matched );
00153               ld->ld_matched = NULL;
00154        }
00155 
00156        if ( ld->ld_referrals != NULL) {
00157               LDAP_VFREE(ld->ld_referrals);
00158               ld->ld_referrals = NULL;
00159        }  
00160     
00161        if ( ld->ld_selectinfo != NULL ) {
00162               ldap_free_select_info( ld->ld_selectinfo );
00163               ld->ld_selectinfo = NULL;
00164        }
00165 
00166        if ( ld->ld_options.ldo_defludp != NULL ) {
00167               ldap_free_urllist( ld->ld_options.ldo_defludp );
00168               ld->ld_options.ldo_defludp = NULL;
00169        }
00170 
00171 #ifdef LDAP_CONNECTIONLESS
00172        if ( ld->ld_options.ldo_peer != NULL ) {
00173               LDAP_FREE( ld->ld_options.ldo_peer );
00174               ld->ld_options.ldo_peer = NULL;
00175        }
00176 
00177        if ( ld->ld_options.ldo_cldapdn != NULL ) {
00178               LDAP_FREE( ld->ld_options.ldo_cldapdn );
00179               ld->ld_options.ldo_cldapdn = NULL;
00180        }
00181 #endif
00182 
00183 #ifdef HAVE_CYRUS_SASL
00184        if ( ld->ld_options.ldo_def_sasl_mech != NULL ) {
00185               LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
00186               ld->ld_options.ldo_def_sasl_mech = NULL;
00187        }
00188 
00189        if ( ld->ld_options.ldo_def_sasl_realm != NULL ) {
00190               LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
00191               ld->ld_options.ldo_def_sasl_realm = NULL;
00192        }
00193 
00194        if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) {
00195               LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
00196               ld->ld_options.ldo_def_sasl_authcid = NULL;
00197        }
00198 
00199        if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) {
00200               LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
00201               ld->ld_options.ldo_def_sasl_authzid = NULL;
00202        }
00203 #endif
00204 
00205 #ifdef HAVE_TLS
00206        ldap_int_tls_destroy( &ld->ld_options );
00207 #endif
00208 
00209        if ( ld->ld_options.ldo_sctrls != NULL ) {
00210               ldap_controls_free( ld->ld_options.ldo_sctrls );
00211               ld->ld_options.ldo_sctrls = NULL;
00212        }
00213 
00214        if ( ld->ld_options.ldo_cctrls != NULL ) {
00215               ldap_controls_free( ld->ld_options.ldo_cctrls );
00216               ld->ld_options.ldo_cctrls = NULL;
00217        }
00218        LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex );
00219 
00220        ber_sockbuf_free( ld->ld_sb );   
00221    
00222 #ifdef LDAP_R_COMPILE
00223        ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex );
00224        ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
00225        ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
00226        ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
00227        ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex );
00228        ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex );
00229        ldap_pvt_thread_mutex_unlock( &ld->ld_ldcmutex );
00230        ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex );
00231 #endif
00232 #ifndef NDEBUG
00233        LDAP_TRASH(ld);
00234 #endif
00235        LDAP_FREE( (char *) ld->ldc );
00236        LDAP_FREE( (char *) ld );
00237    
00238        return( err );
00239 }
00240 
00241 int
00242 ldap_destroy( LDAP *ld )
00243 {
00244        return ( ldap_ld_free( ld, 1, NULL, NULL ) );
00245 }
00246 
00247 int
00248 ldap_unbind_s( LDAP *ld )
00249 {
00250        return( ldap_unbind_ext( ld, NULL, NULL ) );
00251 }
00252 
00253 /* FIXME: this function is called only by ldap_free_connection(),
00254  * which, most of the times, is called with ld_req_mutex locked */
00255 int
00256 ldap_send_unbind(
00257        LDAP *ld,
00258        Sockbuf *sb,
00259        LDAPControl **sctrls,
00260        LDAPControl **cctrls )
00261 {
00262        BerElement    *ber;
00263        ber_int_t     id;
00264 
00265        Debug( LDAP_DEBUG_TRACE, "ldap_send_unbind\n", 0, 0, 0 );
00266 
00267 #ifdef LDAP_CONNECTIONLESS
00268        if (LDAP_IS_UDP(ld))
00269               return LDAP_SUCCESS;
00270 #endif
00271        /* create a message to send */
00272        if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
00273               return( ld->ld_errno );
00274        }
00275 
00276        LDAP_NEXT_MSGID(ld, id);
00277 
00278        /* fill it in */
00279        if ( ber_printf( ber, "{itn" /*}*/, id,
00280            LDAP_REQ_UNBIND ) == -1 ) {
00281               ld->ld_errno = LDAP_ENCODING_ERROR;
00282               ber_free( ber, 1 );
00283               return( ld->ld_errno );
00284        }
00285 
00286        /* Put Server Controls */
00287        if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
00288               ber_free( ber, 1 );
00289               return ld->ld_errno;
00290        }
00291 
00292        if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) {
00293               ld->ld_errno = LDAP_ENCODING_ERROR;
00294               ber_free( ber, 1 );
00295               return( ld->ld_errno );
00296        }
00297 
00298        ld->ld_errno = LDAP_SUCCESS;
00299        /* send the message */
00300        if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) {
00301               ld->ld_errno = LDAP_SERVER_DOWN;
00302        }
00303 
00304        return( ld->ld_errno );
00305 }