~ubuntu-branches/ubuntu/feisty/apache2/feisty-updates

« back to all changes in this revision

Viewing changes to srclib/apr-util/ldap/apr_ldap_url.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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
/* Portions Copyright 1998-2002 The OpenLDAP Foundation
 
18
 * All rights reserved.
 
19
 * 
 
20
 * Redistribution and use in source and binary forms, with or without
 
21
 * modification, are permitted only as authorized by the OpenLDAP
 
22
 * Public License.  A copy of this license is available at
 
23
 * http://www.OpenLDAP.org/license.html or in file LICENSE in the
 
24
 * top-level directory of the distribution.
 
25
 * 
 
26
 * OpenLDAP is a registered trademark of the OpenLDAP Foundation.
 
27
 * 
 
28
 * Individual files and/or contributed packages may be copyright by
 
29
 * other parties and subject to additional restrictions.
 
30
 * 
 
31
 * This work is derived from the University of Michigan LDAP v3.3
 
32
 * distribution.  Information concerning this software is available
 
33
 * at: http://www.umich.edu/~dirsvcs/ldap/
 
34
 * 
 
35
 * This work also contains materials derived from public sources.
 
36
 * 
 
37
 * Additional information about OpenLDAP can be obtained at:
 
38
 *     http://www.openldap.org/
 
39
 */
 
40
 
 
41
/* 
 
42
 * Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
 
43
 * All rights reserved.
 
44
 * 
 
45
 * Redistribution and use in source and binary forms are permitted
 
46
 * provided that this notice is preserved and that due credit is given
 
47
 * to the University of Michigan at Ann Arbor. The name of the University
 
48
 * may not be used to endorse or promote products derived from this
 
49
 * software without specific prior written permission. This software
 
50
 * is provided ``as is'' without express or implied warranty.
 
51
 */
 
52
 
 
53
/*  apr_ldap_url.c -- LDAP URL (RFC 2255) related routines
 
54
 *
 
55
 *  Win32 and perhaps other non-OpenLDAP based ldap libraries may be
 
56
 *  missing ldap_url_* APIs.  We focus here on the one significant
 
57
 *  aspect, which is parsing.  We have [for the time being] omitted
 
58
 *  the ldap_url_search APIs.
 
59
 *
 
60
 *  LDAP URLs look like this:
 
61
 *    ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
 
62
 *
 
63
 *  where:
 
64
 *   attributes is a comma separated list
 
65
 *   scope is one of these three strings:  base one sub (default=base)
 
66
 *   filter is an string-represented filter as in RFC 2254
 
67
 *
 
68
 *  e.g.,  ldap://host:port/dc=com?o,cn?base?o=openldap?extension
 
69
 *
 
70
 *  Tolerates URLs that look like: <ldapurl> and <URL:ldapurl>
 
71
 */
 
72
 
 
73
#include "apu.h"
 
74
#include "apr_pools.h"
 
75
#include "apr_general.h"
 
76
#include "apr_strings.h"
 
77
#include "apr_ldap.h"
 
78
 
 
79
#if APR_HAS_LDAP
 
80
 
 
81
#if APR_HAVE_STDLIB_H
 
82
#include <stdlib.h>
 
83
#endif
 
84
 
 
85
#ifndef LDAPS_PORT
 
86
#define LDAPS_PORT              636  /* ldaps:/// default LDAP over TLS port */
 
87
#endif
 
88
 
 
89
#define APR_LDAP_URL_PREFIX         "ldap://"
 
90
#define APR_LDAP_URL_PREFIX_LEN     (sizeof(APR_LDAP_URL_PREFIX)-1)
 
91
#define APR_LDAPS_URL_PREFIX        "ldaps://"
 
92
#define APR_LDAPS_URL_PREFIX_LEN    (sizeof(APR_LDAPS_URL_PREFIX)-1)
 
93
#define APR_LDAPI_URL_PREFIX        "ldapi://"
 
94
#define APR_LDAPI_URL_PREFIX_LEN    (sizeof(APR_LDAPI_URL_PREFIX)-1)
 
95
#define APR_LDAP_URL_URLCOLON       "URL:"
 
96
#define APR_LDAP_URL_URLCOLON_LEN   (sizeof(APR_LDAP_URL_URLCOLON)-1)
 
97
 
 
98
 
 
99
/* local functions */
 
100
static const char* skip_url_prefix(const char *url,
 
101
                                   int *enclosedp,
 
102
                                   const char **scheme);
 
103
 
 
104
static void apr_ldap_pvt_hex_unescape(char *s);
 
105
 
 
106
static int apr_ldap_pvt_unhex(int c);
 
107
 
 
108
static char **apr_ldap_str2charray(apr_pool_t *pool,
 
109
                                   const char *str,
 
110
                                   const char *brkstr);
 
111
 
 
112
 
 
113
/**
 
114
 * Is this URL an ldap url?
 
115
 *
 
116
 */
 
117
APU_DECLARE(int) apr_ldap_is_ldap_url(const char *url)
 
118
{
 
119
    int enclosed;
 
120
    const char * scheme;
 
121
 
 
122
    if( url == NULL ) {
 
123
        return 0;
 
124
    }
 
125
 
 
126
    if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
 
127
        return 0;
 
128
    }
 
129
 
 
130
    return 1;
 
131
}
 
132
 
 
133
/**
 
134
 * Is this URL a secure ldap url?
 
135
 *
 
136
 */
 
137
APU_DECLARE(int) apr_ldap_is_ldaps_url(const char *url)
 
138
{
 
139
    int enclosed;
 
140
    const char * scheme;
 
141
 
 
142
    if( url == NULL ) {
 
143
        return 0;
 
144
    }
 
145
 
 
146
    if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
 
147
        return 0;
 
148
    }
 
149
 
 
150
    return strcmp(scheme, "ldaps") == 0;
 
151
}
 
152
 
 
153
/**
 
154
 * Is this URL an ldap socket url?
 
155
 *
 
156
 */
 
157
APU_DECLARE(int) apr_ldap_is_ldapi_url(const char *url)
 
158
{
 
159
    int enclosed;
 
160
    const char * scheme;
 
161
 
 
162
    if( url == NULL ) {
 
163
        return 0;
 
164
    }
 
165
 
 
166
    if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
 
167
        return 0;
 
168
    }
 
169
 
 
170
    return strcmp(scheme, "ldapi") == 0;
 
171
}
 
172
 
 
173
 
 
174
static const char *skip_url_prefix(const char *url, int *enclosedp,
 
175
                                   const char **scheme)
 
176
{
 
177
    /*
 
178
     * return non-zero if this looks like a LDAP URL; zero if not
 
179
     * if non-zero returned, *urlp will be moved past "ldap://" part of URL
 
180
     */
 
181
    const char *p;
 
182
 
 
183
    if ( url == NULL ) {
 
184
        return( NULL );
 
185
    }
 
186
 
 
187
    p = url;
 
188
 
 
189
    /* skip leading '<' (if any) */
 
190
    if ( *p == '<' ) {
 
191
        *enclosedp = 1;
 
192
        ++p;
 
193
    } else {
 
194
        *enclosedp = 0;
 
195
    }
 
196
 
 
197
    /* skip leading "URL:" (if any) */
 
198
    if ( strncasecmp( p, APR_LDAP_URL_URLCOLON, APR_LDAP_URL_URLCOLON_LEN ) == 0 ) {
 
199
        p += APR_LDAP_URL_URLCOLON_LEN;
 
200
    }
 
201
 
 
202
    /* check for "ldap://" prefix */
 
203
    if ( strncasecmp( p, APR_LDAP_URL_PREFIX, APR_LDAP_URL_PREFIX_LEN ) == 0 ) {
 
204
        /* skip over "ldap://" prefix and return success */
 
205
        p += APR_LDAP_URL_PREFIX_LEN;
 
206
        *scheme = "ldap";
 
207
        return( p );
 
208
    }
 
209
 
 
210
    /* check for "ldaps://" prefix */
 
211
    if ( strncasecmp( p, APR_LDAPS_URL_PREFIX, APR_LDAPS_URL_PREFIX_LEN ) == 0 ) {
 
212
        /* skip over "ldaps://" prefix and return success */
 
213
        p += APR_LDAPS_URL_PREFIX_LEN;
 
214
        *scheme = "ldaps";
 
215
        return( p );
 
216
    }
 
217
 
 
218
    /* check for "ldapi://" prefix */
 
219
    if ( strncasecmp( p, APR_LDAPI_URL_PREFIX, APR_LDAPI_URL_PREFIX_LEN ) == 0 ) {
 
220
        /* skip over "ldapi://" prefix and return success */
 
221
        p += APR_LDAPI_URL_PREFIX_LEN;
 
222
        *scheme = "ldapi";
 
223
        return( p );
 
224
    }
 
225
 
 
226
    return( NULL );
 
227
}
 
228
 
 
229
 
 
230
static int str2scope(const char *p)
 
231
{
 
232
    if ( strcasecmp( p, "one" ) == 0 ) {
 
233
        return LDAP_SCOPE_ONELEVEL;
 
234
 
 
235
    } else if ( strcasecmp( p, "onetree" ) == 0 ) {
 
236
        return LDAP_SCOPE_ONELEVEL;
 
237
 
 
238
    } else if ( strcasecmp( p, "base" ) == 0 ) {
 
239
        return LDAP_SCOPE_BASE;
 
240
 
 
241
    } else if ( strcasecmp( p, "sub" ) == 0 ) {
 
242
        return LDAP_SCOPE_SUBTREE;
 
243
 
 
244
    } else if ( strcasecmp( p, "subtree" ) == 0 ) {
 
245
        return LDAP_SCOPE_SUBTREE;
 
246
    }
 
247
 
 
248
    return( -1 );
 
249
}
 
250
 
 
251
 
 
252
/**
 
253
 * Parse the URL provided into an apr_ldap_url_desc_t object.
 
254
 *
 
255
 * APR_SUCCESS is returned on success, APR_EGENERAL on failure.
 
256
 * The LDAP result code and reason string is returned in the
 
257
 * apr_ldap_err_t structure.
 
258
 */
 
259
APU_DECLARE(int) apr_ldap_url_parse_ext(apr_pool_t *pool,
 
260
                                        const char *url_in,
 
261
                                        apr_ldap_url_desc_t **ludpp,
 
262
                                        apr_ldap_err_t **result_err)
 
263
{
 
264
    apr_ldap_url_desc_t *ludp;
 
265
    char        *p, *q, *r;
 
266
    int         i, enclosed;
 
267
    const char  *scheme = NULL;
 
268
    const char  *url_tmp;
 
269
    char        *url;
 
270
 
 
271
    apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
 
272
    *result_err = result;
 
273
 
 
274
    /* sanity check our parameters */
 
275
    if( url_in == NULL || ludpp == NULL ) {
 
276
        result->reason = "Either the LDAP URL, or the URL structure was NULL. Oops.";
 
277
        result->rc = APR_LDAP_URL_ERR_PARAM;
 
278
        return APR_EGENERAL;
 
279
    }
 
280
 
 
281
    *ludpp = NULL;  /* pessimistic */
 
282
 
 
283
    url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
 
284
    if ( url_tmp == NULL ) {
 
285
        result->reason = "The scheme was not recognised as a valid LDAP URL scheme.";
 
286
        result->rc = APR_LDAP_URL_ERR_BADSCHEME;
 
287
        return APR_EGENERAL;
 
288
    }
 
289
 
 
290
    /* make working copy of the remainder of the URL */
 
291
    url = (char *)apr_pstrdup(pool, url_tmp);
 
292
    if ( url == NULL ) {
 
293
        result->reason = "Out of memory parsing LDAP URL.";
 
294
        result->rc = APR_LDAP_URL_ERR_MEM;
 
295
        return APR_EGENERAL;
 
296
    }
 
297
 
 
298
    if ( enclosed ) {
 
299
        p = &url[strlen(url)-1];
 
300
 
 
301
        if( *p != '>' ) {
 
302
            result->reason = "Bad enclosure error while parsing LDAP URL.";
 
303
            result->rc = APR_LDAP_URL_ERR_BADENCLOSURE;
 
304
            return APR_EGENERAL;
 
305
        }
 
306
 
 
307
        *p = '\0';
 
308
    }
 
309
 
 
310
    /* allocate return struct */
 
311
    ludp = (apr_ldap_url_desc_t *)apr_pcalloc(pool, sizeof(apr_ldap_url_desc_t));
 
312
    if ( ludp == NULL ) {
 
313
        result->reason = "Out of memory parsing LDAP URL.";
 
314
        result->rc = APR_LDAP_URL_ERR_MEM;
 
315
        return APR_EGENERAL;
 
316
    }
 
317
 
 
318
    ludp->lud_next = NULL;
 
319
    ludp->lud_host = NULL;
 
320
    ludp->lud_port = LDAP_PORT;
 
321
    ludp->lud_dn = NULL;
 
322
    ludp->lud_attrs = NULL;
 
323
    ludp->lud_filter = NULL;
 
324
    ludp->lud_scope = -1;
 
325
    ludp->lud_filter = NULL;
 
326
    ludp->lud_exts = NULL;
 
327
 
 
328
    ludp->lud_scheme = (char *)apr_pstrdup(pool, scheme);
 
329
    if ( ludp->lud_scheme == NULL ) {
 
330
        result->reason = "Out of memory parsing LDAP URL.";
 
331
        result->rc = APR_LDAP_URL_ERR_MEM;
 
332
        return APR_EGENERAL;
 
333
    }
 
334
 
 
335
    if( strcasecmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
 
336
        ludp->lud_port = LDAPS_PORT;
 
337
    }
 
338
 
 
339
    /* scan forward for '/' that marks end of hostport and begin. of dn */
 
340
    p = strchr( url, '/' );
 
341
 
 
342
    if( p != NULL ) {
 
343
        /* terminate hostport; point to start of dn */
 
344
        *p++ = '\0';
 
345
    }
 
346
 
 
347
    /* IPv6 syntax with [ip address]:port */
 
348
    if ( *url == '[' ) {
 
349
        r = strchr( url, ']' );
 
350
        if ( r == NULL ) {
 
351
            result->reason = "Bad LDAP URL while parsing IPV6 syntax.";
 
352
            result->rc = APR_LDAP_URL_ERR_BADURL;
 
353
            return APR_EGENERAL;
 
354
        }
 
355
        *r++ = '\0';
 
356
        q = strrchr( r, ':' );
 
357
    } else {
 
358
        q = strrchr( url, ':' );
 
359
    }
 
360
 
 
361
    if ( q != NULL ) {
 
362
        apr_ldap_pvt_hex_unescape( ++q );
 
363
 
 
364
        if( *q == '\0' ) {
 
365
            result->reason = "Bad LDAP URL while parsing.";
 
366
            result->rc = APR_LDAP_URL_ERR_BADURL;
 
367
            return APR_EGENERAL;
 
368
        }
 
369
 
 
370
        ludp->lud_port = atoi( q );
 
371
    }
 
372
 
 
373
    apr_ldap_pvt_hex_unescape( url );
 
374
 
 
375
    /* If [ip address]:port syntax, url is [ip and we skip the [ */
 
376
    ludp->lud_host = (char *)apr_pstrdup(pool, url + ( *url == '[' ));
 
377
    if( ludp->lud_host == NULL ) {
 
378
        result->reason = "Out of memory parsing LDAP URL.";
 
379
        result->rc = APR_LDAP_URL_ERR_MEM;
 
380
        return APR_EGENERAL;
 
381
    }
 
382
 
 
383
    /*
 
384
     * Kludge.  ldap://111.222.333.444:389??cn=abc,o=company
 
385
     *
 
386
     * On early Novell releases, search references/referrals were returned
 
387
     * in this format, i.e., the dn was kind of in the scope position,
 
388
     * but the required slash is missing. The whole thing is illegal syntax,
 
389
     * but we need to account for it. Fortunately it can't be confused with
 
390
     * anything real.
 
391
     */
 
392
    if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
 
393
        q++;
 
394
        /* ? immediately followed by question */
 
395
        if( *q == '?') {
 
396
            q++;
 
397
            if( *q != '\0' ) {
 
398
                /* parse dn part */
 
399
                apr_ldap_pvt_hex_unescape( q );
 
400
                ludp->lud_dn = (char *)apr_pstrdup(pool, q);
 
401
            } else {
 
402
                ludp->lud_dn = (char *)apr_pstrdup(pool, "");
 
403
            }
 
404
 
 
405
            if( ludp->lud_dn == NULL ) {
 
406
                result->reason = "Out of memory parsing LDAP URL.";
 
407
                result->rc = APR_LDAP_URL_ERR_MEM;
 
408
                return APR_EGENERAL;
 
409
            }
 
410
        }
 
411
    }
 
412
 
 
413
    if( p == NULL ) {
 
414
        *ludpp = ludp;
 
415
        return APR_SUCCESS;
 
416
    }
 
417
 
 
418
    /* scan forward for '?' that may marks end of dn */
 
419
    q = strchr( p, '?' );
 
420
 
 
421
    if( q != NULL ) {
 
422
        /* terminate dn part */
 
423
        *q++ = '\0';
 
424
    }
 
425
 
 
426
    if( *p != '\0' ) {
 
427
        /* parse dn part */
 
428
        apr_ldap_pvt_hex_unescape( p );
 
429
        ludp->lud_dn = (char *)apr_pstrdup(pool, p);
 
430
    } else {
 
431
        ludp->lud_dn = (char *)apr_pstrdup(pool, "");
 
432
    }
 
433
 
 
434
    if( ludp->lud_dn == NULL ) {
 
435
        result->reason = "Out of memory parsing LDAP URL.";
 
436
        result->rc = APR_LDAP_URL_ERR_MEM;
 
437
        return APR_EGENERAL;
 
438
    }
 
439
 
 
440
    if( q == NULL ) {
 
441
        /* no more */
 
442
        *ludpp = ludp;
 
443
        return APR_SUCCESS;
 
444
    }
 
445
 
 
446
    /* scan forward for '?' that may marks end of attributes */
 
447
    p = q;
 
448
    q = strchr( p, '?' );
 
449
 
 
450
    if( q != NULL ) {
 
451
        /* terminate attributes part */
 
452
        *q++ = '\0';
 
453
    }
 
454
 
 
455
    if( *p != '\0' ) {
 
456
        /* parse attributes */
 
457
        apr_ldap_pvt_hex_unescape( p );
 
458
        ludp->lud_attrs = apr_ldap_str2charray(pool, p, ",");
 
459
 
 
460
        if( ludp->lud_attrs == NULL ) {
 
461
            result->reason = "Bad attributes encountered while parsing LDAP URL.";
 
462
            result->rc = APR_LDAP_URL_ERR_BADATTRS;
 
463
            return APR_EGENERAL;
 
464
        }
 
465
    }
 
466
 
 
467
    if ( q == NULL ) {
 
468
        /* no more */
 
469
        *ludpp = ludp;
 
470
        return APR_SUCCESS;
 
471
    }
 
472
 
 
473
    /* scan forward for '?' that may marks end of scope */
 
474
    p = q;
 
475
    q = strchr( p, '?' );
 
476
 
 
477
    if( q != NULL ) {
 
478
        /* terminate the scope part */
 
479
        *q++ = '\0';
 
480
    }
 
481
 
 
482
    if( *p != '\0' ) {
 
483
        /* parse the scope */
 
484
        apr_ldap_pvt_hex_unescape( p );
 
485
        ludp->lud_scope = str2scope( p );
 
486
 
 
487
        if( ludp->lud_scope == -1 ) {
 
488
            result->reason = "Bad scope encountered while parsing LDAP URL.";
 
489
            result->rc = APR_LDAP_URL_ERR_BADSCOPE;
 
490
            return APR_EGENERAL;
 
491
        }
 
492
    }
 
493
 
 
494
    if ( q == NULL ) {
 
495
        /* no more */
 
496
        *ludpp = ludp;
 
497
        return APR_SUCCESS;
 
498
    }
 
499
 
 
500
    /* scan forward for '?' that may marks end of filter */
 
501
    p = q;
 
502
    q = strchr( p, '?' );
 
503
 
 
504
    if( q != NULL ) {
 
505
        /* terminate the filter part */
 
506
        *q++ = '\0';
 
507
    }
 
508
 
 
509
    if( *p != '\0' ) {
 
510
        /* parse the filter */
 
511
        apr_ldap_pvt_hex_unescape( p );
 
512
 
 
513
        if( ! *p ) {
 
514
            /* missing filter */
 
515
            result->reason = "Bad filter encountered while parsing LDAP URL.";
 
516
            result->rc = APR_LDAP_URL_ERR_BADFILTER;
 
517
            return APR_EGENERAL;
 
518
        }
 
519
 
 
520
        ludp->lud_filter = (char *)apr_pstrdup(pool, p);
 
521
        if( ludp->lud_filter == NULL ) {
 
522
            result->reason = "Out of memory parsing LDAP URL.";
 
523
            result->rc = APR_LDAP_URL_ERR_MEM;
 
524
            return APR_EGENERAL;
 
525
        }
 
526
    }
 
527
 
 
528
    if ( q == NULL ) {
 
529
        /* no more */
 
530
        *ludpp = ludp;
 
531
        return APR_SUCCESS;
 
532
    }
 
533
 
 
534
    /* scan forward for '?' that may marks end of extensions */
 
535
    p = q;
 
536
    q = strchr( p, '?' );
 
537
 
 
538
    if( q != NULL ) {
 
539
        /* extra '?' */
 
540
        result->reason = "Bad URL encountered while parsing LDAP URL.";
 
541
        result->rc = APR_LDAP_URL_ERR_BADURL;
 
542
        return APR_EGENERAL;
 
543
    }
 
544
 
 
545
    /* parse the extensions */
 
546
    ludp->lud_exts = apr_ldap_str2charray(pool, p, ",");
 
547
    if( ludp->lud_exts == NULL ) {
 
548
        result->reason = "Bad extensions encountered while parsing LDAP URL.";
 
549
        result->rc = APR_LDAP_URL_ERR_BADEXTS;
 
550
        return APR_EGENERAL;
 
551
    }
 
552
 
 
553
    for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
 
554
        apr_ldap_pvt_hex_unescape( ludp->lud_exts[i] );
 
555
 
 
556
        if( *ludp->lud_exts[i] == '!' ) {
 
557
            /* count the number of critical extensions */
 
558
            ludp->lud_crit_exts++;
 
559
        }
 
560
    }
 
561
 
 
562
    if( i == 0 ) {
 
563
        /* must have 1 or more */
 
564
        result->reason = "Bad extensions encountered while parsing LDAP URL.";
 
565
        result->rc = APR_LDAP_URL_ERR_BADEXTS;
 
566
        return APR_EGENERAL;
 
567
    }
 
568
 
 
569
    /* no more */
 
570
    *ludpp = ludp;
 
571
    return APR_SUCCESS;
 
572
}
 
573
 
 
574
 
 
575
/**
 
576
 * Parse the URL provided into an apr_ldap_url_desc_t object.
 
577
 *
 
578
 * APR_SUCCESS is returned on success, APR_EGENERAL on failure.
 
579
 * The LDAP result code and reason string is returned in the
 
580
 * apr_ldap_err_t structure.
 
581
 */
 
582
APU_DECLARE(int) apr_ldap_url_parse(apr_pool_t *pool,
 
583
                                    const char *url_in,
 
584
                                    apr_ldap_url_desc_t **ludpp,
 
585
                                    apr_ldap_err_t **result_err)
 
586
{
 
587
 
 
588
    int rc = apr_ldap_url_parse_ext(pool, url_in, ludpp, result_err);
 
589
    if( rc != APR_SUCCESS ) {
 
590
        return rc;
 
591
    }
 
592
 
 
593
    if ((*ludpp)->lud_scope == -1) {
 
594
        (*ludpp)->lud_scope = LDAP_SCOPE_BASE;
 
595
    }
 
596
 
 
597
    if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
 
598
        (*ludpp)->lud_host = NULL;
 
599
    }
 
600
 
 
601
    return rc;
 
602
 
 
603
}
 
604
 
 
605
 
 
606
static void apr_ldap_pvt_hex_unescape(char *s)
 
607
{
 
608
    /*
 
609
     * Remove URL hex escapes from s... done in place.  The basic concept for
 
610
     * this routine is borrowed from the WWW library HTUnEscape() routine.
 
611
     */
 
612
    char    *p;
 
613
 
 
614
    for ( p = s; *s != '\0'; ++s ) {
 
615
        if ( *s == '%' ) {
 
616
            if ( *++s == '\0' ) {
 
617
                break;
 
618
            }
 
619
            *p = apr_ldap_pvt_unhex( *s ) << 4;
 
620
            if ( *++s == '\0' ) {
 
621
                break;
 
622
            }
 
623
            *p++ += apr_ldap_pvt_unhex( *s );
 
624
        } else {
 
625
            *p++ = *s;
 
626
        }
 
627
    }
 
628
 
 
629
    *p = '\0';
 
630
}
 
631
 
 
632
 
 
633
static int apr_ldap_pvt_unhex(int c)
 
634
{
 
635
    return( c >= '0' && c <= '9' ? c - '0'
 
636
        : c >= 'A' && c <= 'F' ? c - 'A' + 10
 
637
        : c - 'a' + 10 );
 
638
}
 
639
 
 
640
 
 
641
/**
 
642
 * Convert a string to a character array
 
643
 */
 
644
static char **apr_ldap_str2charray(apr_pool_t *pool,
 
645
                                   const char *str_in,
 
646
                                   const char *brkstr)
 
647
{
 
648
    char    **res;
 
649
    char    *str, *s;
 
650
    char    *lasts;
 
651
    int i;
 
652
 
 
653
    /* protect the input string from strtok */
 
654
    str = (char *)apr_pstrdup(pool, str_in);
 
655
    if( str == NULL ) {
 
656
        return NULL;
 
657
    }
 
658
 
 
659
    i = 1;
 
660
    for ( s = str; *s; s++ ) {
 
661
        /* Warning: this strchr was previously ldap_utf8_strchr(), check
 
662
         * whether this particular code has any charset issues.
 
663
         */
 
664
        if ( strchr( brkstr, *s ) != NULL ) {
 
665
            i++;
 
666
        }
 
667
    }
 
668
 
 
669
    res = (char **) apr_pcalloc(pool, (i + 1) * sizeof(char *));
 
670
    if( res == NULL ) {
 
671
        return NULL;
 
672
    }
 
673
 
 
674
    i = 0;
 
675
 
 
676
    for ( s = (char *)apr_strtok( str, brkstr, &lasts );
 
677
          s != NULL;
 
678
          s = (char *)apr_strtok( NULL, brkstr, &lasts ) ) {
 
679
 
 
680
        res[i] = (char *)apr_pstrdup(pool, s);
 
681
        if(res[i] == NULL) {
 
682
            return NULL;
 
683
        }
 
684
 
 
685
        i++;
 
686
    }
 
687
 
 
688
    res[i] = NULL;
 
689
 
 
690
    return( res );
 
691
 
 
692
}
 
693
 
 
694
#endif /* APR_HAS_LDAP */