~ubuntu-branches/ubuntu/trusty/apr-util/trusty

« back to all changes in this revision

Viewing changes to ldap/apr_ldap_rebind.c

  • Committer: Bazaar Package Importer
  • Author(s): Ryan Niebur
  • Date: 2009-03-26 22:25:48 UTC
  • mto: (4.1.1 squeeze) (20.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20090326222548-v103269kb84vo0ub
Tags: upstream-1.3.4+dfsg
ImportĀ upstreamĀ versionĀ 1.3.4+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
/* APR utility routine used to create the xref_lock. */
 
68
APU_DECLARE_LDAP(apr_status_t) apr_ldap_rebind_init(apr_pool_t *pool)
 
69
{
 
70
    apr_status_t retcode = APR_SUCCESS;
 
71
 
 
72
#ifdef NETWARE
 
73
    get_apd
 
74
#endif
 
75
 
 
76
#if APR_HAS_THREADS
 
77
    if (apr_ldap_xref_lock == NULL) {
 
78
        retcode = apr_thread_mutex_create(&apr_ldap_xref_lock, APR_THREAD_MUTEX_DEFAULT, pool);
 
79
    }
 
80
#endif
 
81
 
 
82
    return(retcode);
 
83
}
 
84
 
 
85
 
 
86
APU_DECLARE_LDAP(apr_status_t) apr_ldap_rebind_add(apr_pool_t *pool,
 
87
                                                   LDAP *ld, 
 
88
                                                   const char *bindDN, 
 
89
                                                   const char *bindPW)
 
90
{
 
91
    apr_status_t retcode = APR_SUCCESS;
 
92
    apr_ldap_rebind_entry_t *new_xref;
 
93
 
 
94
#ifdef NETWARE
 
95
    get_apd
 
96
#endif
 
97
 
 
98
    new_xref = (apr_ldap_rebind_entry_t *)apr_pcalloc(pool, sizeof(apr_ldap_rebind_entry_t));
 
99
    if (new_xref) {
 
100
        new_xref->pool = pool;
 
101
        new_xref->index = ld;
 
102
        if (bindDN) {
 
103
            new_xref->bindDN = apr_pstrdup(pool, bindDN);
 
104
        }
 
105
        if (bindPW) {
 
106
            new_xref->bindPW = apr_pstrdup(pool, bindPW);
 
107
        }
 
108
    
 
109
#if APR_HAS_THREADS
 
110
       apr_thread_mutex_lock(apr_ldap_xref_lock);
 
111
#endif
 
112
    
 
113
        new_xref->next = xref_head;
 
114
        xref_head = new_xref;
 
115
    
 
116
#if APR_HAS_THREADS
 
117
        apr_thread_mutex_unlock(apr_ldap_xref_lock);
 
118
#endif
 
119
    }
 
120
    else {
 
121
        return(APR_ENOMEM);
 
122
    }
 
123
 
 
124
    retcode = apr_ldap_rebind_set_callback(ld);
 
125
    if (APR_SUCCESS != retcode) {
 
126
        apr_ldap_rebind_remove(ld);
 
127
        return retcode;
 
128
    }
 
129
 
 
130
    apr_pool_cleanup_register(pool, ld,
 
131
                              apr_ldap_rebind_remove_helper,
 
132
                              apr_pool_cleanup_null);
 
133
 
 
134
    return(APR_SUCCESS);
 
135
}
 
136
 
 
137
 
 
138
APU_DECLARE_LDAP(apr_status_t) apr_ldap_rebind_remove(LDAP *ld)
 
139
{
 
140
    apr_ldap_rebind_entry_t *tmp_xref, *prev = NULL;
 
141
 
 
142
#ifdef NETWARE
 
143
    get_apd
 
144
#endif
 
145
 
 
146
#if APR_HAS_THREADS
 
147
    apr_thread_mutex_lock(apr_ldap_xref_lock);
 
148
#endif
 
149
    tmp_xref = xref_head;
 
150
 
 
151
    while ((tmp_xref) && (tmp_xref->index != ld)) {
 
152
        prev = tmp_xref;
 
153
        tmp_xref = tmp_xref->next;
 
154
    }
 
155
 
 
156
    if (tmp_xref) {
 
157
        if (tmp_xref == xref_head) {
 
158
            xref_head = xref_head->next;
 
159
        }
 
160
        else {
 
161
            prev->next = tmp_xref->next;
 
162
        }
 
163
 
 
164
        /* tmp_xref and its contents were pool allocated so they don't need to be freed here. */
 
165
 
 
166
        /* remove the cleanup, just in case this was done manually */
 
167
        apr_pool_cleanup_kill(tmp_xref->pool, tmp_xref->index,
 
168
                              apr_ldap_rebind_remove_helper);
 
169
    }
 
170
 
 
171
#if APR_HAS_THREADS
 
172
    apr_thread_mutex_unlock(apr_ldap_xref_lock);
 
173
#endif
 
174
    return APR_SUCCESS;
 
175
}
 
176
 
 
177
 
 
178
static apr_status_t apr_ldap_rebind_remove_helper(void *data)
 
179
{
 
180
    LDAP *ld = (LDAP *)data;
 
181
    apr_ldap_rebind_remove(ld);
 
182
    return APR_SUCCESS;
 
183
}
 
184
 
 
185
#if APR_HAS_TIVOLI_LDAPSDK || APR_HAS_OPENLDAP_LDAPSDK || APR_HAS_NOVELL_LDAPSDK
 
186
static apr_ldap_rebind_entry_t *apr_ldap_rebind_lookup(LDAP *ld)
 
187
{
 
188
    apr_ldap_rebind_entry_t *tmp_xref, *match = NULL;
 
189
 
 
190
#ifdef NETWARE
 
191
    get_apd
 
192
#endif
 
193
 
 
194
#if APR_HAS_THREADS
 
195
    apr_thread_mutex_lock(apr_ldap_xref_lock);
 
196
#endif
 
197
    tmp_xref = xref_head;
 
198
 
 
199
    while (tmp_xref) {
 
200
        if (tmp_xref->index == ld) {
 
201
            match = tmp_xref;
 
202
            tmp_xref = NULL;
 
203
        }
 
204
        else {
 
205
            tmp_xref = tmp_xref->next;
 
206
        }
 
207
    }
 
208
 
 
209
#if APR_HAS_THREADS
 
210
    apr_thread_mutex_unlock(apr_ldap_xref_lock);
 
211
#endif
 
212
 
 
213
    return (match);
 
214
}
 
215
#endif
 
216
 
 
217
#if APR_HAS_TIVOLI_LDAPSDK
 
218
 
 
219
/* LDAP_rebindproc() Tivoli LDAP style
 
220
 *     Rebind callback function. Called when chasing referrals. See API docs.
 
221
 * ON ENTRY:
 
222
 *     ld       Pointer to an LDAP control structure. (input only)
 
223
 *     binddnp  Pointer to an Application DName used for binding (in *or* out)
 
224
 *     passwdp  Pointer to the password associated with the DName (in *or* out)
 
225
 *     methodp  Pointer to the Auth method (output only)
 
226
 *     freeit   Flag to indicate if this is a lookup or a free request (input only)
 
227
 */
 
228
static int LDAP_rebindproc(LDAP *ld, char **binddnp, char **passwdp, int *methodp, int freeit)
 
229
{
 
230
    if (!freeit) {
 
231
        apr_ldap_rebind_entry_t *my_conn;
 
232
 
 
233
        *methodp = LDAP_AUTH_SIMPLE;
 
234
        my_conn = apr_ldap_rebind_lookup(ld);
 
235
 
 
236
        if ((my_conn) && (my_conn->bindDN != NULL)) {
 
237
            *binddnp = strdup(my_conn->bindDN);
 
238
            *passwdp = strdup(my_conn->bindPW);
 
239
        } else {
 
240
            *binddnp = NULL;
 
241
            *passwdp = NULL;
 
242
        }
 
243
    } else {
 
244
        if (*binddnp) {
 
245
            free(*binddnp);
 
246
        }
 
247
        if (*passwdp) {
 
248
            free(*passwdp);
 
249
        }
 
250
    }
 
251
 
 
252
    return LDAP_SUCCESS;
 
253
}
 
254
 
 
255
static int apr_ldap_rebind_set_callback(LDAP *ld)
 
256
{
 
257
    ldap_set_rebind_proc(ld, (LDAPRebindProc)LDAP_rebindproc);
 
258
    return APR_SUCCESS;
 
259
}
 
260
 
 
261
#elif APR_HAS_OPENLDAP_LDAPSDK
 
262
 
 
263
/* LDAP_rebindproc() openLDAP V3 style
 
264
 * ON ENTRY:
 
265
 *     ld       Pointer to an LDAP control structure. (input only)
 
266
 *     url      Unused in this routine
 
267
 *     request  Unused in this routine
 
268
 *     msgid    Unused in this routine
 
269
 *     params   Unused in this routine
 
270
 *
 
271
 *     or
 
272
 *
 
273
 *     ld       Pointer to an LDAP control structure. (input only)
 
274
 *     url      Unused in this routine
 
275
 *     request  Unused in this routine
 
276
 *     msgid    Unused in this routine
 
277
 */
 
278
#if defined(LDAP_SET_REBIND_PROC_THREE)
 
279
static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request,
 
280
                           ber_int_t msgid, void *params)
 
281
#else
 
282
static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request,
 
283
                           ber_int_t msgid)
 
284
#endif
 
285
{
 
286
    apr_ldap_rebind_entry_t *my_conn;
 
287
    const char *bindDN = NULL;
 
288
    const char *bindPW = NULL;
 
289
 
 
290
    my_conn = apr_ldap_rebind_lookup(ld);
 
291
 
 
292
    if ((my_conn) && (my_conn->bindDN != NULL)) {
 
293
        bindDN = my_conn->bindDN;
 
294
        bindPW = my_conn->bindPW;
 
295
    }
 
296
 
 
297
    return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
 
298
}
 
299
 
 
300
static int apr_ldap_rebind_set_callback(LDAP *ld)
 
301
{
 
302
#if defined(LDAP_SET_REBIND_PROC_THREE)
 
303
    ldap_set_rebind_proc(ld, LDAP_rebindproc, NULL);
 
304
#else
 
305
    ldap_set_rebind_proc(ld, LDAP_rebindproc);
 
306
#endif
 
307
    return APR_SUCCESS;
 
308
}
 
309
 
 
310
#elif APR_HAS_NOVELL_LDAPSDK
 
311
 
 
312
/* LDAP_rebindproc() openLDAP V3 style
 
313
 * ON ENTRY:
 
314
 *     ld       Pointer to an LDAP control structure. (input only)
 
315
 *     url      Unused in this routine
 
316
 *     request  Unused in this routine
 
317
 *     msgid    Unused in this routine
 
318
 */
 
319
static int LDAP_rebindproc(LDAP *ld, LDAP_CONST char *url, int request, ber_int_t msgid)
 
320
{
 
321
 
 
322
    apr_ldap_rebind_entry_t *my_conn;
 
323
    const char *bindDN = NULL;
 
324
    const char *bindPW = NULL;
 
325
 
 
326
    my_conn = apr_ldap_rebind_lookup(ld);
 
327
 
 
328
    if ((my_conn) && (my_conn->bindDN != NULL)) {
 
329
        bindDN = my_conn->bindDN;
 
330
        bindPW = my_conn->bindPW;
 
331
    }
 
332
 
 
333
    return (ldap_bind_s(ld, bindDN, bindPW, LDAP_AUTH_SIMPLE));
 
334
}
 
335
 
 
336
static int apr_ldap_rebind_set_callback(LDAP *ld)
 
337
{
 
338
    ldap_set_rebind_proc(ld, LDAP_rebindproc);
 
339
    return APR_SUCCESS;
 
340
}
 
341
 
 
342
#else         /* Implementation not recognised */
 
343
 
 
344
static int apr_ldap_rebind_set_callback(LDAP *ld)
 
345
{
 
346
    return APR_ENOTIMPL;
 
347
}
 
348
 
 
349
#endif
 
350
 
 
351
#endif       /* APR_HAS_LDAP */