X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fgetdn.c;h=3fe68f5466107aeab1045dcbe3099952ed9b541c;hb=dd733e163a74db2968107b75e14f8705417b02c5;hp=fc2b3264777c95819efc68c1165ed96ec93308cd;hpb=2a869f5a99f537b246ba8640502e2a86117cb6e8;p=openldap diff --git a/libraries/libldap/getdn.c b/libraries/libldap/getdn.c index fc2b326477..3fe68f5466 100644 --- a/libraries/libldap/getdn.c +++ b/libraries/libldap/getdn.c @@ -1,4 +1,9 @@ +/* $OpenLDAP$ */ /* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ +/* Portions * Copyright (c) 1994 Regents of the University of Michigan. * All rights reserved. * @@ -7,20 +12,22 @@ #include "portable.h" -#ifndef lint -static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n"; -#endif - #include -#include + +#include #include #include #include #include -#include "lber.h" -#include "ldap.h" +#include "ldap-int.h" + +#define NAME_TYPE_LDAP_RDN 0 +#define NAME_TYPE_LDAP_DN 1 +#define NAME_TYPE_DCE_DN 2 + +static char **explode_name( const char *name, int notypes, int is_type ); char * ldap_get_dn( LDAP *ld, LDAPMessage *entry ) @@ -36,7 +43,7 @@ ldap_get_dn( LDAP *ld, LDAPMessage *entry ) } tmp = *entry->lm_ber; /* struct copy */ - if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) { + if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) { ld->ld_errno = LDAP_DECODING_ERROR; return( NULL ); } @@ -45,129 +52,162 @@ ldap_get_dn( LDAP *ld, LDAPMessage *entry ) } char * -ldap_dn2ufn( char *dn ) +ldap_dn2ufn( LDAP_CONST char *dn ) { - char *p, *ufn, *r; - int state; + char *ufn; + char **vals; Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 ); - if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL ) - return( strdup( dn )); + /* produces completely untyped UFNs */ - ufn = strdup( ++p ); + if( dn == NULL ) { + return NULL; + } -#define INQUOTE 1 -#define OUTQUOTE 2 - state = OUTQUOTE; - for ( p = ufn, r = ufn; *p; p++ ) { - switch ( *p ) { - case '\\': - if ( *++p == '\0' ) - p--; - else { - *r++ = '\\'; - *r++ = *p; - } - break; - case '"': - if ( state == INQUOTE ) - state = OUTQUOTE; - else - state = INQUOTE; - *r++ = *p; - break; - case ';': - case ',': - if ( state == OUTQUOTE ) - *r++ = ','; - else - *r++ = *p; - break; - case '=': - if ( state == INQUOTE ) - *r++ = *p; - else { - char *rsave = r; - - *r-- = '\0'; - while ( !isspace( *r ) && *r != ';' - && *r != ',' && r > ufn ) - r--; - r++; - - if ( strcasecmp( r, "c" ) - && strcasecmp( r, "o" ) - && strcasecmp( r, "ou" ) - && strcasecmp( r, "st" ) - && strcasecmp( r, "l" ) - && strcasecmp( r, "cn" ) ) { - r = rsave; - *r++ = '='; - } - } - break; - default: - *r++ = *p; - break; - } + vals = ldap_explode_dn( dn , 1 ); + if( vals == NULL ) { + return NULL; } - *r = '\0'; - return( ufn ); + ufn = ldap_charray2str( vals, ", " ); + + ldap_memvfree( vals ); + return ufn; } char ** -ldap_explode_dns( char *dn ) +ldap_explode_dn( LDAP_CONST char *dn, int notypes ) { - int ncomps, maxcomps; - char *s; - char **rdns; + Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 ); - if ( (rdns = (char **) malloc( 8 * sizeof(char *) )) == NULL ) { - return( NULL ); + return explode_name( dn, notypes, NAME_TYPE_LDAP_DN ); +} + +char ** +ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) +{ + Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 ); + return explode_name( rdn, notypes, NAME_TYPE_LDAP_RDN ); +} + +char * +ldap_dn2dcedn( LDAP_CONST char *dn ) +{ + char *dce, *q, **rdns, **p; + int len = 0; + + Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 ); + + rdns = explode_name( dn, 0, NAME_TYPE_LDAP_DN ); + if ( rdns == NULL ) { + return NULL; + } + + for ( p = rdns; *p != NULL; p++ ) { + len += strlen( *p ) + 1; } - maxcomps = 8; - ncomps = 0; - for ( s = strtok( dn, "@." ); s != NULL; s = strtok( NULL, "@." ) ) { - if ( ncomps == maxcomps ) { - maxcomps *= 2; - if ( (rdns = (char **) realloc( rdns, maxcomps * - sizeof(char *) )) == NULL ) { - return( NULL ); - } - } - rdns[ncomps++] = strdup( s ); + q = dce = LDAP_MALLOC( len + 1 ); + if ( dce == NULL ) { + return NULL; + } + + p--; /* get back past NULL */ + + for ( ; p != rdns; p-- ) { + strcpy( q, "/" ); + q++; + strcpy( q, *p ); + q += strlen( *p ); } - rdns[ncomps] = NULL; - return( rdns ); + strcpy( q, "/" ); + q++; + strcpy( q, *p ); + + return dce; } -char ** -ldap_explode_dn( char *dn, int notypes ) +char * +ldap_dcedn2dn( LDAP_CONST char *dce ) { - char *p, *q, *rdnstart, **rdns = NULL; - int state, count = 0, endquote, len; + char *dn, *q, **rdns, **p; + int len; - Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 ); + + rdns = explode_name( dce, 0, NAME_TYPE_DCE_DN ); + if ( rdns == NULL ) { + return NULL; + } + + len = 0; + + for ( p = rdns; *p != NULL; p++ ) { + len += strlen( *p ) + 1; + } + + q = dn = LDAP_MALLOC( len ); + if ( dn == NULL ) { + return NULL; + } - if ( ldap_is_dns_dn( dn ) ) { - return( ldap_explode_dns( dn ) ); + p--; + + for ( ; p != rdns; p-- ) { + strcpy( q, *p ); + q += strlen( *p ); + strcpy( q, "," ); + q++; + } + + if ( *dce == '/' ) { + /* the name was fully qualified, thus the most-significant + * RDN was empty. trash the last comma */ + q--; + *q = '\0'; + } else { + /* the name was relative. copy the most significant RDN */ + strcpy( q, *p ); } - rdnstart = dn; - p = dn-1; + return dn; +} + +#define INQUOTE 1 +#define OUTQUOTE 2 + +static char ** +explode_name( const char *name, int notypes, int is_type ) +{ + const char *p, *q, *rdn; + char **parts = NULL; + int offset, state, have_equals, count = 0, endquote, len; + + /* safe guard */ + if(name == NULL) name = ""; + + /* skip leading whitespace */ + while( ldap_utf8_isspace( name )) { + LDAP_UTF8_INCR( name ); + } + + p = rdn = name; + offset = 0; state = OUTQUOTE; + have_equals=0; do { + /* step forward */ + p += offset; + offset = 1; - ++p; switch ( *p ) { case '\\': - if ( *++p == '\0' ) - p--; + if ( p[1] != '\0' ) { + offset = LDAP_UTF8_OFFSET(++p); + } break; case '"': if ( state == INQUOTE ) @@ -175,47 +215,78 @@ ldap_explode_dn( char *dn, int notypes ) else state = INQUOTE; break; + case '=': + if( state == OUTQUOTE ) have_equals++; + break; + case '+': + if (is_type == NAME_TYPE_LDAP_RDN) + goto end_part; + break; + case '/': + if (is_type == NAME_TYPE_DCE_DN) + goto end_part; + break; case ';': case ',': + if (is_type == NAME_TYPE_LDAP_DN) + goto end_part; + break; case '\0': + end_part: if ( state == OUTQUOTE ) { ++count; - if ( rdns == NULL ) { - if (( rdns = (char **)malloc( 8 + have_equals=0; + + if ( parts == NULL ) { + if (( parts = (char **)LDAP_MALLOC( 8 * sizeof( char *))) == NULL ) return( NULL ); } else if ( count >= 8 ) { - if (( rdns = (char **)realloc( rdns, + if (( parts = (char **)LDAP_REALLOC( parts, (count+1) * sizeof( char *))) == NULL ) return( NULL ); } - rdns[ count ] = NULL; + + parts[ count ] = NULL; endquote = 0; + if ( notypes ) { - for ( q = rdnstart; - q < p && *q != '='; ++q ) { - ; + for ( q = rdn; q < p && *q != '='; ++q ) { + /* EMPTY */; } + if ( q < p ) { - rdnstart = ++q; + rdn = ++q; } - if ( *rdnstart == '"' ) { - ++rdnstart; + + if ( *rdn == '"' ) { + ++rdn; } - if ( *(p-1) == '"' ) { + if ( p[-1] == '"' ) { endquote = 1; --p; } } - len = p - rdnstart; - if (( rdns[ count-1 ] = (char *)calloc( 1, - len + 1 )) != NULL ) { - SAFEMEMCPY( rdns[ count-1 ], rdnstart, - len ); - rdns[ count-1 ][ len ] = '\0'; + len = p - rdn; + + if (( parts[ count-1 ] = (char *)LDAP_CALLOC( 1, + len + 1 )) != NULL ) + { + AC_MEMCPY( parts[ count-1 ], rdn, len ); + + if( !endquote ) { + /* skip trailing spaces */ + while( len > 0 && ldap_utf8_isspace( + &parts[count-1][len-1] ) ) + { + --len; + } + } + + parts[ count-1 ][ len ] = '\0'; } /* @@ -226,22 +297,12 @@ ldap_explode_dn( char *dn, int notypes ) if ( endquote == 1 ) p++; - rdnstart = *p ? p + 1 : p; - while ( isspace( *rdnstart )) - ++rdnstart; - } - break; + rdn = *p ? &p[1] : p; + while ( ldap_utf8_isspace( rdn ) ) + ++rdn; + } break; } } while ( *p ); - return( rdns ); + return( parts ); } - - -int -ldap_is_dns_dn( char *dn ) -{ - return( dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL && - strchr( dn, ',' ) == NULL ); -} -