1 /* $OpenLDAP: pkg/ldap/libraries/libldap/unbind.c,v 1.56.2.4 2008/02/11 23:26:41 kurt Exp $ */ 2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2008 The OpenLDAP Foundation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted only as authorized by the OpenLDAP 9 * Public License. 10 * 11 * A copy of this license is available in the file LICENSE in the 12 * top-level directory of the distribution or, alternatively, at 13 * <http://www.OpenLDAP.org/license.html>. 14 */ 15 /* Portions Copyright (c) 1990 Regents of the University of Michigan. 16 * All rights reserved. 17 */ 18 19 #include "portable.h" 20 21 #include <stdio.h> 22 #include <ac/stdlib.h> 23 24 #include <ac/socket.h> 25 #include <ac/string.h> 26 #include <ac/time.h> 27 28 #include "ldap-int.h" 29 30 /* An Unbind Request looks like this: 31 * 32 * UnbindRequest ::= [APPLICATION 2] NULL 33 * 34 * and has no response. (Source: RFC 4511) 35 */ 36 37 int 38 ldap_unbind_ext( 39 LDAP *ld, 40 LDAPControl **sctrls, 41 LDAPControl **cctrls ) 42 { 43 int rc; 44 45 assert( ld != NULL ); 46 assert( LDAP_VALID( ld ) ); 47 48 /* check client controls */ 49 rc = ldap_int_client_controls( ld, cctrls ); 50 if( rc != LDAP_SUCCESS ) return rc; 51 52 return ldap_ld_free( ld, 1, sctrls, cctrls ); 53 } 54 55 int 56 ldap_unbind_ext_s( 57 LDAP *ld, 58 LDAPControl **sctrls, 59 LDAPControl **cctrls ) 60 { 61 return ldap_unbind_ext( ld, sctrls, cctrls ); 62 } 63 64 int 65 ldap_unbind( LDAP *ld ) 66 { 67 Debug( LDAP_DEBUG_TRACE, "ldap_unbind\n", 0, 0, 0 ); 68 69 return( ldap_unbind_ext( ld, NULL, NULL ) ); 70 } 71 72 73 int 74 ldap_ld_free( 75 LDAP *ld, 76 int close, 77 LDAPControl **sctrls, 78 LDAPControl **cctrls ) 79 { 80 LDAPMessage *lm, *next; 81 int err = LDAP_SUCCESS; 82 83 /* free LDAP structure and outstanding requests/responses */ 84 #ifdef LDAP_R_COMPILE 85 ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); 86 #endif 87 while ( ld->ld_requests != NULL ) { 88 ldap_free_request( ld, ld->ld_requests ); 89 } 90 91 /* free and unbind from all open connections */ 92 while ( ld->ld_conns != NULL ) { 93 ldap_free_connection( ld, ld->ld_conns, 1, close ); 94 } 95 #ifdef LDAP_R_COMPILE 96 ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); 97 #endif 98 99 #ifdef LDAP_R_COMPILE 100 ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); 101 #endif 102 for ( lm = ld->ld_responses; lm != NULL; lm = next ) { 103 next = lm->lm_next; 104 ldap_msgfree( lm ); 105 } 106 107 if ( ld->ld_abandoned != NULL ) { 108 LDAP_FREE( ld->ld_abandoned ); 109 ld->ld_abandoned = NULL; 110 } 111 #ifdef LDAP_R_COMPILE 112 ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); 113 #endif 114 115 if ( ld->ld_error != NULL ) { 116 LDAP_FREE( ld->ld_error ); 117 ld->ld_error = NULL; 118 } 119 120 if ( ld->ld_matched != NULL ) { 121 LDAP_FREE( ld->ld_matched ); 122 ld->ld_matched = NULL; 123 } 124 125 if( ld->ld_referrals != NULL) { 126 LDAP_VFREE(ld->ld_referrals); 127 ld->ld_referrals = NULL; 128 } 129 130 if ( ld->ld_selectinfo != NULL ) { 131 ldap_free_select_info( ld->ld_selectinfo ); 132 ld->ld_selectinfo = NULL; 133 } 134 135 if ( ld->ld_options.ldo_defludp != NULL ) { 136 ldap_free_urllist( ld->ld_options.ldo_defludp ); 137 ld->ld_options.ldo_defludp = NULL; 138 } 139 140 #ifdef LDAP_CONNECTIONLESS 141 if ( ld->ld_options.ldo_peer != NULL ) { 142 LDAP_FREE( ld->ld_options.ldo_peer ); 143 ld->ld_options.ldo_peer = NULL; 144 } 145 #endif 146 147 #ifdef HAVE_CYRUS_SASL 148 if ( ld->ld_options.ldo_def_sasl_mech != NULL ) { 149 LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); 150 ld->ld_options.ldo_def_sasl_mech = NULL; 151 } 152 153 if ( ld->ld_options.ldo_def_sasl_realm != NULL ) { 154 LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); 155 ld->ld_options.ldo_def_sasl_realm = NULL; 156 } 157 158 if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) { 159 LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); 160 ld->ld_options.ldo_def_sasl_authcid = NULL; 161 } 162 163 if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) { 164 LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); 165 ld->ld_options.ldo_def_sasl_authzid = NULL; 166 } 167 #endif 168 169 #ifdef HAVE_TLS 170 ldap_int_tls_destroy( &ld->ld_options ); 171 #endif 172 173 if ( ld->ld_options.ldo_sctrls != NULL ) { 174 ldap_controls_free( ld->ld_options.ldo_sctrls ); 175 ld->ld_options.ldo_sctrls = NULL; 176 } 177 178 if ( ld->ld_options.ldo_cctrls != NULL ) { 179 ldap_controls_free( ld->ld_options.ldo_cctrls ); 180 ld->ld_options.ldo_cctrls = NULL; 181 } 182 183 ber_sockbuf_free( ld->ld_sb ); 184 185 #ifdef LDAP_R_COMPILE 186 ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex ); 187 ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex ); 188 ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex ); 189 #endif 190 #ifndef NDEBUG 191 LDAP_TRASH(ld); 192 #endif 193 LDAP_FREE( (char *) ld ); 194 195 return( err ); 196 } 197 198 int 199 ldap_unbind_s( LDAP *ld ) 200 { 201 return( ldap_unbind_ext( ld, NULL, NULL ) ); 202 } 203 204 /* FIXME: this function is called only by ldap_free_connection(), 205 * which, most of the times, is called with ld_req_mutex locked */ 206 int 207 ldap_send_unbind( 208 LDAP *ld, 209 Sockbuf *sb, 210 LDAPControl **sctrls, 211 LDAPControl **cctrls ) 212 { 213 BerElement *ber; 214 ber_int_t id; 215 216 Debug( LDAP_DEBUG_TRACE, "ldap_send_unbind\n", 0, 0, 0 ); 217 218 #ifdef LDAP_CONNECTIONLESS 219 if (LDAP_IS_UDP(ld)) 220 return LDAP_SUCCESS; 221 #endif 222 /* create a message to send */ 223 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { 224 return( ld->ld_errno ); 225 } 226 227 id = ++(ld)->ld_msgid; 228 229 /* fill it in */ 230 if ( ber_printf( ber, "{itn" /*}*/, id, 231 LDAP_REQ_UNBIND ) == -1 ) { 232 ld->ld_errno = LDAP_ENCODING_ERROR; 233 ber_free( ber, 1 ); 234 return( ld->ld_errno ); 235 } 236 237 /* Put Server Controls */ 238 if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { 239 ber_free( ber, 1 ); 240 return ld->ld_errno; 241 } 242 243 if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) { 244 ld->ld_errno = LDAP_ENCODING_ERROR; 245 ber_free( ber, 1 ); 246 return( ld->ld_errno ); 247 } 248 249 ld->ld_errno = LDAP_SUCCESS; 250 /* send the message */ 251 if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) { 252 ld->ld_errno = LDAP_SERVER_DOWN; 253 } 254 255 return( ld->ld_errno ); 256 } 257