1 /* $NetBSD: unbind.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* OpenLDAP: pkg/ldap/libraries/libldap/unbind.c,v 1.56.2.6 2009/01/22 00:00:56 kurt Exp */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2009 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 /* free LDAP structure and outstanding requests/responses */ 86 #ifdef LDAP_R_COMPILE 87 ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); 88 #endif 89 while ( ld->ld_requests != NULL ) { 90 ldap_free_request( ld, ld->ld_requests ); 91 } 92 93 /* free and unbind from all open connections */ 94 while ( ld->ld_conns != NULL ) { 95 ldap_free_connection( ld, ld->ld_conns, 1, close ); 96 } 97 #ifdef LDAP_R_COMPILE 98 ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex ); 99 #endif 100 101 #ifdef LDAP_R_COMPILE 102 ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex ); 103 #endif 104 for ( lm = ld->ld_responses; lm != NULL; lm = next ) { 105 next = lm->lm_next; 106 ldap_msgfree( lm ); 107 } 108 109 if ( ld->ld_abandoned != NULL ) { 110 LDAP_FREE( ld->ld_abandoned ); 111 ld->ld_abandoned = NULL; 112 } 113 #ifdef LDAP_R_COMPILE 114 ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); 115 #endif 116 117 /* final close callbacks */ 118 { 119 ldaplist *ll, *next; 120 121 for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) { 122 ldap_conncb *cb = ll->ll_data; 123 next = ll->ll_next; 124 cb->lc_del( ld, NULL, cb ); 125 LDAP_FREE( ll ); 126 } 127 } 128 129 if ( ld->ld_error != NULL ) { 130 LDAP_FREE( ld->ld_error ); 131 ld->ld_error = NULL; 132 } 133 134 if ( ld->ld_matched != NULL ) { 135 LDAP_FREE( ld->ld_matched ); 136 ld->ld_matched = NULL; 137 } 138 139 if( ld->ld_referrals != NULL) { 140 LDAP_VFREE(ld->ld_referrals); 141 ld->ld_referrals = NULL; 142 } 143 144 if ( ld->ld_selectinfo != NULL ) { 145 ldap_free_select_info( ld->ld_selectinfo ); 146 ld->ld_selectinfo = NULL; 147 } 148 149 if ( ld->ld_options.ldo_defludp != NULL ) { 150 ldap_free_urllist( ld->ld_options.ldo_defludp ); 151 ld->ld_options.ldo_defludp = NULL; 152 } 153 154 #ifdef LDAP_CONNECTIONLESS 155 if ( ld->ld_options.ldo_peer != NULL ) { 156 LDAP_FREE( ld->ld_options.ldo_peer ); 157 ld->ld_options.ldo_peer = NULL; 158 } 159 #endif 160 161 #ifdef HAVE_CYRUS_SASL 162 if ( ld->ld_options.ldo_def_sasl_mech != NULL ) { 163 LDAP_FREE( ld->ld_options.ldo_def_sasl_mech ); 164 ld->ld_options.ldo_def_sasl_mech = NULL; 165 } 166 167 if ( ld->ld_options.ldo_def_sasl_realm != NULL ) { 168 LDAP_FREE( ld->ld_options.ldo_def_sasl_realm ); 169 ld->ld_options.ldo_def_sasl_realm = NULL; 170 } 171 172 if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) { 173 LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid ); 174 ld->ld_options.ldo_def_sasl_authcid = NULL; 175 } 176 177 if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) { 178 LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid ); 179 ld->ld_options.ldo_def_sasl_authzid = NULL; 180 } 181 #endif 182 183 #ifdef HAVE_TLS 184 ldap_int_tls_destroy( &ld->ld_options ); 185 #endif 186 187 if ( ld->ld_options.ldo_sctrls != NULL ) { 188 ldap_controls_free( ld->ld_options.ldo_sctrls ); 189 ld->ld_options.ldo_sctrls = NULL; 190 } 191 192 if ( ld->ld_options.ldo_cctrls != NULL ) { 193 ldap_controls_free( ld->ld_options.ldo_cctrls ); 194 ld->ld_options.ldo_cctrls = NULL; 195 } 196 197 ber_sockbuf_free( ld->ld_sb ); 198 199 #ifdef LDAP_R_COMPILE 200 ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex ); 201 ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex ); 202 ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex ); 203 #endif 204 #ifndef NDEBUG 205 LDAP_TRASH(ld); 206 #endif 207 LDAP_FREE( (char *) ld ); 208 209 return( err ); 210 } 211 212 int 213 ldap_unbind_s( LDAP *ld ) 214 { 215 return( ldap_unbind_ext( ld, NULL, NULL ) ); 216 } 217 218 /* FIXME: this function is called only by ldap_free_connection(), 219 * which, most of the times, is called with ld_req_mutex locked */ 220 int 221 ldap_send_unbind( 222 LDAP *ld, 223 Sockbuf *sb, 224 LDAPControl **sctrls, 225 LDAPControl **cctrls ) 226 { 227 BerElement *ber; 228 ber_int_t id; 229 230 Debug( LDAP_DEBUG_TRACE, "ldap_send_unbind\n", 0, 0, 0 ); 231 232 #ifdef LDAP_CONNECTIONLESS 233 if (LDAP_IS_UDP(ld)) 234 return LDAP_SUCCESS; 235 #endif 236 /* create a message to send */ 237 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { 238 return( ld->ld_errno ); 239 } 240 241 id = ++(ld)->ld_msgid; 242 243 /* fill it in */ 244 if ( ber_printf( ber, "{itn" /*}*/, id, 245 LDAP_REQ_UNBIND ) == -1 ) { 246 ld->ld_errno = LDAP_ENCODING_ERROR; 247 ber_free( ber, 1 ); 248 return( ld->ld_errno ); 249 } 250 251 /* Put Server Controls */ 252 if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { 253 ber_free( ber, 1 ); 254 return ld->ld_errno; 255 } 256 257 if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) { 258 ld->ld_errno = LDAP_ENCODING_ERROR; 259 ber_free( ber, 1 ); 260 return( ld->ld_errno ); 261 } 262 263 ld->ld_errno = LDAP_SUCCESS; 264 /* send the message */ 265 if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) { 266 ld->ld_errno = LDAP_SERVER_DOWN; 267 } 268 269 return( ld->ld_errno ); 270 } 271