View | Details | Raw Unified | Return to bug 26538
Collapse All | Expand All

(-)ldap/apr_ldap_rebind.c (+251 lines)
Line 0 Link Here
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 "apr_ldap.h"
27
#include "apr_errno.h"
28
#include "apr_strings.h"
29
#include "apr_ldap_rebind.h"
30
31
#include "stdio.h"
32
33
#if APR_HAS_THREADS
34
static apr_thread_mutex_t *apr_ldap_xref_lock = NULL;
35
#endif
36
37
/* Used to store information about connections for use in the referral rebind callback. */
38
struct apr_ldap_rebind_entry {
39
    LDAP *index;
40
    const char *bindDN;
41
    const char *bindPW;
42
    struct apr_ldap_rebind_entry *next;
43
};
44
typedef struct apr_ldap_rebind_entry apr_ldap_rebind_entry_t;
45
46
static apr_ldap_rebind_entry_t *xref_head = NULL;
47
48
static int apr_ldap_rebind_set_callback(LDAP *ld);
49
static apr_status_t apr_ldap_rebind_remove_helper(void *data);
50
51
/* APR utility routine used to create the xref_lock. */
52
APU_DECLARE(apr_status_t) apr_ldap_rebind_init(apr_pool_t *pool)
53
{
54
    apr_status_t retcode = APR_SUCCESS;
55
56
#if APR_HAS_THREADS
57
    if (apr_ldap_xref_lock == NULL) {
58
        retcode = apr_thread_mutex_create(&apr_ldap_xref_lock, APR_THREAD_MUTEX_DEFAULT, pool);
59
    }
60
#endif
61
62
    return(retcode);
63
}
64
65
66
/*************************************************************************************/
67
APU_DECLARE(apr_status_t) apr_ldap_rebind_add(apr_pool_t *pool, LDAP *ld, const char *bindDN, const char *bindPW)
68
{
69
    apr_status_t retcode = APR_SUCCESS;
70
    apr_ldap_rebind_entry_t *new_xref;
71
72
    new_xref = (apr_ldap_rebind_entry_t *)apr_pcalloc(pool, sizeof(apr_ldap_rebind_entry_t));
73
    if (new_xref) {
74
        new_xref->index = ld;
75
        if (bindDN) {
76
            new_xref->bindDN = apr_pstrdup(pool, bindDN);
77
        }
78
        if (bindPW) {
79
            new_xref->bindPW = apr_pstrdup(pool, bindPW);
80
        }
81
    
82
#if APR_HAS_THREADS
83
       apr_thread_mutex_lock(apr_ldap_xref_lock);
84
#endif
85
    
86
        new_xref->next = xref_head;
87
        xref_head = new_xref;
88
    
89
#if APR_HAS_THREADS
90
        apr_thread_mutex_unlock(apr_ldap_xref_lock);
91
#endif
92
    }
93
    else {
94
        return(APR_ENOMEM);
95
    }
96
97
    retcode = apr_ldap_rebind_set_callback(ld);
98
    if (APR_SUCCESS != retcode) {
99
        apr_ldap_rebind_remove(ld);
100
        return retcode;
101
    }
102
103
    apr_pool_cleanup_register(pool, ld,
104
                              apr_ldap_rebind_remove_helper,
105
                              apr_pool_cleanup_null);
106
107
    return(APR_SUCCESS);
108
}
109
110
/*************************************************************************************/
111
APU_DECLARE(apr_status_t) apr_ldap_rebind_remove(LDAP *ld)
112
{
113
    apr_ldap_rebind_entry_t *tmp_xref, *prev = NULL;
114
115
#if APR_HAS_THREADS
116
    apr_thread_mutex_lock(apr_ldap_xref_lock);
117
#endif
118
    tmp_xref = xref_head;
119
120
    while ((tmp_xref) && (tmp_xref->index != ld)) {
121
        prev = tmp_xref;
122
        tmp_xref = tmp_xref->next;
123
    }
124
125
    if (tmp_xref) {
126
        if (tmp_xref == xref_head) {
127
            xref_head = xref_head->next;
128
        }
129
        else {
130
            prev->next = tmp_xref->next;
131
        }
132
        /* tmp_xref and its contents were pool allocated so they don't need to be freed here. */
133
    }
134
135
#if APR_HAS_THREADS
136
    apr_thread_mutex_unlock(apr_ldap_xref_lock);
137
#endif
138
    return APR_SUCCESS;
139
}
140
141
static apr_status_t apr_ldap_rebind_remove_helper(void *data)
142
{
143
    LDAP *ld = (LDAP *)data;
144
    apr_ldap_rebind_remove(ld);
145
    return APR_SUCCESS;
146
}
147
148
/*************************************************************************************/
149
static apr_ldap_rebind_entry_t *apr_ldap_rebind_lookup(LDAP *ld)
150
{
151
    apr_ldap_rebind_entry_t *tmp_xref, *match = NULL;
152
153
#if APR_HAS_THREADS
154
    apr_thread_mutex_lock(apr_ldap_xref_lock);
155
#endif
156
    tmp_xref = xref_head;
157
158
    while (tmp_xref) {
159
        if (tmp_xref->index == ld) {
160
            match = tmp_xref;
161
            tmp_xref = NULL;
162
        }
163
        else {
164
            tmp_xref = tmp_xref->next;
165
        }
166
    }
167
168
#if APR_HAS_THREADS
169
    apr_thread_mutex_unlock(apr_ldap_xref_lock);
170
#endif
171
172
    return (match);
173
}
174
175
/* LDAP_rebindproc() ITDS style
176
 *     Rebind callback function. Called when chasing referrals. See API docs.
177
 * ON ENTRY:
178
 *     ld       Pointer to an LDAP control structure. (input only)
179
 *     binddnp  Pointer to an Application DName used for binding (in *or* out)
180
 *     passwdp  Pointer to the password associated with the DName (in *or* out)
181
 *     methodp  Pointer to the Auth method (output only)
182
 *     freeit   Flag to indicate if this is a lookup or a free request (input only)
183
 */
184
#if APR_HAS_TIVOLI_LDAPSDK
185
static int LDAP_rebindproc(LDAP *ld, char **binddnp, char **passwdp, int *methodp, int freeit)
186
{
187
    if (!freeit) {
188
        apr_ldap_rebind_entry_t *my_conn;
189
190
        *methodp = LDAP_AUTH_SIMPLE;
191
        my_conn = apr_ldap_xref_lookup(ld);
192
193
        if ((my_conn) && (my_conn->bindDN != NULL)) {
194
            *binddnp = strdup(my_conn->bindDN);
195
            *passwdp = strdup(my_conn->bindPW);
196
        } else {
197
            *binddnp = NULL;
198
            *passwdp = NULL;
199
        }
200
    } else {
201
        if (*binddnp) {
202
            free(*binddnp);
203
        }
204
        if (*passwdp) {
205
            free(*passwdp);
206
        }
207
    }
208
209
    return LDAP_SUCCESS;
210
}
211
212
static int apr_ldap_rebind_set_callback(LDAP *ld)
213
{
214
    ldap_set_rebind_proc(ld, (LDAPRebindProc)LDAP_rebindproc);
215
    return APR_SUCCESS;
216
}
217
218
#elif APR_HAS_OPENLDAP_LDAPSDK
219
220
/* LDAP_rebindproc() openLDAP V3 style */
221
static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params)
222
{
223
    apr_ldap_rebind_entry_t *my_conn;
224
    const char *bindDN = NULL;
225
    const char *bindPW = NULL;
226
227
    my_conn = apr_ldap_rebind_lookup(ld);
228
229
    if ((my_conn) && (my_conn->bindDN != NULL)) {
230
        bindDN = my_conn->bindDN;
231
        bindPW = my_conn->bindPW;
232
    }
233
234
    return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
235
}
236
237
static int apr_ldap_rebind_set_callback(LDAP *ld)
238
{
239
    ldap_set_rebind_proc(ld, LDAP_rebindproc, NULL);
240
    return APR_SUCCESS;
241
}
242
243
#else         /* Implementation not recognised */
244
245
static int apr_ldap_rebind_set_callback(LDAP *ld)
246
{
247
    return APR_ENOTIMPL;
248
}
249
250
#endif
251
(-)ldap/NWGNUmakefile (+1 lines)
Lines 231-236 Link Here
231
	$(OBJDIR)/apr_ldap_init.o \
231
	$(OBJDIR)/apr_ldap_init.o \
232
	$(OBJDIR)/apr_ldap_option.o \
232
	$(OBJDIR)/apr_ldap_option.o \
233
	$(OBJDIR)/apr_ldap_url.o \
233
	$(OBJDIR)/apr_ldap_url.o \
234
	$(OBJDIR)/apr_ldap_rebind.o \
234
	$(EOLIST)
235
	$(EOLIST)
235
236
236
#
237
#
(-)include/apr_ldap_rebind.h (+80 lines)
Line 0 Link Here
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
/**
18
 * The APR LDAP rebind functions provide an implementation of
19
 * a rebind procedure that can be used to allow clients to chase referrals,
20
 * using the same credentials used to log in originally.
21
 *
22
 * Use of this implementation is optional.
23
 *
24
 * @file apu_ldap_rebind.h
25
 * @brief Apache LDAP library
26
 */
27
28
#ifndef APU_LDAP_REBIND_H
29
#define APU_LDAP_REBIND_H
30
31
/**
32
 * APR LDAP initialize rebind lock
33
 *
34
 * This function creates the lock for controlling access to the xref list..
35
 * @param pool Pool to use when creating the xref_lock.
36
 */
37
APU_DECLARE(apr_status_t) apr_ldap_rebind_init(apr_pool_t *pool);
38
39
40
/**
41
 * APR LDAP rebind_add function
42
 *
43
 * This function creates a cross reference entry for the specified ldap
44
 * connection. The rebind callback function will look up this ldap 
45
 * connection so it can retrieve the bindDN and bindPW for use in any 
46
 * binds while referrals are being chased.
47
 *
48
 * This function will add the callback to the LDAP handle passed in.
49
 *
50
 * A cleanup is registered within the pool provided to remove this
51
 * entry when the pool is removed. Alternatively apr_ldap_rebind_remove()
52
 * can be called to explicitly remove the entry at will.
53
 *
54
 * @param pool The pool to use
55
 * @param ld The LDAP connectionhandle
56
 * @param bindDN The bind DN to be used for any binds while chasing 
57
 *               referrals on this ldap connection.
58
 * @param bindPW The bind Password to be used for any binds while 
59
 *               chasing referrals on this ldap connection.
60
 */
61
APU_DECLARE(apr_status_t) apr_ldap_rebind_add(apr_pool_t *pool,
62
                                              LDAP *ld,
63
                                              const char *bindDN,
64
                                              const char *bindPW);
65
66
/**
67
 * APR LDAP rebind_remove function
68
 *
69
 * This function removes the rebind cross reference entry for the
70
 * specified ldap connection.
71
 *
72
 * If not explicitly removed, this function will be called automatically
73
 * when the pool is cleaned up.
74
 *
75
 * @param ld The LDAP connectionhandle
76
 */
77
APU_DECLARE(apr_status_t) apr_ldap_rebind_remove(LDAP *ld);
78
79
#endif /* APU_LDAP_REBIND_H */
80
(-)include/apr_ldap.h.in (+1 lines)
Lines 154-159 Link Here
154
#include "apr_ldap_url.h"
154
#include "apr_ldap_url.h"
155
#include "apr_ldap_init.h"
155
#include "apr_ldap_init.h"
156
#include "apr_ldap_option.h"
156
#include "apr_ldap_option.h"
157
#include "apr_ldap_rebind.h"
157
158
158
/** @} */
159
/** @} */
159
#endif /* APR_HAS_LDAP */
160
#endif /* APR_HAS_LDAP */

Return to bug 26538