unbind.c revision 1.1.1.1
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
37int
38ldap_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
55int
56ldap_unbind_ext_s(
57	LDAP *ld,
58	LDAPControl **sctrls,
59	LDAPControl **cctrls )
60{
61	return ldap_unbind_ext( ld, sctrls, cctrls );
62}
63
64int
65ldap_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
73int
74ldap_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
198int
199ldap_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 */
206int
207ldap_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