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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* ap_ldap_rebind.c -- LDAP rebind callbacks for referrals
19 * The LDAP SDK allows a callback to be set to enable rebinding
20 * for referral processing.
25 #include "ap_config.h"
30 #include "apr_errno.h"
31 #include "apr_strings.h"
35 /* Used to store information about connections for use in the referral rebind callback. */
36 struct ap_ldap_rebind_entry {
41 struct ap_ldap_rebind_entry *next;
43 typedef struct ap_ldap_rebind_entry ap_ldap_rebind_entry_t;
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;
54 static apr_thread_mutex_t *ap_ldap_xref_lock = NULL;
56 static ap_ldap_rebind_entry_t *xref_head = NULL;
58 static int ap_ldap_rebind_set_callback(LDAP *ld);
59 static apr_status_t ap_ldap_rebind_remove_helper(void *data);
61 static apr_status_t ap_ldap_pool_cleanup_set_null(void *data_)
63 void **ptr = (void **)data_;
69 /* AP utility routine used to create the xref_lock. */
70 LDAP_DECLARE(apr_status_t) ap_ldap_rebind_init(apr_pool_t *pool)
72 apr_status_t retcode = APR_SUCCESS;
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);
83 if (ap_ldap_xref_lock == NULL) {
84 retcode = apr_thread_mutex_create(&ap_ldap_xref_lock, APR_THREAD_MUTEX_DEFAULT, pool);
92 LDAP_DECLARE(apr_status_t) ap_ldap_rebind_add(apr_pool_t *pool,
97 apr_status_t retcode = APR_SUCCESS;
98 ap_ldap_rebind_entry_t *new_xref;
104 new_xref = (ap_ldap_rebind_entry_t *)apr_pcalloc(pool, sizeof(ap_ldap_rebind_entry_t));
106 new_xref->pool = pool;
107 new_xref->index = ld;
109 new_xref->bindDN = apr_pstrdup(pool, bindDN);
112 new_xref->bindPW = apr_pstrdup(pool, bindPW);
116 retcode = apr_thread_mutex_lock(ap_ldap_xref_lock);
117 if (retcode != APR_SUCCESS) {
122 new_xref->next = xref_head;
123 xref_head = new_xref;
126 retcode = apr_thread_mutex_unlock(ap_ldap_xref_lock);
127 if (retcode != APR_SUCCESS) {
136 retcode = ap_ldap_rebind_set_callback(ld);
137 if (APR_SUCCESS != retcode) {
138 ap_ldap_rebind_remove(ld);
142 apr_pool_cleanup_register(pool, ld,
143 ap_ldap_rebind_remove_helper,
144 apr_pool_cleanup_null);
150 LDAP_DECLARE(apr_status_t) ap_ldap_rebind_remove(LDAP *ld)
152 ap_ldap_rebind_entry_t *tmp_xref, *prev = NULL;
153 apr_status_t retcode = 0;
160 retcode = apr_thread_mutex_lock(ap_ldap_xref_lock);
161 if (retcode != APR_SUCCESS) {
165 tmp_xref = xref_head;
167 while ((tmp_xref) && (tmp_xref->index != ld)) {
169 tmp_xref = tmp_xref->next;
173 if (tmp_xref == xref_head) {
174 xref_head = xref_head->next;
177 prev->next = tmp_xref->next;
180 /* tmp_xref and its contents were pool allocated so they don't need to be freed here. */
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);
188 retcode = apr_thread_mutex_unlock(ap_ldap_xref_lock);
189 if (retcode != APR_SUCCESS) {
197 static apr_status_t ap_ldap_rebind_remove_helper(void *data)
199 LDAP *ld = (LDAP *)data;
200 ap_ldap_rebind_remove(ld);
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)
207 ap_ldap_rebind_entry_t *tmp_xref, *match = NULL;
214 apr_thread_mutex_lock(ap_ldap_xref_lock);
216 tmp_xref = xref_head;
219 if (tmp_xref->index == ld) {
224 tmp_xref = tmp_xref->next;
229 apr_thread_mutex_unlock(ap_ldap_xref_lock);
236 #if AP_HAS_TIVOLI_LDAPSDK
238 /* LDAP_rebindproc() Tivoli LDAP style
239 * Rebind callback function. Called when chasing referrals. See API docs.
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)
247 static int LDAP_rebindproc(LDAP *ld, char **binddnp, char **passwdp, int *methodp, int freeit)
250 ap_ldap_rebind_entry_t *my_conn;
252 *methodp = LDAP_AUTH_SIMPLE;
253 my_conn = ap_ldap_rebind_lookup(ld);
255 if ((my_conn) && (my_conn->bindDN != NULL)) {
256 *binddnp = strdup(my_conn->bindDN);
257 *passwdp = strdup(my_conn->bindPW);
274 static int ap_ldap_rebind_set_callback(LDAP *ld)
276 ldap_set_rebind_proc(ld, (LDAPRebindProc)LDAP_rebindproc);
280 #elif AP_HAS_OPENLDAP_LDAPSDK
282 /* LDAP_rebindproc() openLDAP V3 style
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
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
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)
301 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request,
305 ap_ldap_rebind_entry_t *my_conn;
306 const char *bindDN = NULL;
307 const char *bindPW = NULL;
309 my_conn = ap_ldap_rebind_lookup(ld);
311 if ((my_conn) && (my_conn->bindDN != NULL)) {
312 bindDN = my_conn->bindDN;
313 bindPW = my_conn->bindPW;
316 return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
319 static int ap_ldap_rebind_set_callback(LDAP *ld)
321 #if defined(LDAP_SET_REBIND_PROC_THREE)
322 ldap_set_rebind_proc(ld, LDAP_rebindproc, NULL);
324 ldap_set_rebind_proc(ld, LDAP_rebindproc);
329 #elif AP_HAS_NOVELL_LDAPSDK
331 /* LDAP_rebindproc() openLDAP V3 style
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
338 static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid)
341 ap_ldap_rebind_entry_t *my_conn;
342 const char *bindDN = NULL;
343 const char *bindPW = NULL;
345 my_conn = ap_ldap_rebind_lookup(ld);
347 if ((my_conn) && (my_conn->bindDN != NULL)) {
348 bindDN = my_conn->bindDN;
349 bindPW = my_conn->bindPW;
352 return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
355 static int ap_ldap_rebind_set_callback(LDAP *ld)
357 ldap_set_rebind_proc(ld, LDAP_rebindproc);
361 #else /* Implementation not recognised */
363 static int ap_ldap_rebind_set_callback(LDAP *ld)
371 #endif /* AP_HAS_LDAP */