ap_ldap_url.c revision 328106dab4706c964329eb20ad8173e1dbd2d32a
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Portions Copyright 1998-2002 The OpenLDAP Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License. A copy of this license is available at
* http://www.OpenLDAP.org/license.html or in file LICENSE in the
* top-level directory of the distribution.
*
* OpenLDAP is a registered trademark of the OpenLDAP Foundation.
*
* other parties and subject to additional restrictions.
*
* This work is derived from the University of Michigan LDAP v3.3
* distribution. Information concerning this software is available
*
* This work also contains materials derived from public sources.
*
* Additional information about OpenLDAP can be obtained at:
*/
/*
* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
/* ap_ldap_url.c -- LDAP URL (RFC 2255) related routines
*
* Win32 and perhaps other non-OpenLDAP based ldap libraries may be
* missing ldap_url_* APIs. We focus here on the one significant
* aspect, which is parsing. We have [for the time being] omitted
* the ldap_url_search APIs.
*
* LDAP URLs look like this:
* ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
*
* where:
* attributes is a comma separated list
* scope is one of these three strings: base one sub (default=base)
* filter is an string-represented filter as in RFC 2254
*
*
* Tolerates URLs that look like: <ldapurl> and <URL:ldapurl>
*/
#include "apu.h"
#include "apr_pools.h"
#include "apr_general.h"
#include "apr_strings.h"
#include "ap_config.h"
#include "ap_ldap.h"
#if AP_HAS_LDAP
#include <stdlib.h>
#endif
#ifndef LDAPS_PORT
#endif
#define AP_LDAP_URL_PREFIX "ldap://"
#define AP_LDAPS_URL_PREFIX "ldaps://"
#define AP_LDAPI_URL_PREFIX "ldapi://"
#define AP_LDAP_URL_URLCOLON "URL:"
/* local functions */
static const char* skip_url_prefix(const char *url,
int *enclosedp,
const char **scheme);
static void ap_ldap_pvt_hex_unescape(char *s);
static int ap_ldap_pvt_unhex(int c);
const char *str,
const char *brkstr);
/**
* Is this URL an ldap url?
*
*/
{
int enclosed;
const char * scheme;
return 0;
}
return 0;
}
return 1;
}
/**
* Is this URL a secure ldap url?
*
*/
{
int enclosed;
const char * scheme;
return 0;
}
return 0;
}
}
/**
* Is this URL an ldap socket url?
*
*/
{
int enclosed;
const char * scheme;
return 0;
}
return 0;
}
}
const char **scheme)
{
/*
* return non-zero if this looks like a LDAP URL; zero if not
* if non-zero returned, *urlp will be moved past "ldap://" part of URL
*/
const char *p;
return( NULL );
}
p = url;
/* skip leading '<' (if any) */
if ( *p == '<' ) {
*enclosedp = 1;
++p;
} else {
*enclosedp = 0;
}
/* skip leading "URL:" (if any) */
p += AP_LDAP_URL_URLCOLON_LEN;
}
/* check for "ldap://" prefix */
/* skip over "ldap://" prefix and return success */
p += AP_LDAP_URL_PREFIX_LEN;
*scheme = "ldap";
return( p );
}
/* check for "ldaps://" prefix */
/* skip over "ldaps://" prefix and return success */
p += AP_LDAPS_URL_PREFIX_LEN;
*scheme = "ldaps";
return( p );
}
/* check for "ldapi://" prefix */
/* skip over "ldapi://" prefix and return success */
p += AP_LDAPI_URL_PREFIX_LEN;
*scheme = "ldapi";
return( p );
}
return( NULL );
}
static int str2scope(const char *p)
{
if ( strcasecmp( p, "one" ) == 0 ) {
return LDAP_SCOPE_ONELEVEL;
} else if ( strcasecmp( p, "onetree" ) == 0 ) {
return LDAP_SCOPE_ONELEVEL;
} else if ( strcasecmp( p, "base" ) == 0 ) {
return LDAP_SCOPE_BASE;
} else if ( strcasecmp( p, "sub" ) == 0 ) {
return LDAP_SCOPE_SUBTREE;
} else if ( strcasecmp( p, "subtree" ) == 0 ) {
return LDAP_SCOPE_SUBTREE;
}
return( -1 );
}
/**
* Parse the URL provided into an ap_ldap_url_desc_t object.
*
* APR_SUCCESS is returned on success, APR_EGENERAL on failure.
* The LDAP result code and reason string is returned in the
* ap_ldap_err_t structure.
*/
const char *url_in,
{
char *p, *q, *r;
int i, enclosed;
const char *url_tmp;
char *url;
*result_err = result;
/* sanity check our parameters */
return APR_EGENERAL;
}
return APR_EGENERAL;
}
/* make working copy of the remainder of the URL */
return APR_EGENERAL;
}
if ( enclosed ) {
if( *p != '>' ) {
return APR_EGENERAL;
}
*p = '\0';
}
/* allocate return struct */
return APR_EGENERAL;
}
return APR_EGENERAL;
}
}
/* scan forward for '/' that marks end of hostport and begin. of dn */
if( p != NULL ) {
/* terminate hostport; point to start of dn */
*p++ = '\0';
}
/* IPv6 syntax with [ip address]:port */
if ( *url == '[' ) {
if ( r == NULL ) {
return APR_EGENERAL;
}
*r++ = '\0';
q = strrchr( r, ':' );
} else {
}
if ( q != NULL ) {
ap_ldap_pvt_hex_unescape( ++q );
if( *q == '\0' ) {
return APR_EGENERAL;
}
}
/* If [ip address]:port syntax, url is [ip and we skip the [ */
return APR_EGENERAL;
}
/*
* Kludge. ldap://111.222.333.444:389??cn=abc,o=company
*
* On early Novell releases, search references/referrals were returned
* in this format, i.e., the dn was kind of in the scope position,
* but the required slash is missing. The whole thing is illegal syntax,
* but we need to account for it. Fortunately it can't be confused with
* anything real.
*/
q++;
/* ? immediately followed by question */
if( *q == '?') {
q++;
if( *q != '\0' ) {
/* parse dn part */
ap_ldap_pvt_hex_unescape( q );
} else {
}
return APR_EGENERAL;
}
}
}
if( p == NULL ) {
return APR_SUCCESS;
}
/* scan forward for '?' that may marks end of dn */
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate dn part */
*q++ = '\0';
}
if( *p != '\0' ) {
/* parse dn part */
ap_ldap_pvt_hex_unescape( p );
} else {
}
return APR_EGENERAL;
}
if( q == NULL ) {
/* no more */
return APR_SUCCESS;
}
/* scan forward for '?' that may marks end of attributes */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate attributes part */
*q++ = '\0';
}
if( *p != '\0' ) {
/* parse attributes */
ap_ldap_pvt_hex_unescape( p );
return APR_EGENERAL;
}
}
if ( q == NULL ) {
/* no more */
return APR_SUCCESS;
}
/* scan forward for '?' that may marks end of scope */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate the scope part */
*q++ = '\0';
}
if( *p != '\0' ) {
/* parse the scope */
ap_ldap_pvt_hex_unescape( p );
return APR_EGENERAL;
}
}
if ( q == NULL ) {
/* no more */
return APR_SUCCESS;
}
/* scan forward for '?' that may marks end of filter */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* terminate the filter part */
*q++ = '\0';
}
if( *p != '\0' ) {
/* parse the filter */
ap_ldap_pvt_hex_unescape( p );
if( ! *p ) {
/* missing filter */
return APR_EGENERAL;
}
return APR_EGENERAL;
}
}
if ( q == NULL ) {
/* no more */
return APR_SUCCESS;
}
/* scan forward for '?' that may marks end of extensions */
p = q;
q = strchr( p, '?' );
if( q != NULL ) {
/* extra '?' */
return APR_EGENERAL;
}
/* parse the extensions */
return APR_EGENERAL;
}
/* count the number of critical extensions */
ludp->lud_crit_exts++;
}
}
if( i == 0 ) {
/* must have 1 or more */
return APR_EGENERAL;
}
/* no more */
return APR_SUCCESS;
}
/**
* Parse the URL provided into an ap_ldap_url_desc_t object.
*
* APR_SUCCESS is returned on success, APR_EGENERAL on failure.
* The LDAP result code and reason string is returned in the
* ap_ldap_err_t structure.
*/
const char *url_in,
{
if( rc != APR_SUCCESS ) {
return rc;
}
}
}
return rc;
}
static void ap_ldap_pvt_hex_unescape(char *s)
{
/*
* Remove URL hex escapes from s... done in place. The basic concept for
* this routine is borrowed from the WWW library HTUnEscape() routine.
*/
char *p;
for ( p = s; *s != '\0'; ++s ) {
if ( *s == '%' ) {
if ( *++s == '\0' ) {
break;
}
*p = ap_ldap_pvt_unhex( *s ) << 4;
if ( *++s == '\0' ) {
break;
}
*p++ += ap_ldap_pvt_unhex( *s );
} else {
*p++ = *s;
}
}
*p = '\0';
}
static int ap_ldap_pvt_unhex(int c)
{
return( c >= '0' && c <= '9' ? c - '0'
: c >= 'A' && c <= 'F' ? c - 'A' + 10
: c - 'a' + 10 );
}
/**
* Convert a string to a character array
*/
const char *str_in,
const char *brkstr)
{
char **res;
char *str, *s;
char *lasts;
int i;
/* protect the input string from strtok */
return NULL;
}
i = 1;
for ( s = str; *s; s++ ) {
/* Warning: this strchr was previously ldap_utf8_strchr(), check
* whether this particular code has any charset issues.
*/
i++;
}
}
return NULL;
}
i = 0;
s != NULL;
return NULL;
}
i++;
}
return( res );
}
#endif /* AP_HAS_LDAP */