X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Furl.c;h=97059170b7d214db18b30fe4d1e417de65933ef9;hb=bb17493d31e19c47bc3a906a39ffa3d57e28aaa4;hp=adc08c9b48951ee2fc7f9791ce58b00064f1ef8d;hpb=8684be027837029f0cc082f2e5d8fc197da5db0f;p=openldap diff --git a/libraries/libldap/url.c b/libraries/libldap/url.c index adc08c9b48..97059170b7 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 */ @@ -60,11 +60,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 +132,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 ) { @@ -181,6 +206,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 ); } @@ -206,6 +241,185 @@ 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_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) @@ -231,7 +445,11 @@ ldap_url_parse_ext( 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 */ +#ifdef NEW_LOGGING + LDAP_LOG (( "url", LDAP_LEVEL_ENTRY, "ldap_url_parse_ext(%s)\n", url_in )); +#else Debug( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 ); +#endif #endif *ludpp = NULL; /* pessimistic */ @@ -271,7 +489,7 @@ ldap_url_parse_ext( 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; @@ -287,10 +505,6 @@ ldap_url_parse_ext( 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, '/' ); @@ -555,6 +769,18 @@ ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp ) (*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; } @@ -665,7 +891,7 @@ ldap_url_parselist (LDAPURLDesc **ludlist, const char *url ) if (url == NULL) return LDAP_PARAM_ERROR; - urls = ldap_str2charray((char *)url, ", "); + urls = ldap_str2charray(url, ", "); if (urls == NULL) return LDAP_NO_MEMORY; @@ -702,7 +928,7 @@ ldap_url_parsehosts( if (hosts == NULL) return LDAP_PARAM_ERROR; - specs = ldap_str2charray((char *)hosts, ", "); + specs = ldap_str2charray(hosts, ", "); if (specs == NULL) return LDAP_NO_MEMORY; @@ -893,92 +1119,14 @@ ldap_free_urldesc( LDAPURLDesc *ludp ) LDAP_FREE( ludp ); } - - -int -ldap_url_search( LDAP *ld, LDAP_CONST char *url, int attrsonly ) +static int +ldap_int_unhex( int c ) { - int err; - LDAPURLDesc *ludp; - 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 ); - - 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, - 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 ) -{ - 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 ) { @@ -991,10 +1139,10 @@ ldap_pvt_hex_unescape( char *s ) for ( p = s; *s != '\0'; ++s ) { if ( *s == '%' ) { if ( *++s != '\0' ) { - *p = ldap_pvt_unhex( *s ) << 4; + *p = ldap_int_unhex( *s ) << 4; } if ( *++s != '\0' ) { - *p++ += ldap_pvt_unhex( *s ); + *p++ += ldap_int_unhex( *s ); } } else { *p++ = *s; @@ -1005,10 +1153,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 ); -}