1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251876Speter * contributor license agreements. See the NOTICE file distributed with 3251876Speter * this work for additional information regarding copyright ownership. 4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251876Speter * (the "License"); you may not use this file except in compliance with 6251876Speter * the License. You may obtain a copy of the License at 7251876Speter * 8251876Speter * http://www.apache.org/licenses/LICENSE-2.0 9251876Speter * 10251876Speter * Unless required by applicable law or agreed to in writing, software 11251876Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251876Speter * See the License for the specific language governing permissions and 14251876Speter * limitations under the License. 15251876Speter */ 16251876Speter 17251876Speter/* Portions Copyright 1998-2002 The OpenLDAP Foundation 18251876Speter * All rights reserved. 19251876Speter * 20251876Speter * Redistribution and use in source and binary forms, with or without 21251876Speter * modification, are permitted only as authorized by the OpenLDAP 22251876Speter * Public License. A copy of this license is available at 23251876Speter * http://www.OpenLDAP.org/license.html or in file LICENSE in the 24251876Speter * top-level directory of the distribution. 25251876Speter * 26251876Speter * OpenLDAP is a registered trademark of the OpenLDAP Foundation. 27251876Speter * 28251876Speter * Individual files and/or contributed packages may be copyright by 29251876Speter * other parties and subject to additional restrictions. 30251876Speter * 31251876Speter * This work is derived from the University of Michigan LDAP v3.3 32251876Speter * distribution. Information concerning this software is available 33251876Speter * at: http://www.umich.edu/~dirsvcs/ldap/ 34251876Speter * 35251876Speter * This work also contains materials derived from public sources. 36251876Speter * 37251876Speter * Additional information about OpenLDAP can be obtained at: 38251876Speter * http://www.openldap.org/ 39251876Speter */ 40251876Speter 41251876Speter/* 42251876Speter * Portions Copyright (c) 1992-1996 Regents of the University of Michigan. 43251876Speter * All rights reserved. 44251876Speter * 45251876Speter * Redistribution and use in source and binary forms are permitted 46251876Speter * provided that this notice is preserved and that due credit is given 47251876Speter * to the University of Michigan at Ann Arbor. The name of the University 48251876Speter * may not be used to endorse or promote products derived from this 49251876Speter * software without specific prior written permission. This software 50251876Speter * is provided ``as is'' without express or implied warranty. 51251876Speter */ 52251876Speter 53251876Speter/* apr_ldap_url.c -- LDAP URL (RFC 2255) related routines 54251876Speter * 55251876Speter * Win32 and perhaps other non-OpenLDAP based ldap libraries may be 56251876Speter * missing ldap_url_* APIs. We focus here on the one significant 57251876Speter * aspect, which is parsing. We have [for the time being] omitted 58251876Speter * the ldap_url_search APIs. 59251876Speter * 60251876Speter * LDAP URLs look like this: 61251876Speter * ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]] 62251876Speter * 63251876Speter * where: 64251876Speter * attributes is a comma separated list 65251876Speter * scope is one of these three strings: base one sub (default=base) 66251876Speter * filter is an string-represented filter as in RFC 2254 67251876Speter * 68251876Speter * e.g., ldap://host:port/dc=com?o,cn?base?o=openldap?extension 69251876Speter * 70251876Speter * Tolerates URLs that look like: <ldapurl> and <URL:ldapurl> 71251876Speter */ 72251876Speter 73251876Speter#include "apu.h" 74251876Speter#include "apr_pools.h" 75251876Speter#include "apr_general.h" 76251876Speter#include "apr_strings.h" 77251876Speter#include "apr_ldap.h" 78251876Speter 79251876Speter#if APR_HAS_LDAP 80251876Speter 81251876Speter#if APR_HAVE_STDLIB_H 82251876Speter#include <stdlib.h> 83251876Speter#endif 84251876Speter 85251876Speter#ifndef LDAPS_PORT 86251876Speter#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */ 87251876Speter#endif 88251876Speter 89251876Speter#define APR_LDAP_URL_PREFIX "ldap://" 90251876Speter#define APR_LDAP_URL_PREFIX_LEN (sizeof(APR_LDAP_URL_PREFIX)-1) 91251876Speter#define APR_LDAPS_URL_PREFIX "ldaps://" 92251876Speter#define APR_LDAPS_URL_PREFIX_LEN (sizeof(APR_LDAPS_URL_PREFIX)-1) 93251876Speter#define APR_LDAPI_URL_PREFIX "ldapi://" 94251876Speter#define APR_LDAPI_URL_PREFIX_LEN (sizeof(APR_LDAPI_URL_PREFIX)-1) 95251876Speter#define APR_LDAP_URL_URLCOLON "URL:" 96251876Speter#define APR_LDAP_URL_URLCOLON_LEN (sizeof(APR_LDAP_URL_URLCOLON)-1) 97251876Speter 98251876Speter 99251876Speter/* local functions */ 100251876Speterstatic const char* skip_url_prefix(const char *url, 101251876Speter int *enclosedp, 102251876Speter const char **scheme); 103251876Speter 104251876Speterstatic void apr_ldap_pvt_hex_unescape(char *s); 105251876Speter 106251876Speterstatic int apr_ldap_pvt_unhex(int c); 107251876Speter 108251876Speterstatic char **apr_ldap_str2charray(apr_pool_t *pool, 109251876Speter const char *str, 110251876Speter const char *brkstr); 111251876Speter 112251876Speter 113251876Speter/** 114251876Speter * Is this URL an ldap url? 115251876Speter * 116251876Speter */ 117251876SpeterAPU_DECLARE(int) apr_ldap_is_ldap_url(const char *url) 118251876Speter{ 119251876Speter int enclosed; 120251876Speter const char * scheme; 121251876Speter 122251876Speter if( url == NULL ) { 123251876Speter return 0; 124251876Speter } 125251876Speter 126251876Speter if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { 127251876Speter return 0; 128251876Speter } 129251876Speter 130251876Speter return 1; 131251876Speter} 132251876Speter 133251876Speter/** 134251876Speter * Is this URL a secure ldap url? 135251876Speter * 136251876Speter */ 137251876SpeterAPU_DECLARE(int) apr_ldap_is_ldaps_url(const char *url) 138251876Speter{ 139251876Speter int enclosed; 140251876Speter const char * scheme; 141251876Speter 142251876Speter if( url == NULL ) { 143251876Speter return 0; 144251876Speter } 145251876Speter 146251876Speter if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { 147251876Speter return 0; 148251876Speter } 149251876Speter 150251876Speter return strcmp(scheme, "ldaps") == 0; 151251876Speter} 152251876Speter 153251876Speter/** 154251876Speter * Is this URL an ldap socket url? 155251876Speter * 156251876Speter */ 157251876SpeterAPU_DECLARE(int) apr_ldap_is_ldapi_url(const char *url) 158251876Speter{ 159251876Speter int enclosed; 160251876Speter const char * scheme; 161251876Speter 162251876Speter if( url == NULL ) { 163251876Speter return 0; 164251876Speter } 165251876Speter 166251876Speter if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { 167251876Speter return 0; 168251876Speter } 169251876Speter 170251876Speter return strcmp(scheme, "ldapi") == 0; 171251876Speter} 172251876Speter 173251876Speter 174251876Speterstatic const char *skip_url_prefix(const char *url, int *enclosedp, 175251876Speter const char **scheme) 176251876Speter{ 177251876Speter /* 178251876Speter * return non-zero if this looks like a LDAP URL; zero if not 179251876Speter * if non-zero returned, *urlp will be moved past "ldap://" part of URL 180251876Speter */ 181251876Speter const char *p; 182251876Speter 183251876Speter if ( url == NULL ) { 184251876Speter return( NULL ); 185251876Speter } 186251876Speter 187251876Speter p = url; 188251876Speter 189251876Speter /* skip leading '<' (if any) */ 190251876Speter if ( *p == '<' ) { 191251876Speter *enclosedp = 1; 192251876Speter ++p; 193251876Speter } else { 194251876Speter *enclosedp = 0; 195251876Speter } 196251876Speter 197251876Speter /* skip leading "URL:" (if any) */ 198251876Speter if ( strncasecmp( p, APR_LDAP_URL_URLCOLON, APR_LDAP_URL_URLCOLON_LEN ) == 0 ) { 199251876Speter p += APR_LDAP_URL_URLCOLON_LEN; 200251876Speter } 201251876Speter 202251876Speter /* check for "ldap://" prefix */ 203251876Speter if ( strncasecmp( p, APR_LDAP_URL_PREFIX, APR_LDAP_URL_PREFIX_LEN ) == 0 ) { 204251876Speter /* skip over "ldap://" prefix and return success */ 205251876Speter p += APR_LDAP_URL_PREFIX_LEN; 206251876Speter *scheme = "ldap"; 207251876Speter return( p ); 208251876Speter } 209251876Speter 210251876Speter /* check for "ldaps://" prefix */ 211251876Speter if ( strncasecmp( p, APR_LDAPS_URL_PREFIX, APR_LDAPS_URL_PREFIX_LEN ) == 0 ) { 212251876Speter /* skip over "ldaps://" prefix and return success */ 213251876Speter p += APR_LDAPS_URL_PREFIX_LEN; 214251876Speter *scheme = "ldaps"; 215251876Speter return( p ); 216251876Speter } 217251876Speter 218251876Speter /* check for "ldapi://" prefix */ 219251876Speter if ( strncasecmp( p, APR_LDAPI_URL_PREFIX, APR_LDAPI_URL_PREFIX_LEN ) == 0 ) { 220251876Speter /* skip over "ldapi://" prefix and return success */ 221251876Speter p += APR_LDAPI_URL_PREFIX_LEN; 222251876Speter *scheme = "ldapi"; 223251876Speter return( p ); 224251876Speter } 225251876Speter 226251876Speter return( NULL ); 227251876Speter} 228251876Speter 229251876Speter 230251876Speterstatic int str2scope(const char *p) 231251876Speter{ 232251876Speter if ( strcasecmp( p, "one" ) == 0 ) { 233251876Speter return LDAP_SCOPE_ONELEVEL; 234251876Speter 235251876Speter } else if ( strcasecmp( p, "onetree" ) == 0 ) { 236251876Speter return LDAP_SCOPE_ONELEVEL; 237251876Speter 238251876Speter } else if ( strcasecmp( p, "base" ) == 0 ) { 239251876Speter return LDAP_SCOPE_BASE; 240251876Speter 241251876Speter } else if ( strcasecmp( p, "sub" ) == 0 ) { 242251876Speter return LDAP_SCOPE_SUBTREE; 243251876Speter 244251876Speter } else if ( strcasecmp( p, "subtree" ) == 0 ) { 245251876Speter return LDAP_SCOPE_SUBTREE; 246251876Speter } 247251876Speter 248251876Speter return( -1 ); 249251876Speter} 250251876Speter 251251876Speter 252251876Speter/** 253251876Speter * Parse the URL provided into an apr_ldap_url_desc_t object. 254251876Speter * 255251876Speter * APR_SUCCESS is returned on success, APR_EGENERAL on failure. 256251876Speter * The LDAP result code and reason string is returned in the 257251876Speter * apr_ldap_err_t structure. 258251876Speter */ 259251876SpeterAPU_DECLARE(int) apr_ldap_url_parse_ext(apr_pool_t *pool, 260251876Speter const char *url_in, 261251876Speter apr_ldap_url_desc_t **ludpp, 262251876Speter apr_ldap_err_t **result_err) 263251876Speter{ 264251876Speter apr_ldap_url_desc_t *ludp; 265251876Speter char *p, *q, *r; 266251876Speter int i, enclosed; 267251876Speter const char *scheme = NULL; 268251876Speter const char *url_tmp; 269251876Speter char *url; 270251876Speter 271251876Speter apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t)); 272251876Speter *result_err = result; 273251876Speter 274251876Speter /* sanity check our parameters */ 275251876Speter if( url_in == NULL || ludpp == NULL ) { 276251876Speter result->reason = "Either the LDAP URL, or the URL structure was NULL. Oops."; 277251876Speter result->rc = APR_LDAP_URL_ERR_PARAM; 278251876Speter return APR_EGENERAL; 279251876Speter } 280251876Speter 281251876Speter *ludpp = NULL; /* pessimistic */ 282251876Speter 283251876Speter url_tmp = skip_url_prefix( url_in, &enclosed, &scheme ); 284251876Speter if ( url_tmp == NULL ) { 285251876Speter result->reason = "The scheme was not recognised as a valid LDAP URL scheme."; 286251876Speter result->rc = APR_LDAP_URL_ERR_BADSCHEME; 287251876Speter return APR_EGENERAL; 288251876Speter } 289251876Speter 290251876Speter /* make working copy of the remainder of the URL */ 291251876Speter url = (char *)apr_pstrdup(pool, url_tmp); 292251876Speter if ( url == NULL ) { 293251876Speter result->reason = "Out of memory parsing LDAP URL."; 294251876Speter result->rc = APR_LDAP_URL_ERR_MEM; 295251876Speter return APR_EGENERAL; 296251876Speter } 297251876Speter 298251876Speter if ( enclosed ) { 299251876Speter p = &url[strlen(url)-1]; 300251876Speter 301251876Speter if( *p != '>' ) { 302251876Speter result->reason = "Bad enclosure error while parsing LDAP URL."; 303251876Speter result->rc = APR_LDAP_URL_ERR_BADENCLOSURE; 304251876Speter return APR_EGENERAL; 305251876Speter } 306251876Speter 307251876Speter *p = '\0'; 308251876Speter } 309251876Speter 310251876Speter /* allocate return struct */ 311251876Speter ludp = (apr_ldap_url_desc_t *)apr_pcalloc(pool, sizeof(apr_ldap_url_desc_t)); 312251876Speter if ( ludp == NULL ) { 313251876Speter result->reason = "Out of memory parsing LDAP URL."; 314251876Speter result->rc = APR_LDAP_URL_ERR_MEM; 315251876Speter return APR_EGENERAL; 316251876Speter } 317251876Speter 318251876Speter ludp->lud_next = NULL; 319251876Speter ludp->lud_host = NULL; 320251876Speter ludp->lud_port = LDAP_PORT; 321251876Speter ludp->lud_dn = NULL; 322251876Speter ludp->lud_attrs = NULL; 323251876Speter ludp->lud_filter = NULL; 324251876Speter ludp->lud_scope = -1; 325251876Speter ludp->lud_filter = NULL; 326251876Speter ludp->lud_exts = NULL; 327251876Speter 328251876Speter ludp->lud_scheme = (char *)apr_pstrdup(pool, scheme); 329251876Speter if ( ludp->lud_scheme == NULL ) { 330251876Speter result->reason = "Out of memory parsing LDAP URL."; 331251876Speter result->rc = APR_LDAP_URL_ERR_MEM; 332251876Speter return APR_EGENERAL; 333251876Speter } 334251876Speter 335251876Speter if( strcasecmp( ludp->lud_scheme, "ldaps" ) == 0 ) { 336251876Speter ludp->lud_port = LDAPS_PORT; 337251876Speter } 338251876Speter 339251876Speter /* scan forward for '/' that marks end of hostport and begin. of dn */ 340251876Speter p = strchr( url, '/' ); 341251876Speter 342251876Speter if( p != NULL ) { 343251876Speter /* terminate hostport; point to start of dn */ 344251876Speter *p++ = '\0'; 345251876Speter } 346251876Speter 347251876Speter /* IPv6 syntax with [ip address]:port */ 348251876Speter if ( *url == '[' ) { 349251876Speter r = strchr( url, ']' ); 350251876Speter if ( r == NULL ) { 351251876Speter result->reason = "Bad LDAP URL while parsing IPV6 syntax."; 352251876Speter result->rc = APR_LDAP_URL_ERR_BADURL; 353251876Speter return APR_EGENERAL; 354251876Speter } 355251876Speter *r++ = '\0'; 356251876Speter q = strrchr( r, ':' ); 357251876Speter } else { 358251876Speter q = strrchr( url, ':' ); 359251876Speter } 360251876Speter 361251876Speter if ( q != NULL ) { 362251876Speter apr_ldap_pvt_hex_unescape( ++q ); 363251876Speter 364251876Speter if( *q == '\0' ) { 365251876Speter result->reason = "Bad LDAP URL while parsing."; 366251876Speter result->rc = APR_LDAP_URL_ERR_BADURL; 367251876Speter return APR_EGENERAL; 368251876Speter } 369251876Speter 370251876Speter ludp->lud_port = atoi( q ); 371251876Speter } 372251876Speter 373251876Speter apr_ldap_pvt_hex_unescape( url ); 374251876Speter 375251876Speter /* If [ip address]:port syntax, url is [ip and we skip the [ */ 376251876Speter ludp->lud_host = (char *)apr_pstrdup(pool, url + ( *url == '[' )); 377251876Speter if( ludp->lud_host == NULL ) { 378251876Speter result->reason = "Out of memory parsing LDAP URL."; 379251876Speter result->rc = APR_LDAP_URL_ERR_MEM; 380251876Speter return APR_EGENERAL; 381251876Speter } 382251876Speter 383251876Speter /* 384251876Speter * Kludge. ldap://111.222.333.444:389??cn=abc,o=company 385251876Speter * 386251876Speter * On early Novell releases, search references/referrals were returned 387251876Speter * in this format, i.e., the dn was kind of in the scope position, 388251876Speter * but the required slash is missing. The whole thing is illegal syntax, 389251876Speter * but we need to account for it. Fortunately it can't be confused with 390251876Speter * anything real. 391251876Speter */ 392251876Speter if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { 393251876Speter q++; 394251876Speter /* ? immediately followed by question */ 395251876Speter if( *q == '?') { 396251876Speter q++; 397251876Speter if( *q != '\0' ) { 398251876Speter /* parse dn part */ 399251876Speter apr_ldap_pvt_hex_unescape( q ); 400251876Speter ludp->lud_dn = (char *)apr_pstrdup(pool, q); 401251876Speter } else { 402251876Speter ludp->lud_dn = (char *)apr_pstrdup(pool, ""); 403251876Speter } 404251876Speter 405251876Speter if( ludp->lud_dn == NULL ) { 406251876Speter result->reason = "Out of memory parsing LDAP URL."; 407251876Speter result->rc = APR_LDAP_URL_ERR_MEM; 408251876Speter return APR_EGENERAL; 409251876Speter } 410251876Speter } 411251876Speter } 412251876Speter 413251876Speter if( p == NULL ) { 414251876Speter *ludpp = ludp; 415251876Speter return APR_SUCCESS; 416251876Speter } 417251876Speter 418251876Speter /* scan forward for '?' that may marks end of dn */ 419251876Speter q = strchr( p, '?' ); 420251876Speter 421251876Speter if( q != NULL ) { 422251876Speter /* terminate dn part */ 423251876Speter *q++ = '\0'; 424251876Speter } 425251876Speter 426251876Speter if( *p != '\0' ) { 427251876Speter /* parse dn part */ 428251876Speter apr_ldap_pvt_hex_unescape( p ); 429251876Speter ludp->lud_dn = (char *)apr_pstrdup(pool, p); 430251876Speter } else { 431251876Speter ludp->lud_dn = (char *)apr_pstrdup(pool, ""); 432251876Speter } 433251876Speter 434251876Speter if( ludp->lud_dn == NULL ) { 435251876Speter result->reason = "Out of memory parsing LDAP URL."; 436251876Speter result->rc = APR_LDAP_URL_ERR_MEM; 437251876Speter return APR_EGENERAL; 438251876Speter } 439251876Speter 440251876Speter if( q == NULL ) { 441251876Speter /* no more */ 442251876Speter *ludpp = ludp; 443251876Speter return APR_SUCCESS; 444251876Speter } 445251876Speter 446251876Speter /* scan forward for '?' that may marks end of attributes */ 447251876Speter p = q; 448251876Speter q = strchr( p, '?' ); 449251876Speter 450251876Speter if( q != NULL ) { 451251876Speter /* terminate attributes part */ 452251876Speter *q++ = '\0'; 453251876Speter } 454251876Speter 455251876Speter if( *p != '\0' ) { 456251876Speter /* parse attributes */ 457251876Speter apr_ldap_pvt_hex_unescape( p ); 458251876Speter ludp->lud_attrs = apr_ldap_str2charray(pool, p, ","); 459251876Speter 460251876Speter if( ludp->lud_attrs == NULL ) { 461251876Speter result->reason = "Bad attributes encountered while parsing LDAP URL."; 462251876Speter result->rc = APR_LDAP_URL_ERR_BADATTRS; 463251876Speter return APR_EGENERAL; 464251876Speter } 465251876Speter } 466251876Speter 467251876Speter if ( q == NULL ) { 468251876Speter /* no more */ 469251876Speter *ludpp = ludp; 470251876Speter return APR_SUCCESS; 471251876Speter } 472251876Speter 473251876Speter /* scan forward for '?' that may marks end of scope */ 474251876Speter p = q; 475251876Speter q = strchr( p, '?' ); 476251876Speter 477251876Speter if( q != NULL ) { 478251876Speter /* terminate the scope part */ 479251876Speter *q++ = '\0'; 480251876Speter } 481251876Speter 482251876Speter if( *p != '\0' ) { 483251876Speter /* parse the scope */ 484251876Speter apr_ldap_pvt_hex_unescape( p ); 485251876Speter ludp->lud_scope = str2scope( p ); 486251876Speter 487251876Speter if( ludp->lud_scope == -1 ) { 488251876Speter result->reason = "Bad scope encountered while parsing LDAP URL."; 489251876Speter result->rc = APR_LDAP_URL_ERR_BADSCOPE; 490251876Speter return APR_EGENERAL; 491251876Speter } 492251876Speter } 493251876Speter 494251876Speter if ( q == NULL ) { 495251876Speter /* no more */ 496251876Speter *ludpp = ludp; 497251876Speter return APR_SUCCESS; 498251876Speter } 499251876Speter 500251876Speter /* scan forward for '?' that may marks end of filter */ 501251876Speter p = q; 502251876Speter q = strchr( p, '?' ); 503251876Speter 504251876Speter if( q != NULL ) { 505251876Speter /* terminate the filter part */ 506251876Speter *q++ = '\0'; 507251876Speter } 508251876Speter 509251876Speter if( *p != '\0' ) { 510251876Speter /* parse the filter */ 511251876Speter apr_ldap_pvt_hex_unescape( p ); 512251876Speter 513251876Speter if( ! *p ) { 514251876Speter /* missing filter */ 515251876Speter result->reason = "Bad filter encountered while parsing LDAP URL."; 516251876Speter result->rc = APR_LDAP_URL_ERR_BADFILTER; 517251876Speter return APR_EGENERAL; 518251876Speter } 519251876Speter 520251876Speter ludp->lud_filter = (char *)apr_pstrdup(pool, p); 521251876Speter if( ludp->lud_filter == NULL ) { 522251876Speter result->reason = "Out of memory parsing LDAP URL."; 523251876Speter result->rc = APR_LDAP_URL_ERR_MEM; 524251876Speter return APR_EGENERAL; 525251876Speter } 526251876Speter } 527251876Speter 528251876Speter if ( q == NULL ) { 529251876Speter /* no more */ 530251876Speter *ludpp = ludp; 531251876Speter return APR_SUCCESS; 532251876Speter } 533251876Speter 534251876Speter /* scan forward for '?' that may marks end of extensions */ 535251876Speter p = q; 536251876Speter q = strchr( p, '?' ); 537251876Speter 538251876Speter if( q != NULL ) { 539251876Speter /* extra '?' */ 540251876Speter result->reason = "Bad URL encountered while parsing LDAP URL."; 541251876Speter result->rc = APR_LDAP_URL_ERR_BADURL; 542251876Speter return APR_EGENERAL; 543251876Speter } 544251876Speter 545251876Speter /* parse the extensions */ 546251876Speter ludp->lud_exts = apr_ldap_str2charray(pool, p, ","); 547251876Speter if( ludp->lud_exts == NULL ) { 548251876Speter result->reason = "Bad extensions encountered while parsing LDAP URL."; 549251876Speter result->rc = APR_LDAP_URL_ERR_BADEXTS; 550251876Speter return APR_EGENERAL; 551251876Speter } 552251876Speter 553251876Speter for( i=0; ludp->lud_exts[i] != NULL; i++ ) { 554251876Speter apr_ldap_pvt_hex_unescape( ludp->lud_exts[i] ); 555251876Speter 556251876Speter if( *ludp->lud_exts[i] == '!' ) { 557251876Speter /* count the number of critical extensions */ 558251876Speter ludp->lud_crit_exts++; 559251876Speter } 560251876Speter } 561251876Speter 562251876Speter if( i == 0 ) { 563251876Speter /* must have 1 or more */ 564251876Speter result->reason = "Bad extensions encountered while parsing LDAP URL."; 565251876Speter result->rc = APR_LDAP_URL_ERR_BADEXTS; 566251876Speter return APR_EGENERAL; 567251876Speter } 568251876Speter 569251876Speter /* no more */ 570251876Speter *ludpp = ludp; 571251876Speter return APR_SUCCESS; 572251876Speter} 573251876Speter 574251876Speter 575251876Speter/** 576251876Speter * Parse the URL provided into an apr_ldap_url_desc_t object. 577251876Speter * 578251876Speter * APR_SUCCESS is returned on success, APR_EGENERAL on failure. 579251876Speter * The LDAP result code and reason string is returned in the 580251876Speter * apr_ldap_err_t structure. 581251876Speter */ 582251876SpeterAPU_DECLARE(int) apr_ldap_url_parse(apr_pool_t *pool, 583251876Speter const char *url_in, 584251876Speter apr_ldap_url_desc_t **ludpp, 585251876Speter apr_ldap_err_t **result_err) 586251876Speter{ 587251876Speter 588251876Speter int rc = apr_ldap_url_parse_ext(pool, url_in, ludpp, result_err); 589251876Speter if( rc != APR_SUCCESS ) { 590251876Speter return rc; 591251876Speter } 592251876Speter 593251876Speter if ((*ludpp)->lud_scope == -1) { 594251876Speter (*ludpp)->lud_scope = LDAP_SCOPE_BASE; 595251876Speter } 596251876Speter 597251876Speter if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') { 598251876Speter (*ludpp)->lud_host = NULL; 599251876Speter } 600251876Speter 601251876Speter return rc; 602251876Speter 603251876Speter} 604251876Speter 605251876Speter 606251876Speterstatic void apr_ldap_pvt_hex_unescape(char *s) 607251876Speter{ 608251876Speter /* 609251876Speter * Remove URL hex escapes from s... done in place. The basic concept for 610251876Speter * this routine is borrowed from the WWW library HTUnEscape() routine. 611251876Speter */ 612251876Speter char *p; 613251876Speter 614251876Speter for ( p = s; *s != '\0'; ++s ) { 615251876Speter if ( *s == '%' ) { 616251876Speter if ( *++s == '\0' ) { 617251876Speter break; 618251876Speter } 619251876Speter *p = apr_ldap_pvt_unhex( *s ) << 4; 620251876Speter if ( *++s == '\0' ) { 621251876Speter break; 622251876Speter } 623251876Speter *p++ += apr_ldap_pvt_unhex( *s ); 624251876Speter } else { 625251876Speter *p++ = *s; 626251876Speter } 627251876Speter } 628251876Speter 629251876Speter *p = '\0'; 630251876Speter} 631251876Speter 632251876Speter 633251876Speterstatic int apr_ldap_pvt_unhex(int c) 634251876Speter{ 635251876Speter return( c >= '0' && c <= '9' ? c - '0' 636251876Speter : c >= 'A' && c <= 'F' ? c - 'A' + 10 637251876Speter : c - 'a' + 10 ); 638251876Speter} 639251876Speter 640251876Speter 641251876Speter/** 642251876Speter * Convert a string to a character array 643251876Speter */ 644251876Speterstatic char **apr_ldap_str2charray(apr_pool_t *pool, 645251876Speter const char *str_in, 646251876Speter const char *brkstr) 647251876Speter{ 648251876Speter char **res; 649251876Speter char *str, *s; 650251876Speter char *lasts; 651251876Speter int i; 652251876Speter 653251876Speter /* protect the input string from strtok */ 654251876Speter str = (char *)apr_pstrdup(pool, str_in); 655251876Speter if( str == NULL ) { 656251876Speter return NULL; 657251876Speter } 658251876Speter 659251876Speter i = 1; 660251876Speter for ( s = str; *s; s++ ) { 661251876Speter /* Warning: this strchr was previously ldap_utf8_strchr(), check 662251876Speter * whether this particular code has any charset issues. 663251876Speter */ 664251876Speter if ( strchr( brkstr, *s ) != NULL ) { 665251876Speter i++; 666251876Speter } 667251876Speter } 668251876Speter 669251876Speter res = (char **) apr_pcalloc(pool, (i + 1) * sizeof(char *)); 670251876Speter if( res == NULL ) { 671251876Speter return NULL; 672251876Speter } 673251876Speter 674251876Speter i = 0; 675251876Speter 676251876Speter for ( s = (char *)apr_strtok( str, brkstr, &lasts ); 677251876Speter s != NULL; 678251876Speter s = (char *)apr_strtok( NULL, brkstr, &lasts ) ) { 679251876Speter 680251876Speter res[i] = (char *)apr_pstrdup(pool, s); 681251876Speter if(res[i] == NULL) { 682251876Speter return NULL; 683251876Speter } 684251876Speter 685251876Speter i++; 686251876Speter } 687251876Speter 688251876Speter res[i] = NULL; 689251876Speter 690251876Speter return( res ); 691251876Speter 692251876Speter} 693251876Speter 694251876Speter#endif /* APR_HAS_LDAP */ 695