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