]> git.sur5r.net Git - openldap/blob - libraries/libldap/unbind.c
1d23cc71cfd660f334b6fd229670229f81fba854
[openldap] / libraries / libldap / unbind.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2017 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         LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
84         /* Someone else is still using this ld. */
85         if (ld->ld_ldcrefcnt > 1) {     /* but not last thread */
86                 /* clean up self only */
87                 ld->ld_ldcrefcnt--;
88                 if ( ld->ld_error != NULL ) {
89                         LDAP_FREE( ld->ld_error );
90                         ld->ld_error = NULL;
91                 }
92
93                 if ( ld->ld_matched != NULL ) {
94                         LDAP_FREE( ld->ld_matched );
95                         ld->ld_matched = NULL;
96                 }
97                 if ( ld->ld_referrals != NULL) {
98                         LDAP_VFREE(ld->ld_referrals);
99                         ld->ld_referrals = NULL;
100                 }
101                 LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
102                 LDAP_FREE( (char *) ld );
103                 return( err );
104         }
105
106         /* This ld is the last thread. */
107         LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
108
109         /* free LDAP structure and outstanding requests/responses */
110         LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
111         while ( ld->ld_requests != NULL ) {
112                 ldap_free_request( ld, ld->ld_requests );
113         }
114         LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
115         LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
116
117         /* free and unbind from all open connections */
118         while ( ld->ld_conns != NULL ) {
119                 ldap_free_connection( ld, ld->ld_conns, 1, close );
120         }
121         LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
122         LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
123         for ( lm = ld->ld_responses; lm != NULL; lm = next ) {
124                 next = lm->lm_next;
125                 ldap_msgfree( lm );
126         }
127
128         if ( ld->ld_abandoned != NULL ) {
129                 LDAP_FREE( ld->ld_abandoned );
130                 ld->ld_abandoned = NULL;
131         }
132         LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
133
134         ber_sockbuf_free( ld->ld_sb );
135
136         LDAP_MUTEX_LOCK( &ld->ld_ldopts_mutex );
137
138         /* final close callbacks */
139         {
140                 ldaplist *ll, *next;
141
142                 for ( ll = ld->ld_options.ldo_conn_cbs; ll; ll = next ) {
143                         ldap_conncb *cb = ll->ll_data;
144                         next = ll->ll_next;
145                         cb->lc_del( ld, NULL, cb );
146                         LDAP_FREE( ll );
147                 }
148         }
149
150         if ( ld->ld_error != NULL ) {
151                 LDAP_FREE( ld->ld_error );
152                 ld->ld_error = NULL;
153         }
154
155         if ( ld->ld_matched != NULL ) {
156                 LDAP_FREE( ld->ld_matched );
157                 ld->ld_matched = NULL;
158         }
159
160         if ( ld->ld_referrals != NULL) {
161                 LDAP_VFREE(ld->ld_referrals);
162                 ld->ld_referrals = NULL;
163         }
164
165         if ( ld->ld_selectinfo != NULL ) {
166                 ldap_free_select_info( ld->ld_selectinfo );
167                 ld->ld_selectinfo = NULL;
168         }
169
170         if ( ld->ld_options.ldo_defludp != NULL ) {
171                 ldap_free_urllist( ld->ld_options.ldo_defludp );
172                 ld->ld_options.ldo_defludp = NULL;
173         }
174
175 #ifdef LDAP_CONNECTIONLESS
176         if ( ld->ld_options.ldo_peer != NULL ) {
177                 LDAP_FREE( ld->ld_options.ldo_peer );
178                 ld->ld_options.ldo_peer = NULL;
179         }
180
181         if ( ld->ld_options.ldo_cldapdn != NULL ) {
182                 LDAP_FREE( ld->ld_options.ldo_cldapdn );
183                 ld->ld_options.ldo_cldapdn = NULL;
184         }
185 #endif
186
187 #ifdef HAVE_CYRUS_SASL
188         if ( ld->ld_options.ldo_def_sasl_mech != NULL ) {
189                 LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
190                 ld->ld_options.ldo_def_sasl_mech = NULL;
191         }
192
193         if ( ld->ld_options.ldo_def_sasl_realm != NULL ) {
194                 LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
195                 ld->ld_options.ldo_def_sasl_realm = NULL;
196         }
197
198         if ( ld->ld_options.ldo_def_sasl_authcid != NULL ) {
199                 LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
200                 ld->ld_options.ldo_def_sasl_authcid = NULL;
201         }
202
203         if ( ld->ld_options.ldo_def_sasl_authzid != NULL ) {
204                 LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
205                 ld->ld_options.ldo_def_sasl_authzid = NULL;
206         }
207 #endif
208
209 #ifdef HAVE_TLS
210         ldap_int_tls_destroy( &ld->ld_options );
211 #endif
212
213         if ( ld->ld_options.ldo_sctrls != NULL ) {
214                 ldap_controls_free( ld->ld_options.ldo_sctrls );
215                 ld->ld_options.ldo_sctrls = NULL;
216         }
217
218         if ( ld->ld_options.ldo_cctrls != NULL ) {
219                 ldap_controls_free( ld->ld_options.ldo_cctrls );
220                 ld->ld_options.ldo_cctrls = NULL;
221         }
222         LDAP_MUTEX_UNLOCK( &ld->ld_ldopts_mutex );
223
224 #ifdef LDAP_R_COMPILE
225         ldap_pvt_thread_mutex_destroy( &ld->ld_msgid_mutex );
226         ldap_pvt_thread_mutex_destroy( &ld->ld_conn_mutex );
227         ldap_pvt_thread_mutex_destroy( &ld->ld_req_mutex );
228         ldap_pvt_thread_mutex_destroy( &ld->ld_res_mutex );
229         ldap_pvt_thread_mutex_destroy( &ld->ld_abandon_mutex );
230         ldap_pvt_thread_mutex_destroy( &ld->ld_ldopts_mutex );
231         ldap_pvt_thread_mutex_destroy( &ld->ld_ldcmutex );
232 #endif
233 #ifndef NDEBUG
234         LDAP_TRASH(ld);
235 #endif
236         LDAP_FREE( (char *) ld->ldc );
237         LDAP_FREE( (char *) ld );
238
239         return( err );
240 }
241
242 int
243 ldap_destroy( LDAP *ld )
244 {
245         return ( ldap_ld_free( ld, 1, NULL, NULL ) );
246 }
247
248 int
249 ldap_unbind_s( LDAP *ld )
250 {
251         return( ldap_unbind_ext( ld, NULL, NULL ) );
252 }
253
254 /* FIXME: this function is called only by ldap_free_connection(),
255  * which, most of the times, is called with ld_req_mutex locked */
256 int
257 ldap_send_unbind(
258         LDAP *ld,
259         Sockbuf *sb,
260         LDAPControl **sctrls,
261         LDAPControl **cctrls )
262 {
263         BerElement      *ber;
264         ber_int_t       id;
265
266         Debug( LDAP_DEBUG_TRACE, "ldap_send_unbind\n", 0, 0, 0 );
267
268 #ifdef LDAP_CONNECTIONLESS
269         if (LDAP_IS_UDP(ld))
270                 return LDAP_SUCCESS;
271 #endif
272         /* create a message to send */
273         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
274                 return( ld->ld_errno );
275         }
276
277         LDAP_NEXT_MSGID(ld, id);
278
279         /* fill it in */
280         if ( ber_printf( ber, "{itn" /*}*/, id,
281             LDAP_REQ_UNBIND ) == -1 ) {
282                 ld->ld_errno = LDAP_ENCODING_ERROR;
283                 ber_free( ber, 1 );
284                 return( ld->ld_errno );
285         }
286
287         /* Put Server Controls */
288         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
289                 ber_free( ber, 1 );
290                 return ld->ld_errno;
291         }
292
293         if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) {
294                 ld->ld_errno = LDAP_ENCODING_ERROR;
295                 ber_free( ber, 1 );
296                 return( ld->ld_errno );
297         }
298
299         ld->ld_errno = LDAP_SUCCESS;
300         /* send the message */
301         if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) {
302                 ld->ld_errno = LDAP_SERVER_DOWN;
303         }
304
305         return( ld->ld_errno );
306 }