X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Furl.c;h=8bf8bd56d56f7a9d86cb7d1c5f897c48a86f49af;hb=3b9f4a82ee478c943a66696adf9133dc9f503e16;hp=ccb7eca61335ca6267887896b1fc4b84be3467d0;hpb=57ed8f645810a858b33c294afad72fd2add674d4;p=openldap diff --git a/libraries/libldap/url.c b/libraries/libldap/url.c index ccb7eca613..8bf8bd56d5 100644 --- a/libraries/libldap/url.c +++ b/libraries/libldap/url.c @@ -1,6 +1,6 @@ /* $OpenLDAP$ */ /* - * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ /* Portions @@ -17,7 +17,7 @@ * scope is one of these three strings: base one sub (default=base) * filter is an string-represented filter as in RFC 2254 * - * e.g., ldap://host:port/dc=com?o,cn?base?o=openldap?extension + * e.g., ldap://host:port/dc=com?o,cn?base?(o=openldap)?extension * * We also tolerate URLs that look like: and */ @@ -34,7 +34,6 @@ #include "ldap-int.h" - /* local functions */ static const char* skip_url_prefix LDAP_P(( const char *url, @@ -60,11 +59,17 @@ int ldap_pvt_url_scheme2proto( const char *scheme ) if( strcmp("ldaps", scheme) == 0 ) { return LDAP_PROTO_TCP; } +#ifdef LDAP_CONNECTIONLESS + if( strcmp("cldap", scheme) == 0 ) { + return LDAP_PROTO_UDP; + } +#endif return -1; } -int ldap_pvt_url_scheme2tls( const char *scheme ) +int +ldap_pvt_url_scheme2tls( const char *scheme ) { assert( scheme ); @@ -126,16 +131,35 @@ ldap_is_ldapi_url( LDAP_CONST char *url ) return strcmp(scheme, "ldapi") == 0; } +#ifdef LDAP_CONNECTIONLESS +int +ldap_is_ldapc_url( LDAP_CONST char *url ) +{ + int enclosed; + const char * scheme; + + if( url == NULL ) { + return 0; + } + + if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) { + return 0; + } + + return strcmp(scheme, "cldap") == 0; +} +#endif + static const char* skip_url_prefix( const char *url, int *enclosedp, 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 - */ + /* + * 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; if ( url == NULL ) { @@ -153,8 +177,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; } @@ -182,6 +205,16 @@ skip_url_prefix( return( p ); } +#ifdef LDAP_CONNECTIONLESS + /* check for "cldap://" prefix */ + if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) { + /* skip over "cldap://" prefix and return success */ + p += LDAPC_URL_PREFIX_LEN; + *scheme = "cldap"; + return( p ); + } +#endif + return( NULL ); } @@ -207,9 +240,188 @@ static int str2scope( const char *p ) return( -1 ); } +static int hex_escape( char *buf, const char *s, int list ) +{ + int i; + int pos; + static const char hex[] = "0123456789ABCDEF"; + + if( s == NULL ) return 0; + + for( pos=0,i=0; s[i]; i++ ) { + int escape = 0; + switch( s[i] ) { + case ',': + escape = list; + break; + case '%': + case '?': + case ' ': + case '<': + case '>': + case '"': + case '#': + case '{': + case '}': + case '|': + case '\\': + case '^': + case '~': + case '`': + case '[': + case ']': + escape = 1; + break; + + default: + escape = s[i] < 0x20 || 0x1f >= s[i]; + } + + if( escape ) { + buf[pos++] = '%'; + buf[pos++] = hex[ (s[i] >> 4) & 0x0f ]; + buf[pos++] = hex[ s[i] & 0x0f ]; + } else { + buf[pos++] = s[i]; + } + } + + buf[pos] = '\0'; + return pos; +} + +static int hex_escape_args( char *buf, char **s ) +{ + int pos; + int i; + + if( s == NULL ) return 0; + + pos = 0; + for( i=0; s[i] != NULL; i++ ) { + if( pos ) { + buf[pos++] = ','; + } + pos += hex_escape( &buf[pos], s[i], 1 ); + } + + return pos; +} + +char * ldap_url_desc2str( LDAPURLDesc *u ) +{ + char *s; + int i; + int sep = 0; + int sofar; + size_t len = 0; + if( u == NULL ) return NULL; + + if( u->lud_exts ) { + for( i=0; u->lud_exts[i]; i++ ) { + len += strlen( u->lud_exts[i] ) + 1; + } + if( !sep ) sep = 5; + } + + if( u->lud_filter ) { + len += strlen( u->lud_filter ); + if( !sep ) sep = 4; + } + if ( len ) len++; /* ? */ + + switch( u->lud_scope ) { + case LDAP_SCOPE_ONELEVEL: + case LDAP_SCOPE_SUBTREE: + case LDAP_SCOPE_BASE: + len += sizeof("base"); + if( !sep ) sep = 3; + break; + + default: + if ( len ) len++; /* ? */ + } + + if( u->lud_attrs ) { + for( i=0; u->lud_attrs[i]; i++ ) { + len += strlen( u->lud_attrs[i] ) + 1; + } + if( !sep ) sep = 2; + } else if ( len ) len++; /* ? */ + + if( u->lud_dn ) { + len += strlen( u->lud_dn ) + 1; + if( !sep ) sep = 1; + }; + + if( u->lud_port ) { + len+=6; + } + + if( u->lud_host ) { + len+=strlen( u->lud_host ); + } + + len += strlen( u->lud_scheme ) + sizeof("://"); + + /* allocate enough to hex escape everything -- overkill */ + s = LDAP_MALLOC( 3*len ); + + if( s == NULL ) return NULL; + + if( u->lud_port ) { + sprintf( s, "%s://%s:%d%n", u->lud_scheme, + u->lud_host, u->lud_port, &sofar ); + } else { + sprintf( s, "%s://%s%n", u->lud_scheme, + u->lud_host, &sofar ); + } + + if( sep < 1 ) goto done; + s[sofar++] = '/'; + + sofar += hex_escape( &s[sofar], u->lud_dn, 0 ); + + if( sep < 2 ) goto done; + s[sofar++] = '?'; + + sofar += hex_escape_args( &s[sofar], u->lud_attrs ); + + if( sep < 3 ) goto done; + s[sofar++] = '?'; + + switch( u->lud_scope ) { + case LDAP_SCOPE_BASE: + strcpy( &s[sofar], "base" ); + sofar += sizeof("base") - 1; + break; + case LDAP_SCOPE_ONELEVEL: + strcpy( &s[sofar], "one" ); + sofar += sizeof("one") - 1; + break; + case LDAP_SCOPE_SUBTREE: + strcpy( &s[sofar], "sub" ); + sofar += sizeof("sub") - 1; + break; + } + + if( sep < 4 ) goto done; + s[sofar++] = '?'; + + sofar += hex_escape( &s[sofar], u->lud_filter, 0 ); + + if( sep < 5 ) goto done; + s[sofar++] = '?'; + + sofar += hex_escape_args( &s[sofar], u->lud_exts ); + +done: + s[sofar] = '\0'; + return s; +} 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. @@ -222,7 +434,7 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) const char *url_tmp; char *url; - if( url_in == NULL && ludpp == NULL ) { + if( url_in == NULL || ludpp == NULL ) { return LDAP_URL_ERR_PARAM; } @@ -232,7 +444,11 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) * 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(%s)\n", url_in, 0, 0 ); +#ifdef NEW_LOGGING + LDAP_LOG ( OPERATION, ENTRY, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 ); +#endif #endif *ludpp = NULL; /* pessimistic */ @@ -272,12 +488,13 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) ludp->lud_next = NULL; ludp->lud_host = NULL; - ludp->lud_port = LDAP_PORT; + ludp->lud_port = 0; 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 ); @@ -287,10 +504,6 @@ 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, '/' ); @@ -517,11 +730,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; @@ -533,6 +750,39 @@ 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; + } + + if ((*ludpp)->lud_port == 0) { + if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) { + (*ludpp)->lud_port = LDAP_PORT; +#ifdef LDAP_CONNECTIONLESS + } else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) { + (*ludpp)->lud_port = LDAP_PORT; +#endif + } else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) { + (*ludpp)->lud_port = LDAPS_PORT; + } + } + + return rc; +} + LDAPURLDesc * ldap_url_dup ( LDAPURLDesc *ludp ) { @@ -635,12 +885,12 @@ ldap_url_parselist (LDAPURLDesc **ludlist, const char *url ) LDAPURLDesc *ludp; char **urls; - *ludlist = NULL; + assert( ludlist != NULL ); + assert( url != NULL ); - if (url == NULL) - return LDAP_PARAM_ERROR; + *ludlist = NULL; - urls = ldap_str2charray((char *)url, ", "); + urls = ldap_str2charray(url, ", "); if (urls == NULL) return LDAP_NO_MEMORY; @@ -672,12 +922,12 @@ ldap_url_parsehosts( LDAPURLDesc *ludp; char **specs, *p; - *ludlist = NULL; + assert( ludlist != NULL ); + assert( hosts != NULL ); - if (hosts == NULL) - return LDAP_PARAM_ERROR; + *ludlist = NULL; - specs = ldap_str2charray((char *)hosts, ", "); + specs = ldap_str2charray(hosts, ", "); if (specs == NULL) return LDAP_NO_MEMORY; @@ -868,102 +1118,33 @@ ldap_free_urldesc( LDAPURLDesc *ludp ) LDAP_FREE( ludp ); } - - -int -ldap_url_search( LDAP *ld, LDAP_CONST char *url, int attrsonly ) -{ - int err; - LDAPURLDesc *ludp; - BerElement *ber; - LDAPreqinfo bind; - - if ( ldap_url_parse( url, &ludp ) != 0 ) { - ld->ld_errno = LDAP_PARAM_ERROR; - 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 ); - - if ( ber == NULL ) { - err = -1; - } else { - bind.ri_request = LDAP_REQ_SEARCH; - bind.ri_msgid = ld->ld_msgid; - 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 ); - } - - ldap_free_urldesc( ludp ); - return( err ); -} - - -int -ldap_url_search_st( LDAP *ld, LDAP_CONST char *url, int attrsonly, - struct timeval *timeout, LDAPMessage **res ) -{ - int msgid; - - if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) { - return( ld->ld_errno ); - } - - if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 ) { - return( ld->ld_errno ); - } - - if ( ld->ld_errno == LDAP_TIMEOUT ) { - (void) ldap_abandon( ld, msgid ); - ld->ld_errno = LDAP_TIMEOUT; - return( ld->ld_errno ); - } - - return( ldap_result2error( ld, *res, 0 )); -} - - -int -ldap_url_search_s( - LDAP *ld, LDAP_CONST char *url, int attrsonly, LDAPMessage **res ) +static int +ldap_int_unhex( int c ) { - int msgid; - - if (( msgid = ldap_url_search( ld, url, attrsonly )) == -1 ) { - return( ld->ld_errno ); - } - - if ( ldap_result( ld, msgid, 1, (struct timeval *)NULL, res ) == -1 ) { - return( ld->ld_errno ); - } - - return( ldap_result2error( ld, *res, 0 )); + return( c >= '0' && c <= '9' ? c - '0' + : c >= 'A' && c <= 'F' ? c - 'A' + 10 + : c - 'a' + 10 ); } - 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 ) { if ( *s == '%' ) { - if ( *++s != '\0' ) { - *p = ldap_pvt_unhex( *s ) << 4; + if ( *++s == '\0' ) { + break; } - if ( *++s != '\0' ) { - *p++ += ldap_pvt_unhex( *s ); + *p = ldap_int_unhex( *s ) << 4; + if ( *++s == '\0' ) { + break; } + *p++ += ldap_int_unhex( *s ); } else { *p++ = *s; } @@ -973,10 +1154,3 @@ ldap_pvt_hex_unescape( char *s ) } -int -ldap_pvt_unhex( int c ) -{ - return( c >= '0' && c <= '9' ? c - '0' - : c >= 'A' && c <= 'F' ? c - 'A' + 10 - : c - 'a' + 10 ); -}