1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is Mozilla Communicator client code, released
15 * March 31, 1998.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-1999
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37 /*
38 * Copyright (c) 1990 Regents of the University of Michigan.
39 * All rights reserved.
40 */
41
42 /*
43 * unbind.c
44 */
45
46 #if 0
47 # ifndef lint
48 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
49 # endif
50 #endif
51
52 #include "ldap-int.h"
53
ldap_unbind(LDAP * ld)54 int LDAP_CALL ldap_unbind(LDAP* ld) {
55 LDAPDebug(LDAP_DEBUG_TRACE, "ldap_unbind\n");
56
57 return (ldap_ld_free(ld, NULL, NULL, 1));
58 }
59
ldap_unbind_s(LDAP * ld)60 int LDAP_CALL ldap_unbind_s(LDAP* ld) {
61 return (ldap_ld_free(ld, NULL, NULL, 1));
62 }
63
ldap_unbind_ext(LDAP * ld,LDAPControl ** serverctrls,LDAPControl ** clientctrls)64 int LDAP_CALL ldap_unbind_ext(LDAP* ld, LDAPControl** serverctrls,
65 LDAPControl** clientctrls) {
66 return (ldap_ld_free(ld, serverctrls, clientctrls, 1));
67 }
68
69 /*
70 * Dispose of the LDAP session ld, including all associated connections
71 * and resources. If close is non-zero, an unbind() request is sent as well.
72 */
ldap_ld_free(LDAP * ld,LDAPControl ** serverctrls,LDAPControl ** clientctrls,int close)73 int ldap_ld_free(LDAP* ld, LDAPControl** serverctrls, LDAPControl** clientctrls,
74 int close) {
75 LDAPMessage *lm, *next;
76 int err = LDAP_SUCCESS;
77 LDAPRequest *lr, *nextlr;
78
79 if (!NSLDAPI_VALID_LDAP_POINTER(ld)) {
80 return (LDAP_PARAM_ERROR);
81 }
82
83 if (ld->ld_sbp->sb_naddr == 0) {
84 LDAP_MUTEX_LOCK(ld, LDAP_REQ_LOCK);
85 /* free LDAP structure and outstanding requests/responses */
86 for (lr = ld->ld_requests; lr != NULL; lr = nextlr) {
87 nextlr = lr->lr_next;
88 nsldapi_free_request(ld, lr, 0);
89 }
90 LDAP_MUTEX_UNLOCK(ld, LDAP_REQ_LOCK);
91
92 /* free and unbind from all open connections */
93 LDAP_MUTEX_LOCK(ld, LDAP_CONN_LOCK);
94 while (ld->ld_conns != NULL) {
95 nsldapi_free_connection(ld, ld->ld_conns, serverctrls, clientctrls, 1,
96 close);
97 }
98 LDAP_MUTEX_UNLOCK(ld, LDAP_CONN_LOCK);
99
100 } else {
101 int i;
102
103 for (i = 0; i < ld->ld_sbp->sb_naddr; ++i) {
104 NSLDAPI_FREE(ld->ld_sbp->sb_addrs[i]);
105 }
106 NSLDAPI_FREE(ld->ld_sbp->sb_addrs);
107 NSLDAPI_FREE(ld->ld_sbp->sb_fromaddr);
108 }
109
110 LDAP_MUTEX_LOCK(ld, LDAP_RESP_LOCK);
111 for (lm = ld->ld_responses; lm != NULL; lm = next) {
112 next = lm->lm_next;
113 ldap_msgfree(lm);
114 }
115 LDAP_MUTEX_UNLOCK(ld, LDAP_RESP_LOCK);
116
117 /* call cache unbind function to allow it to clean up after itself */
118 if (ld->ld_cache_unbind != NULL) {
119 LDAP_MUTEX_LOCK(ld, LDAP_CACHE_LOCK);
120 (void)ld->ld_cache_unbind(ld, 0, 0);
121 LDAP_MUTEX_UNLOCK(ld, LDAP_CACHE_LOCK);
122 }
123
124 /* call the dispose handle I/O callback if one is defined */
125 if (ld->ld_extdisposehandle_fn != NULL) {
126 /*
127 * We always pass the session extended I/O argument to
128 * the dispose handle callback.
129 */
130 ld->ld_extdisposehandle_fn(ld, ld->ld_ext_session_arg);
131 }
132
133 if (ld->ld_error != NULL) NSLDAPI_FREE(ld->ld_error);
134 if (ld->ld_matched != NULL) NSLDAPI_FREE(ld->ld_matched);
135 if (ld->ld_host != NULL) NSLDAPI_FREE(ld->ld_host);
136 if (ld->ld_ufnprefix != NULL) NSLDAPI_FREE(ld->ld_ufnprefix);
137 if (ld->ld_filtd != NULL) ldap_getfilter_free(ld->ld_filtd);
138 if (ld->ld_abandoned != NULL) NSLDAPI_FREE(ld->ld_abandoned);
139 if (ld->ld_sbp != NULL) ber_sockbuf_free(ld->ld_sbp);
140 if (ld->ld_defhost != NULL) NSLDAPI_FREE(ld->ld_defhost);
141 if (ld->ld_servercontrols != NULL) ldap_controls_free(ld->ld_servercontrols);
142 if (ld->ld_clientcontrols != NULL) ldap_controls_free(ld->ld_clientcontrols);
143 if (ld->ld_preferred_language != NULL)
144 NSLDAPI_FREE(ld->ld_preferred_language);
145 nsldapi_iostatus_free(ld);
146 #ifdef LDAP_SASLIO_HOOKS
147 NSLDAPI_FREE(ld->ld_def_sasl_mech);
148 NSLDAPI_FREE(ld->ld_def_sasl_realm);
149 NSLDAPI_FREE(ld->ld_def_sasl_authcid);
150 NSLDAPI_FREE(ld->ld_def_sasl_authzid);
151 #endif
152
153 /*
154 * XXXmcs: should use cache function pointers to hook in memcache
155 */
156 if (ld->ld_memcache != NULL) {
157 ldap_memcache_set(ld, NULL);
158 }
159
160 /* free all mutexes we have allocated */
161 nsldapi_mutex_free_all(ld);
162 NSLDAPI_FREE(ld->ld_mutex);
163
164 NSLDAPI_FREE((char*)ld);
165
166 return (err);
167 }
168
nsldapi_send_unbind(LDAP * ld,Sockbuf * sb,LDAPControl ** serverctrls,LDAPControl ** clientctrls)169 int nsldapi_send_unbind(LDAP* ld, Sockbuf* sb, LDAPControl** serverctrls,
170 LDAPControl** clientctrls) {
171 BerElement* ber;
172 int err, msgid;
173
174 LDAPDebug(LDAP_DEBUG_TRACE, "nsldapi_send_unbind\n");
175
176 /* create a message to send */
177 if ((err = nsldapi_alloc_ber_with_options(ld, &ber)) != LDAP_SUCCESS) {
178 return (err);
179 }
180
181 /* fill it in */
182 LDAP_MUTEX_LOCK(ld, LDAP_MSGID_LOCK);
183 msgid = ++ld->ld_msgid;
184 LDAP_MUTEX_UNLOCK(ld, LDAP_MSGID_LOCK);
185
186 if (ber_printf(ber, "{itn", msgid, LDAP_REQ_UNBIND) == -1) {
187 ber_free(ber, 1);
188 err = LDAP_ENCODING_ERROR;
189 LDAP_SET_LDERRNO(ld, err, NULL, NULL);
190 return (err);
191 }
192
193 if ((err = nsldapi_put_controls(ld, serverctrls, 1, ber)) != LDAP_SUCCESS) {
194 ber_free(ber, 1);
195 return (err);
196 }
197
198 /* send the message */
199 err = nsldapi_send_ber_message(ld, sb, ber, 1 /* free ber */,
200 0 /* will not handle EPIPE */);
201 if (err != 0) {
202 ber_free(ber, 1);
203 if (err != -2) {
204 /*
205 * Message could not be sent, and the reason is
206 * something other than a "would block" error.
207 * Note that we ignore "would block" errors because
208 * it is not critical that an UnBind request
209 * actually reach the LDAP server.
210 */
211 err = LDAP_SERVER_DOWN;
212 LDAP_SET_LDERRNO(ld, err, NULL, NULL);
213 return (err);
214 }
215 }
216
217 return (LDAP_SUCCESS);
218 }
219