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