]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/apr-util/ldap/apr_ldap_rebind.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / apr-util / ldap / apr_ldap_rebind.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (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  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*  apr_ldap_rebind.c -- LDAP rebind callbacks for referrals
18  *
19  *  The LDAP SDK allows a callback to be set to enable rebinding
20  *  for referral processing.
21  *
22  */
23
24 #include "apr.h"
25 #include "apu.h"
26 #include "apu_config.h"
27
28 #if APU_DSO_BUILD
29 #define APU_DSO_LDAP_BUILD
30 #endif
31
32 #include "apr_ldap.h"
33 #include "apr_errno.h"
34 #include "apr_strings.h"
35 #include "apr_ldap_rebind.h"
36
37 #include "stdio.h"
38
39 #if APR_HAS_LDAP
40
41 /* Used to store information about connections for use in the referral rebind callback. */
42 struct apr_ldap_rebind_entry {
43     apr_pool_t *pool;
44     LDAP *index;
45     const char *bindDN;
46     const char *bindPW;
47     struct apr_ldap_rebind_entry *next;
48 };
49 typedef struct apr_ldap_rebind_entry apr_ldap_rebind_entry_t;
50
51
52 #ifdef NETWARE
53 #include "apr_private.h"
54 #define get_apd                 APP_DATA* apd = (APP_DATA*)get_app_data(gLibId);
55 #define apr_ldap_xref_lock      ((apr_thread_mutex_t *)(apd->gs_ldap_xref_lock))
56 #define xref_head               ((apr_ldap_rebind_entry_t *)(apd->gs_xref_head))
57 #else
58 #if APR_HAS_THREADS
59 static apr_thread_mutex_t *apr_ldap_xref_lock = NULL;
60 #endif
61 static apr_ldap_rebind_entry_t *xref_head = NULL;
62 #endif
63
64 static int apr_ldap_rebind_set_callback(LDAP *ld);
65 static apr_status_t apr_ldap_rebind_remove_helper(void *data);
66
67 static apr_status_t apr_ldap_pool_cleanup_set_null(void *data_)
68 {
69     void **ptr = (void **)data_;
70     *ptr = NULL;
71     return APR_SUCCESS;
72 }
73
74
75 /* APR utility routine used to create the xref_lock. */
76 APU_DECLARE_LDAP(apr_status_t) apr_ldap_rebind_init(apr_pool_t *pool)
77 {
78     apr_status_t retcode = APR_SUCCESS;
79
80 #ifdef NETWARE
81     get_apd
82 #endif
83
84 #if APR_HAS_THREADS
85     /* run after apr_thread_mutex_create cleanup */
86     apr_pool_cleanup_register(pool, &apr_ldap_xref_lock, apr_ldap_pool_cleanup_set_null,
87                               apr_pool_cleanup_null);
88
89     if (apr_ldap_xref_lock == NULL) {
90         retcode = apr_thread_mutex_create(&apr_ldap_xref_lock, APR_THREAD_MUTEX_DEFAULT, pool);
91     }
92 #endif
93
94     return(retcode);
95 }
96
97
98 APU_DECLARE_LDAP(apr_status_t) apr_ldap_rebind_add(apr_pool_t *pool,
99                                                    LDAP *ld, 
100                                                    const char *bindDN, 
101                                                    const char *bindPW)
102 {
103     apr_status_t retcode = APR_SUCCESS;
104     apr_ldap_rebind_entry_t *new_xref;
105
106 #ifdef NETWARE
107     get_apd
108 #endif
109
110     new_xref = (apr_ldap_rebind_entry_t *)apr_pcalloc(pool, sizeof(apr_ldap_rebind_entry_t));
111     if (new_xref) {
112         new_xref->pool = pool;
113         new_xref->index = ld;
114         if (bindDN) {
115             new_xref->bindDN = apr_pstrdup(pool, bindDN);
116         }
117         if (bindPW) {
118             new_xref->bindPW = apr_pstrdup(pool, bindPW);
119         }
120     
121 #if APR_HAS_THREADS
122        retcode = apr_thread_mutex_lock(apr_ldap_xref_lock);
123        if (retcode != APR_SUCCESS) { 
124            return retcode;
125        }
126 #endif
127     
128         new_xref->next = xref_head;
129         xref_head = new_xref;
130     
131 #if APR_HAS_THREADS
132         retcode = apr_thread_mutex_unlock(apr_ldap_xref_lock);
133         if (retcode != APR_SUCCESS) { 
134            return retcode;
135         }
136 #endif
137     }
138     else {
139         return(APR_ENOMEM);
140     }
141
142     retcode = apr_ldap_rebind_set_callback(ld);
143     if (APR_SUCCESS != retcode) {
144         apr_ldap_rebind_remove(ld);
145         return retcode;
146     }
147
148     apr_pool_cleanup_register(pool, ld,
149                               apr_ldap_rebind_remove_helper,
150                               apr_pool_cleanup_null);
151
152     return(APR_SUCCESS);
153 }
154
155
156 APU_DECLARE_LDAP(apr_status_t) apr_ldap_rebind_remove(LDAP *ld)
157 {
158     apr_ldap_rebind_entry_t *tmp_xref, *prev = NULL;
159     apr_status_t retcode = 0;
160
161 #ifdef NETWARE
162     get_apd
163 #endif
164
165 #if APR_HAS_THREADS
166     retcode = apr_thread_mutex_lock(apr_ldap_xref_lock);
167     if (retcode != APR_SUCCESS) { 
168         return retcode;
169     }
170 #endif
171     tmp_xref = xref_head;
172
173     while ((tmp_xref) && (tmp_xref->index != ld)) {
174         prev = tmp_xref;
175         tmp_xref = tmp_xref->next;
176     }
177
178     if (tmp_xref) {
179         if (tmp_xref == xref_head) {
180             xref_head = xref_head->next;
181         }
182         else {
183             prev->next = tmp_xref->next;
184         }
185
186         /* tmp_xref and its contents were pool allocated so they don't need to be freed here. */
187
188         /* remove the cleanup, just in case this was done manually */
189         apr_pool_cleanup_kill(tmp_xref->pool, tmp_xref->index,
190                               apr_ldap_rebind_remove_helper);
191     }
192
193 #if APR_HAS_THREADS
194     retcode = apr_thread_mutex_unlock(apr_ldap_xref_lock);
195     if (retcode != APR_SUCCESS) { 
196        return retcode;
197     }
198 #endif
199     return APR_SUCCESS;
200 }
201
202
203 static apr_status_t apr_ldap_rebind_remove_helper(void *data)
204 {
205     LDAP *ld = (LDAP *)data;
206     apr_ldap_rebind_remove(ld);
207     return APR_SUCCESS;
208 }
209
210 #if APR_HAS_TIVOLI_LDAPSDK || APR_HAS_OPENLDAP_LDAPSDK || APR_HAS_NOVELL_LDAPSDK
211 static apr_ldap_rebind_entry_t *apr_ldap_rebind_lookup(LDAP *ld)
212 {
213     apr_ldap_rebind_entry_t *tmp_xref, *match = NULL;
214
215 #ifdef NETWARE
216     get_apd
217 #endif
218
219 #if APR_HAS_THREADS
220     apr_thread_mutex_lock(apr_ldap_xref_lock);
221 #endif
222     tmp_xref = xref_head;
223
224     while (tmp_xref) {
225         if (tmp_xref->index == ld) {
226             match = tmp_xref;
227             tmp_xref = NULL;
228         }
229         else {
230             tmp_xref = tmp_xref->next;
231         }
232     }
233
234 #if APR_HAS_THREADS
235     apr_thread_mutex_unlock(apr_ldap_xref_lock);
236 #endif
237
238     return (match);
239 }
240 #endif
241
242 #if APR_HAS_TIVOLI_LDAPSDK
243
244 /* LDAP_rebindproc() Tivoli LDAP style
245  *     Rebind callback function. Called when chasing referrals. See API docs.
246  * ON ENTRY:
247  *     ld       Pointer to an LDAP control structure. (input only)
248  *     binddnp  Pointer to an Application DName used for binding (in *or* out)
249  *     passwdp  Pointer to the password associated with the DName (in *or* out)
250  *     methodp  Pointer to the Auth method (output only)
251  *     freeit   Flag to indicate if this is a lookup or a free request (input only)
252  */
253 static int LDAP_rebindproc(LDAP *ld, char **binddnp, char **passwdp, int *methodp, int freeit)
254 {
255     if (!freeit) {
256         apr_ldap_rebind_entry_t *my_conn;
257
258         *methodp = LDAP_AUTH_SIMPLE;
259         my_conn = apr_ldap_rebind_lookup(ld);
260
261         if ((my_conn) && (my_conn->bindDN != NULL)) {
262             *binddnp = strdup(my_conn->bindDN);
263             *passwdp = strdup(my_conn->bindPW);
264         } else {
265             *binddnp = NULL;
266             *passwdp = NULL;
267         }
268     } else {
269         if (*binddnp) {
270             free(*binddnp);
271         }
272         if (*passwdp) {
273             free(*passwdp);
274         }
275     }
276
277     return LDAP_SUCCESS;
278 }
279
280 static int apr_ldap_rebind_set_callback(LDAP *ld)
281 {
282     ldap_set_rebind_proc(ld, (LDAPRebindProc)LDAP_rebindproc);
283     return APR_SUCCESS;
284 }
285
286 #elif APR_HAS_OPENLDAP_LDAPSDK
287
288 /* LDAP_rebindproc() openLDAP V3 style
289  * ON ENTRY:
290  *     ld       Pointer to an LDAP control structure. (input only)
291  *     url      Unused in this routine
292  *     request  Unused in this routine
293  *     msgid    Unused in this routine
294  *     params   Unused in this routine
295  *
296  *     or
297  *
298  *     ld       Pointer to an LDAP control structure. (input only)
299  *     url      Unused in this routine
300  *     request  Unused in this routine
301  *     msgid    Unused in this routine
302  */
303 #if defined(LDAP_SET_REBIND_PROC_THREE)
304 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
305                            ber_int_t msgid, void *params)
306 #else
307 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request,
308                            ber_int_t msgid)
309 #endif
310 {
311     apr_ldap_rebind_entry_t *my_conn;
312     const char *bindDN = NULL;
313     const char *bindPW = NULL;
314
315     my_conn = apr_ldap_rebind_lookup(ld);
316
317     if ((my_conn) && (my_conn->bindDN != NULL)) {
318         bindDN = my_conn->bindDN;
319         bindPW = my_conn->bindPW;
320     }
321
322     return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
323 }
324
325 static int apr_ldap_rebind_set_callback(LDAP *ld)
326 {
327 #if defined(LDAP_SET_REBIND_PROC_THREE)
328     ldap_set_rebind_proc(ld, LDAP_rebindproc, NULL);
329 #else
330     ldap_set_rebind_proc(ld, LDAP_rebindproc);
331 #endif
332     return APR_SUCCESS;
333 }
334
335 #elif APR_HAS_NOVELL_LDAPSDK
336
337 /* LDAP_rebindproc() openLDAP V3 style
338  * ON ENTRY:
339  *     ld       Pointer to an LDAP control structure. (input only)
340  *     url      Unused in this routine
341  *     request  Unused in this routine
342  *     msgid    Unused in this routine
343  */
344 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid)
345 {
346
347     apr_ldap_rebind_entry_t *my_conn;
348     const char *bindDN = NULL;
349     const char *bindPW = NULL;
350
351     my_conn = apr_ldap_rebind_lookup(ld);
352
353     if ((my_conn) && (my_conn->bindDN != NULL)) {
354         bindDN = my_conn->bindDN;
355         bindPW = my_conn->bindPW;
356     }
357
358     return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
359 }
360
361 static int apr_ldap_rebind_set_callback(LDAP *ld)
362 {
363     ldap_set_rebind_proc(ld, LDAP_rebindproc);
364     return APR_SUCCESS;
365 }
366
367 #else         /* Implementation not recognised */
368
369 static int apr_ldap_rebind_set_callback(LDAP *ld)
370 {
371     return APR_ENOTIMPL;
372 }
373
374 #endif
375
376
377 #endif       /* APR_HAS_LDAP */