]> granicus.if.org Git - apache/blob - modules/ldap/ap_ldap_rebind.c
PR51307: Fix ldap_rebind build error when ldap is enabled and APR is built without...
[apache] / modules / ldap / ap_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 /*  ap_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 "ap_config.h"
26 #include "ap_ldap.h"
27
28 #if AP_HAS_LDAP
29
30 #include "apr_errno.h"
31 #include "apr_strings.h"
32
33 #include "stdio.h"
34
35 /* Used to store information about connections for use in the referral rebind callback. */
36 struct ap_ldap_rebind_entry {
37     apr_pool_t *pool;
38     LDAP *index;
39     const char *bindDN;
40     const char *bindPW;
41     struct ap_ldap_rebind_entry *next;
42 };
43 typedef struct ap_ldap_rebind_entry ap_ldap_rebind_entry_t;
44
45
46 #ifdef NETWARE
47 #define get_apd \
48     APP_DATA* apd = (APP_DATA*)get_app_data(gLibId); \
49     ap_ldap_xref_lock = (apr_thread_mutex_t *)apd->gs_ldap_xref_lock; \
50     xref_head = (ap_ldap_rebind_entry_t *)apd->gs_xref_head;
51 #endif
52
53 #if APR_HAS_THREADS
54 static apr_thread_mutex_t *ap_ldap_xref_lock = NULL;
55 #endif
56 static ap_ldap_rebind_entry_t *xref_head = NULL;
57
58 static int ap_ldap_rebind_set_callback(LDAP *ld);
59 static apr_status_t ap_ldap_rebind_remove_helper(void *data);
60
61 static apr_status_t ap_ldap_pool_cleanup_set_null(void *data_)
62 {
63     void **ptr = (void **)data_;
64     *ptr = NULL;
65     return APR_SUCCESS;
66 }
67
68
69 /* AP utility routine used to create the xref_lock. */
70 LDAP_DECLARE(apr_status_t) ap_ldap_rebind_init(apr_pool_t *pool)
71 {
72     apr_status_t retcode = APR_SUCCESS;
73
74 #ifdef NETWARE
75     get_apd
76 #endif
77
78 #if APR_HAS_THREADS
79     /* run after apr_thread_mutex_create cleanup */
80     apr_pool_cleanup_register(pool, &ap_ldap_xref_lock, ap_ldap_pool_cleanup_set_null, 
81                               apr_pool_cleanup_null);
82
83     if (ap_ldap_xref_lock == NULL) {
84         retcode = apr_thread_mutex_create(&ap_ldap_xref_lock, APR_THREAD_MUTEX_DEFAULT, pool);
85     }
86 #endif
87
88     return(retcode);
89 }
90
91
92 LDAP_DECLARE(apr_status_t) ap_ldap_rebind_add(apr_pool_t *pool,
93                                                    LDAP *ld, 
94                                                    const char *bindDN, 
95                                                    const char *bindPW)
96 {
97     apr_status_t retcode = APR_SUCCESS;
98     ap_ldap_rebind_entry_t *new_xref;
99
100 #ifdef NETWARE
101     get_apd
102 #endif
103
104     new_xref = (ap_ldap_rebind_entry_t *)apr_pcalloc(pool, sizeof(ap_ldap_rebind_entry_t));
105     if (new_xref) {
106         new_xref->pool = pool;
107         new_xref->index = ld;
108         if (bindDN) {
109             new_xref->bindDN = apr_pstrdup(pool, bindDN);
110         }
111         if (bindPW) {
112             new_xref->bindPW = apr_pstrdup(pool, bindPW);
113         }
114     
115 #if APR_HAS_THREADS
116        retcode = apr_thread_mutex_lock(ap_ldap_xref_lock);
117        if (retcode != APR_SUCCESS) { 
118            return retcode;
119        }
120 #endif
121     
122         new_xref->next = xref_head;
123         xref_head = new_xref;
124     
125 #if APR_HAS_THREADS
126         retcode = apr_thread_mutex_unlock(ap_ldap_xref_lock);
127         if (retcode != APR_SUCCESS) { 
128            return retcode;
129         }
130 #endif
131     }
132     else {
133         return(APR_ENOMEM);
134     }
135
136     retcode = ap_ldap_rebind_set_callback(ld);
137     if (APR_SUCCESS != retcode) {
138         ap_ldap_rebind_remove(ld);
139         return retcode;
140     }
141
142     apr_pool_cleanup_register(pool, ld,
143                               ap_ldap_rebind_remove_helper,
144                               apr_pool_cleanup_null);
145
146     return(APR_SUCCESS);
147 }
148
149
150 LDAP_DECLARE(apr_status_t) ap_ldap_rebind_remove(LDAP *ld)
151 {
152     ap_ldap_rebind_entry_t *tmp_xref, *prev = NULL;
153     apr_status_t retcode = 0;
154
155 #ifdef NETWARE
156     get_apd
157 #endif
158
159 #if APR_HAS_THREADS
160     retcode = apr_thread_mutex_lock(ap_ldap_xref_lock);
161     if (retcode != APR_SUCCESS) { 
162         return retcode;
163     }
164 #endif
165     tmp_xref = xref_head;
166
167     while ((tmp_xref) && (tmp_xref->index != ld)) {
168         prev = tmp_xref;
169         tmp_xref = tmp_xref->next;
170     }
171
172     if (tmp_xref) {
173         if (tmp_xref == xref_head) {
174             xref_head = xref_head->next;
175         }
176         else {
177             prev->next = tmp_xref->next;
178         }
179
180         /* tmp_xref and its contents were pool allocated so they don't need to be freed here. */
181
182         /* remove the cleanup, just in case this was done manually */
183         apr_pool_cleanup_kill(tmp_xref->pool, tmp_xref->index,
184                               ap_ldap_rebind_remove_helper);
185     }
186
187 #if APR_HAS_THREADS
188     retcode = apr_thread_mutex_unlock(ap_ldap_xref_lock);
189     if (retcode != APR_SUCCESS) { 
190        return retcode;
191     }
192 #endif
193     return APR_SUCCESS;
194 }
195
196
197 static apr_status_t ap_ldap_rebind_remove_helper(void *data)
198 {
199     LDAP *ld = (LDAP *)data;
200     ap_ldap_rebind_remove(ld);
201     return APR_SUCCESS;
202 }
203
204 #if AP_HAS_TIVOLI_LDAPSDK || AP_HAS_OPENLDAP_LDAPSDK || AP_HAS_NOVELL_LDAPSDK
205 static ap_ldap_rebind_entry_t *ap_ldap_rebind_lookup(LDAP *ld)
206 {
207     ap_ldap_rebind_entry_t *tmp_xref, *match = NULL;
208
209 #ifdef NETWARE
210     get_apd
211 #endif
212
213 #if APR_HAS_THREADS
214     apr_thread_mutex_lock(ap_ldap_xref_lock);
215 #endif
216     tmp_xref = xref_head;
217
218     while (tmp_xref) {
219         if (tmp_xref->index == ld) {
220             match = tmp_xref;
221             tmp_xref = NULL;
222         }
223         else {
224             tmp_xref = tmp_xref->next;
225         }
226     }
227
228 #if APR_HAS_THREADS
229     apr_thread_mutex_unlock(ap_ldap_xref_lock);
230 #endif
231
232     return (match);
233 }
234 #endif
235
236 #if AP_HAS_TIVOLI_LDAPSDK
237
238 /* LDAP_rebindproc() Tivoli LDAP style
239  *     Rebind callback function. Called when chasing referrals. See API docs.
240  * ON ENTRY:
241  *     ld       Pointer to an LDAP control structure. (input only)
242  *     binddnp  Pointer to an Application DName used for binding (in *or* out)
243  *     passwdp  Pointer to the password associated with the DName (in *or* out)
244  *     methodp  Pointer to the Auth method (output only)
245  *     freeit   Flag to indicate if this is a lookup or a free request (input only)
246  */
247 static int LDAP_rebindproc(LDAP *ld, char **binddnp, char **passwdp, int *methodp, int freeit)
248 {
249     if (!freeit) {
250         ap_ldap_rebind_entry_t *my_conn;
251
252         *methodp = LDAP_AUTH_SIMPLE;
253         my_conn = ap_ldap_rebind_lookup(ld);
254
255         if ((my_conn) && (my_conn->bindDN != NULL)) {
256             *binddnp = strdup(my_conn->bindDN);
257             *passwdp = strdup(my_conn->bindPW);
258         } else {
259             *binddnp = NULL;
260             *passwdp = NULL;
261         }
262     } else {
263         if (*binddnp) {
264             free(*binddnp);
265         }
266         if (*passwdp) {
267             free(*passwdp);
268         }
269     }
270
271     return LDAP_SUCCESS;
272 }
273
274 static int ap_ldap_rebind_set_callback(LDAP *ld)
275 {
276     ldap_set_rebind_proc(ld, (LDAPRebindProc)LDAP_rebindproc);
277     return APR_SUCCESS;
278 }
279
280 #elif AP_HAS_OPENLDAP_LDAPSDK
281
282 /* LDAP_rebindproc() openLDAP V3 style
283  * ON ENTRY:
284  *     ld       Pointer to an LDAP control structure. (input only)
285  *     url      Unused in this routine
286  *     request  Unused in this routine
287  *     msgid    Unused in this routine
288  *     params   Unused in this routine
289  *
290  *     or
291  *
292  *     ld       Pointer to an LDAP control structure. (input only)
293  *     url      Unused in this routine
294  *     request  Unused in this routine
295  *     msgid    Unused in this routine
296  */
297 #if defined(LDAP_SET_REBIND_PROC_THREE)
298 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
299                            ber_int_t msgid, void *params)
300 #else
301 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request,
302                            ber_int_t msgid)
303 #endif
304 {
305     ap_ldap_rebind_entry_t *my_conn;
306     const char *bindDN = NULL;
307     const char *bindPW = NULL;
308
309     my_conn = ap_ldap_rebind_lookup(ld);
310
311     if ((my_conn) && (my_conn->bindDN != NULL)) {
312         bindDN = my_conn->bindDN;
313         bindPW = my_conn->bindPW;
314     }
315
316     return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
317 }
318
319 static int ap_ldap_rebind_set_callback(LDAP *ld)
320 {
321 #if defined(LDAP_SET_REBIND_PROC_THREE)
322     ldap_set_rebind_proc(ld, LDAP_rebindproc, NULL);
323 #else
324     ldap_set_rebind_proc(ld, LDAP_rebindproc);
325 #endif
326     return APR_SUCCESS;
327 }
328
329 #elif AP_HAS_NOVELL_LDAPSDK
330
331 /* LDAP_rebindproc() openLDAP V3 style
332  * ON ENTRY:
333  *     ld       Pointer to an LDAP control structure. (input only)
334  *     url      Unused in this routine
335  *     request  Unused in this routine
336  *     msgid    Unused in this routine
337  */
338 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid)
339 {
340
341     ap_ldap_rebind_entry_t *my_conn;
342     const char *bindDN = NULL;
343     const char *bindPW = NULL;
344
345     my_conn = ap_ldap_rebind_lookup(ld);
346
347     if ((my_conn) && (my_conn->bindDN != NULL)) {
348         bindDN = my_conn->bindDN;
349         bindPW = my_conn->bindPW;
350     }
351
352     return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
353 }
354
355 static int ap_ldap_rebind_set_callback(LDAP *ld)
356 {
357     ldap_set_rebind_proc(ld, LDAP_rebindproc);
358     return APR_SUCCESS;
359 }
360
361 #else         /* Implementation not recognised */
362
363 static int ap_ldap_rebind_set_callback(LDAP *ld)
364 {
365     return APR_ENOTIMPL;
366 }
367
368 #endif
369
370
371 #endif       /* AP_HAS_LDAP */