X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Furl.c;h=882d21da30c3919a6969eca9e8abe86a682b7829;hb=3d39ff68a94e4455074707d763138f01aaa1c5b1;hp=0780b6ca072d4ebe98c26df25b6de4f46a3b1a1a;hpb=4587e053e7ac2f4e80ac6ca66607190de0f1fc69;p=openldap diff --git a/libraries/libldap/url.c b/libraries/libldap/url.c index 0780b6ca07..882d21da30 100644 --- a/libraries/libldap/url.c +++ b/libraries/libldap/url.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2006 The OpenLDAP Foundation. + * Copyright 1998-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -20,7 +20,7 @@ /* * LDAP URLs look like this: - * ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]] + * ldap[is]://host[:port][/[dn[?[attributes][?[scope][?[filter][?exts]]]]]] * * where: * attributes is a comma separated list @@ -533,12 +533,17 @@ desc2str_len( LDAPURLDesc *u ) { int sep = 0; int len = 0; + int is_ipc = 0; struct berval scope; - if ( u == NULL ) { + if ( u == NULL || u->lud_scheme == NULL ) { return -1; } + if ( !strcmp( "ldapi", u->lud_scheme )) { + is_ipc = 1; + } + if ( u->lud_exts ) { len += hex_escape_len_list( u->lud_exts, URLESC_COMMA ); if ( !sep ) { @@ -547,7 +552,7 @@ desc2str_len( LDAPURLDesc *u ) } if ( u->lud_filter ) { - len += hex_escape_len( u->lud_filter, URLESC_NONE ); + len += hex_escape_len( u->lud_filter, URLESC_NONE ); if ( !sep ) { sep = 4; } @@ -561,7 +566,7 @@ desc2str_len( LDAPURLDesc *u ) } if ( u->lud_attrs ) { - len += hex_escape_len_list( u->lud_attrs, URLESC_NONE ); + len += hex_escape_len_list( u->lud_attrs, URLESC_NONE ); if ( !sep ) { sep = 2; } @@ -577,16 +582,17 @@ desc2str_len( LDAPURLDesc *u ) len += sep; if ( u->lud_port ) { - char buf[] = ":65535"; + unsigned p = u->lud_port; + if ( p > 65535 ) + return -1; - len += snprintf( buf, sizeof( buf ), ":%d", u->lud_port ); - if ( u->lud_host && u->lud_host[0] ) { - len += strlen( u->lud_host ); - } + len += (p > 999 ? 5 + (p > 9999) : p > 99 ? 4 : 2 + (p > 9)); + } - } else { - if ( u->lud_host && u->lud_host[0] ) { - len += hex_escape_len( u->lud_host, URLESC_SLASH ); + if ( u->lud_host && u->lud_host[0] ) { + len += hex_escape_len( u->lud_host, URLESC_SLASH ); + if ( !is_ipc && strchr( u->lud_host, ':' )) { + len += 2; /* IPv6, [] */ } } @@ -595,12 +601,14 @@ desc2str_len( LDAPURLDesc *u ) return len; } -int +static int desc2str( LDAPURLDesc *u, char *s, int len ) { int i; int sep = 0; int sofar = 0; + int is_v6 = 0; + int is_ipc = 0; struct berval scope = BER_BVNULL; if ( u == NULL ) { @@ -611,6 +619,10 @@ desc2str( LDAPURLDesc *u, char *s, int len ) return -1; } + if ( u->lud_scheme && !strcmp( "ldapi", u->lud_scheme )) { + is_ipc = 1; + } + ldap_pvt_scope2bv( u->lud_scope, &scope ); if ( u->lud_exts ) { @@ -625,17 +637,31 @@ desc2str( LDAPURLDesc *u, char *s, int len ) sep = 1; } + if ( !is_ipc && u->lud_host && strchr( u->lud_host, ':' )) { + is_v6 = 1; + } + if ( u->lud_port ) { - len -= sprintf( s, "%s://%s:%d%n", u->lud_scheme, + len -= sprintf( s, "%s://%s%s%s:%d%n", u->lud_scheme, + is_v6 ? "[" : "", u->lud_host ? u->lud_host : "", + is_v6 ? "]" : "", u->lud_port, &sofar ); } else { len -= sprintf( s, "%s://%n", u->lud_scheme, &sofar ); if ( u->lud_host && u->lud_host[0] ) { + if ( is_v6 ) { + s[sofar++] = '['; + len--; + } i = hex_escape( &s[sofar], len, u->lud_host, URLESC_SLASH ); sofar += i; len -= i; + if ( is_v6 ) { + s[sofar++] = ']'; + len--; + } } } @@ -765,7 +791,7 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags LDAPURLDesc *ludp; char *p, *q, *r; - int i, enclosed; + int i, enclosed, proto, is_v6 = 0; const char *scheme = NULL; const char *url_tmp; char *url; @@ -795,6 +821,11 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags assert( scheme != NULL ); + proto = ldap_pvt_url_scheme2proto( scheme ); + if ( proto == -1 ) { + return LDAP_URL_ERR_BADSCHEME; + } + /* make working copy of the remainder of the URL */ url = LDAP_STRDUP( url_tmp ); if ( url == NULL ) { @@ -839,62 +870,83 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags /* scan forward for '/' that marks end of hostport and begin. of dn */ p = strchr( url, '/' ); + q = NULL; if( p != NULL ) { /* terminate hostport; point to start of dn */ *p++ = '\0'; + } else { + /* check for Novell kludge, see below */ + p = strchr( url, '?' ); + if ( p ) { + *p++ = '\0'; + q = p; + p = 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; + if ( proto != LDAP_PROTO_IPC ) { + /* 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, ':' ); + if ( q && q != r ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + is_v6 = 1; + } else { + q = strchr( url, ':' ); } - *r++ = '\0'; - q = strchr( r, ':' ); - } else { - q = strchr( url, ':' ); - } - if ( q != NULL ) { - char *next; + if ( q != NULL ) { + char *next; - *q++ = '\0'; - ldap_pvt_hex_unescape( q ); + *q++ = '\0'; + ldap_pvt_hex_unescape( q ); - if( *q == '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; - } + if( *q == '\0' ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } - ludp->lud_port = strtol( q, &next, 10 ); - if ( next == q || next[0] != '\0' ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_BADURL; + ludp->lud_port = strtol( q, &next, 10 ); + if ( next == q || next[0] != '\0' ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_BADURL; + } + /* check for Novell kludge */ + if ( !p ) { + if ( *next != '\0' ) { + q = &next[1]; + } else { + q = NULL; + } + } } - } - if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) { - if ( strcmp( ludp->lud_scheme, "ldap" ) == 0 ) { - ludp->lud_port = LDAP_PORT; -#ifdef LDAP_CONNECTIONLESS - } else if ( strcmp( ludp->lud_scheme, "cldap" ) == 0 ) { - ludp->lud_port = LDAP_PORT; -#endif - } else if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) { - ludp->lud_port = LDAPS_PORT; + if ( ( flags & LDAP_PVT_URL_PARSE_DEF_PORT ) && ludp->lud_port == 0 ) { + if ( strcmp( ludp->lud_scheme, "ldaps" ) == 0 ) { + ludp->lud_port = LDAPS_PORT; + } else { + ludp->lud_port = LDAP_PORT; + } } } ldap_pvt_hex_unescape( url ); /* If [ip address]:port syntax, url is [ip and we skip the [ */ - ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) ); + ludp->lud_host = LDAP_STRDUP( url + is_v6 ); if( ludp->lud_host == NULL ) { LDAP_FREE( url ); @@ -919,28 +971,25 @@ ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp, unsigned flags * but we need to account for it. Fortunately it can't be confused with * anything real. */ - if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) { - q++; + if( (p == NULL) && (q != NULL) && (*q == '?') ) { /* ? immediately followed by question */ - if( *q == '?') { - q++; - if( *q != '\0' ) { - /* parse dn part */ - ldap_pvt_hex_unescape( q ); - ludp->lud_dn = LDAP_STRDUP( q ); + q++; + if( *q != '\0' ) { + /* parse dn part */ + ldap_pvt_hex_unescape( q ); + ludp->lud_dn = LDAP_STRDUP( q ); - } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) { - ludp->lud_dn = LDAP_STRDUP( "" ); + } else if ( !( flags & LDAP_PVT_URL_PARSE_NOEMPTY_DN ) ) { + ludp->lud_dn = LDAP_STRDUP( "" ); - } else { - check_dn = 0; - } + } else { + check_dn = 0; + } - if ( check_dn && ludp->lud_dn == NULL ) { - LDAP_FREE( url ); - ldap_free_urldesc( ludp ); - return LDAP_URL_ERR_MEM; - } + if ( check_dn && ludp->lud_dn == NULL ) { + LDAP_FREE( url ); + ldap_free_urldesc( ludp ); + return LDAP_URL_ERR_MEM; } }