X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Furl.c;h=adc08c9b48951ee2fc7f9791ce58b00064f1ef8d;hb=241d6a558e3bfd7a7cfc70a1de65fa527fe40e60;hp=d72dbcb5b2fc4a6f244a553b943028f148ccd30c;hpb=e5ebc553ac1fc7adf6fdea9a3b8918967eba2231;p=openldap diff --git a/libraries/libldap/url.c b/libraries/libldap/url.c index d72dbcb5b2..adc08c9b48 100644 --- a/libraries/libldap/url.c +++ b/libraries/libldap/url.c @@ -28,7 +28,6 @@ #include -#include #include #include #include @@ -154,8 +153,7 @@ skip_url_prefix( } /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) - { + if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) { p += LDAP_URL_URLCOLON_LEN; } @@ -210,24 +208,31 @@ static int str2scope( const char *p ) int -ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) +ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) { /* * Pick apart the pieces of an LDAP URL. */ LDAPURLDesc *ludp; - char *p, *q; + char *p, *q, *r; int i, enclosed; const char *scheme = NULL; const char *url_tmp; char *url; - if( url_in == NULL && ludpp == NULL ) { + if( url_in == NULL || ludpp == NULL ) { return LDAP_URL_ERR_PARAM; } - Debug( LDAP_DEBUG_TRACE, "ldap_url_parse(%s)\n", url_in, 0, 0 ); +#ifndef LDAP_INT_IN_KERNEL + /* Global options may not be created yet + * We can't test if the global options are initialized + * because a call to LDAP_INT_GLOBAL_OPT() will try to allocate + * the options and cause infinite recursion + */ + Debug( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 ); +#endif *ludpp = NULL; /* pessimistic */ @@ -240,8 +245,9 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) assert( scheme ); /* make working copy of the remainder of the URL */ - if (( url = LDAP_STRDUP( url_tmp )) == NULL ) { - return( LDAP_URL_ERR_MEM ); + url = LDAP_STRDUP( url_tmp ); + if ( url == NULL ) { + return LDAP_URL_ERR_MEM; } if ( enclosed ) { @@ -265,12 +271,13 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) ludp->lud_next = NULL; ludp->lud_host = NULL; - ludp->lud_port = 0; + ludp->lud_port = LDAP_PORT; ludp->lud_dn = NULL; ludp->lud_attrs = NULL; ludp->lud_filter = NULL; - ludp->lud_scope = LDAP_SCOPE_BASE; + ludp->lud_scope = LDAP_SCOPE_DEFAULT; ludp->lud_filter = NULL; + ludp->lud_exts = NULL; ludp->lud_scheme = LDAP_STRDUP( scheme ); @@ -280,6 +287,10 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) return LDAP_URL_ERR_MEM; } + if( strcasecmp( ludp->lud_scheme, "ldaps" ) == 0 ) { + ludp->lud_port = LDAPS_PORT; + } + /* scan forward for '/' that marks end of hostport and begin. of dn */ p = strchr( url, '/' ); @@ -288,7 +299,21 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) *p++ = '\0'; } - if (( q = strchr( url, ':' )) != NULL ) { + /* IPv6 syntax with [ip address]:port */ + if ( *url == '[' ) { + r = strchr( url, ']' ); + if ( r == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + *r++ = '\0'; + q = strchr( r, ':' ); + } else { + q = strchr( url, ':' ); + } + + if ( q != NULL ) { *q++ = '\0'; ldap_pvt_hex_unescape( q ); @@ -302,7 +327,9 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) } ldap_pvt_hex_unescape( url ); - ludp->lud_host = LDAP_STRDUP( url ); + + /* If [ip address]:port syntax, url is [ip and we skip the [ */ + ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) ); if( ludp->lud_host == NULL ) { LDAP_FREE( url ); @@ -319,7 +346,7 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) * but we need to account for it. Fortunately it can't be confused with * anything real. */ - if( (p == NULL) && ((q = strchr( q, '?')) != NULL)) { + if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { q++; /* ? immediately followed by question */ if( *q == '?') { @@ -490,11 +517,15 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) for( i=0; ludp->lud_exts[i] != NULL; i++ ) { ldap_pvt_hex_unescape( ludp->lud_exts[i] ); + + if( *ludp->lud_exts[i] == '!' ) { + /* count the number of critical extensions */ + ludp->lud_crit_exts++; + } } if( i == 0 ) { /* must have 1 or more */ - ldap_charray_free( ludp->lud_exts ); LDAP_FREE( url ); ldap_free_urldesc( ludp ); return LDAP_URL_ERR_BADEXTS; @@ -506,6 +537,27 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) return LDAP_URL_SUCCESS; } +int +ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) +{ + int rc = ldap_url_parse_ext( url_in, ludpp ); + + if( rc != LDAP_URL_SUCCESS ) { + return rc; + } + + if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) { + (*ludpp)->lud_scope = LDAP_SCOPE_BASE; + } + + if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') { + LDAP_FREE( (*ludpp)->lud_host ); + (*ludpp)->lud_host = NULL; + } + + return rc; +} + LDAPURLDesc * ldap_url_dup ( LDAPURLDesc *ludp ) { @@ -636,7 +688,10 @@ ldap_url_parselist (LDAPURLDesc **ludlist, const char *url ) } int -ldap_url_parsehosts (LDAPURLDesc **ludlist, const char *hosts ) +ldap_url_parsehosts( + LDAPURLDesc **ludlist, + const char *hosts, + int port ) { int i; LDAPURLDesc *ludp; @@ -663,13 +718,37 @@ ldap_url_parsehosts (LDAPURLDesc **ludlist, const char *hosts ) *ludlist = NULL; return LDAP_NO_MEMORY; } + ludp->lud_port = port; ludp->lud_host = specs[i]; specs[i] = NULL; p = strchr(ludp->lud_host, ':'); if (p != NULL) { - *p++ = 0; - ldap_pvt_hex_unescape(p); - ludp->lud_port = atoi(p); + /* more than one :, IPv6 address */ + if ( strchr(p+1, ':') != NULL ) { + /* allow [address] and [address]:port */ + if ( *ludp->lud_host == '[' ) { + p = LDAP_STRDUP(ludp->lud_host+1); + /* copied, make sure we free source later */ + specs[i] = ludp->lud_host; + ludp->lud_host = p; + p = strchr( ludp->lud_host, ']' ); + if ( p == NULL ) + return LDAP_PARAM_ERROR; + *p++ = '\0'; + if ( *p != ':' ) { + if ( *p != '\0' ) + return LDAP_PARAM_ERROR; + p = NULL; + } + } else { + p = NULL; + } + } + if (p != NULL) { + *p++ = 0; + ldap_pvt_hex_unescape(p); + ludp->lud_port = atoi(p); + } } ldap_pvt_hex_unescape(ludp->lud_host); ludp->lud_scheme = LDAP_STRDUP("ldap"); @@ -678,6 +757,7 @@ ldap_url_parsehosts (LDAPURLDesc **ludlist, const char *hosts ) } /* this should be an array of NULLs now */ + /* except entries starting with [ */ ldap_charray_free(specs); return LDAP_SUCCESS; } @@ -696,6 +776,8 @@ ldap_url_list2hosts (LDAPURLDesc *ludlist) size = 1; /* nul-term */ for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { size += strlen(ludp->lud_host) + 1; /* host and space */ + if (strchr(ludp->lud_host, ':')) /* will add [ ] below */ + size += 2; if (ludp->lud_port != 0) size += sprintf(buf, ":%d", ludp->lud_port); } @@ -705,8 +787,12 @@ ldap_url_list2hosts (LDAPURLDesc *ludlist) p = s; for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { - strcpy(p, ludp->lud_host); - p += strlen(ludp->lud_host); + if (strchr(ludp->lud_host, ':')) { + p += sprintf(p, "[%s]", ludp->lud_host); + } else { + strcpy(p, ludp->lud_host); + p += strlen(ludp->lud_host); + } if (ludp->lud_port != 0) p += sprintf(p, ":%d", ludp->lud_port); *p++ = ' '; @@ -732,6 +818,8 @@ ldap_url_list2urls( size = 1; /* nul-term */ for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { size += strlen(ludp->lud_scheme) + strlen(ludp->lud_host); + if (strchr(ludp->lud_host, ':')) /* will add [ ] below */ + size += 2; size += sizeof(":/// "); if (ludp->lud_port != 0) { @@ -746,7 +834,9 @@ ldap_url_list2urls( p = s; for (ludp = ludlist; ludp != NULL; ludp = ludp->lud_next) { - p += sprintf(p, "%s://%s", ludp->lud_scheme, ludp->lud_host); + p += sprintf(p, + strchr(ludp->lud_host, ':') ? "%s://[%s]" : "%s://%s", + ludp->lud_scheme, ludp->lud_host); if (ludp->lud_port != 0) p += sprintf(p, ":%d", ludp->lud_port); *p++ = '/'; @@ -813,11 +903,20 @@ ldap_url_search( LDAP *ld, LDAP_CONST char *url, int attrsonly ) BerElement *ber; LDAPreqinfo bind; + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + if ( ldap_url_parse( url, &ludp ) != 0 ) { ld->ld_errno = LDAP_PARAM_ERROR; return( -1 ); } + if( ludp->lud_crit_exts ) { + /* we don't support any extension (yet) */ + ld->ld_errno = LDAP_NOT_SUPPORTED; + return( -1 ); + } + ber = ldap_build_search_req( ld, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, attrsonly, NULL, NULL, -1, -1 ); @@ -830,9 +929,7 @@ ldap_url_search( LDAP *ld, LDAP_CONST char *url, int attrsonly ) bind.ri_url = (char *)url; err = ldap_send_server_request( ld, ber, ld->ld_msgid, NULL, - (ludp->lud_host != NULL || ludp->lud_port != 0) - ? ludp : NULL, - NULL, &bind ); + NULL, NULL, &bind ); } ldap_free_urldesc( ludp ); @@ -885,10 +982,10 @@ ldap_url_search_s( void 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. -*/ + /* + * 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 ) {