X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fgetdn.c;h=d43287172576ff1174dffff2afaf20f26ebb5137;hb=3d39ff68a94e4455074707d763138f01aaa1c5b1;hp=5af3069c77bb02fcd42cc7893753300187d5e108;hpb=f80b4ad53e1b1655f37a957a4324898643ace725;p=openldap diff --git a/libraries/libldap/getdn.c b/libraries/libldap/getdn.c index 5af3069c77..d432871725 100644 --- a/libraries/libldap/getdn.c +++ b/libraries/libldap/getdn.c @@ -1,13 +1,19 @@ /* $OpenLDAP$ */ -/* - * Copyright 1998-2002 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. +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2007 The OpenLDAP Foundation. + * All rights reserved. * - * getdn.c + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* Portions Copyright (c) 1994 Regents of the University of Michigan. + * All rights reserved. */ #include "portable.h" @@ -25,19 +31,18 @@ /* extension to UFN that turns trailing "dc=value" rdns in DNS style, * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */ #define DC_IN_UFN -/* #define PRETTY_ESCAPE */ /* parsing/printing routines */ -static int str2strval( const char *str, struct berval *val, - const char **next, unsigned flags, unsigned *retFlags ); +static int str2strval( const char *str, ber_len_t stoplen, struct berval *val, + const char **next, unsigned flags, int *retFlags, void *ctx ); static int DCE2strval( const char *str, struct berval *val, - const char **next, unsigned flags ); + const char **next, unsigned flags, void *ctx ); static int IA52strval( const char *str, struct berval *val, - const char **next, unsigned flags ); + const char **next, unsigned flags, void *ctx ); static int quotedIA52strval( const char *str, struct berval *val, - const char **next, unsigned flags ); + const char **next, unsigned flags, void *ctx ); static int hexstr2binval( const char *str, struct berval *val, - const char **next, unsigned flags ); + const char **next, unsigned flags, void *ctx ); static int hexstr2bin( const char *str, char *c ); static int byte2hexpair( const char *val, char *pair ); static int binval2hexstr( struct berval *val, char *str ); @@ -57,23 +62,23 @@ static int strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len ); static int strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ); -static int dn2domain( LDAPDN *dn, struct berval *bv, int pos, int *iRDN ); +static int dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ); /* AVA helpers */ static LDAPAVA * ldapava_new( - const struct berval *attr, const struct berval *val, unsigned flags ); + const struct berval *attr, const struct berval *val, unsigned flags, void *ctx ); /* Higher level helpers */ -static int rdn2strlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len, +static int rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, int ( *s2l )( struct berval *, unsigned, ber_len_t * ) ); -static int rdn2str( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, +static int rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * )); -static int rdn2UFNstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ); -static int rdn2UFNstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len ); -static int rdn2DCEstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ); -static int rdn2DCEstr( LDAPRDN *rdn, char *str, unsigned flag, ber_len_t *len, int first ); -static int rdn2ADstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ); -static int rdn2ADstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ); +static int rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); +static int rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ); +static int rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); +static int rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flag, ber_len_t *len, int first ); +static int rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ); +static int rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ); /* * RFC 1823 ldap_get_dn @@ -86,10 +91,9 @@ ldap_get_dn( LDAP *ld, LDAPMessage *entry ) Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 ); - if ( entry == NULL ) { - ld->ld_errno = LDAP_PARAM_ERROR; - return( NULL ); - } + assert( ld != NULL ); + assert( LDAP_VALID(ld) ); + assert( entry != NULL ); tmp = *entry->lm_ber; /* struct copy */ if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) { @@ -100,6 +104,53 @@ ldap_get_dn( LDAP *ld, LDAPMessage *entry ) return( dn ); } +int +ldap_get_dn_ber( LDAP *ld, LDAPMessage *entry, BerElement **berout, + BerValue *dn ) +{ + BerElement tmp, *ber; + ber_len_t len = 0; + int rc = LDAP_SUCCESS; + + Debug( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n", 0, 0, 0 ); + + assert( ld != NULL ); + assert( LDAP_VALID(ld) ); + assert( entry != NULL ); + assert( dn != NULL ); + + dn->bv_val = NULL; + dn->bv_len = 0; + + if ( berout ) { + *berout = NULL; + ber = ldap_alloc_ber_with_options( ld ); + if( ber == NULL ) { + return LDAP_NO_MEMORY; + } + *berout = ber; + } else { + ber = &tmp; + } + + *ber = *entry->lm_ber; /* struct copy */ + if ( ber_scanf( ber, "{ml{" /*}*/, dn, &len ) == LBER_ERROR ) { + rc = ld->ld_errno = LDAP_DECODING_ERROR; + } + if ( rc == LDAP_SUCCESS ) { + /* set the length to avoid overrun */ + rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len ); + if( rc != LBER_OPT_SUCCESS ) { + rc = ld->ld_errno = LDAP_LOCAL_ERROR; + } + } + if ( rc != LDAP_SUCCESS && berout ) { + ber_free( ber, 0 ); + *berout = NULL; + } + return rc; +} + /* * RFC 1823 ldap_dn2ufn */ @@ -122,7 +173,7 @@ ldap_dn2ufn( LDAP_CONST char *dn ) char ** ldap_explode_dn( LDAP_CONST char *dn, int notypes ) { - LDAPDN *tmpDN; + LDAPDN tmpDN; char **values = NULL; int iRDN; unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3; @@ -142,7 +193,7 @@ ldap_explode_dn( LDAP_CONST char *dn, int notypes ) return values; } - for ( iRDN = 0; tmpDN[ 0 ][ iRDN ]; iRDN++ ); + for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ); values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iRDN ) ); if ( values == NULL ) { @@ -150,8 +201,8 @@ ldap_explode_dn( LDAP_CONST char *dn, int notypes ) return NULL; } - for ( iRDN = 0; tmpDN[ 0 ][ iRDN ]; iRDN++ ) { - ldap_rdn2str( tmpDN[ 0 ][ iRDN ], &values[ iRDN ], flag ); + for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) { + ldap_rdn2str( tmpDN[ iRDN ], &values[ iRDN ], flag ); } ldap_dnfree( tmpDN ); values[ iRDN ] = NULL; @@ -162,7 +213,7 @@ ldap_explode_dn( LDAP_CONST char *dn, int notypes ) char ** ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) { - LDAPRDN *tmpRDN; + LDAPRDN tmpRDN; char **values = NULL; const char *p; int iAVA; @@ -179,19 +230,19 @@ ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) return( NULL ); } - for ( iAVA = 0; tmpRDN[ 0 ][ iAVA ]; iAVA++ ) ; + for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) ; values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iAVA ) ); if ( values == NULL ) { ldap_rdnfree( tmpRDN ); return( NULL ); } - for ( iAVA = 0; tmpRDN[ 0 ][ iAVA ]; iAVA++ ) { + for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) { ber_len_t l = 0, vl, al = 0; char *str; - LDAPAVA *ava = tmpRDN[ 0 ][ iAVA ]; + LDAPAVA *ava = tmpRDN[ iAVA ]; - if ( ava->la_flags == LDAP_AVA_BINARY ) { + if ( ava->la_flags & LDAP_AVA_BINARY ) { vl = 1 + 2 * ava->la_value.bv_len; } else { @@ -215,7 +266,7 @@ ldap_explode_rdn( LDAP_CONST char *rdn, int notypes ) str = LDAP_MALLOC( l + 1 ); } - if ( ava->la_flags == LDAP_AVA_BINARY ) { + if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ al++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ al ] ) ) { goto error_return; @@ -286,16 +337,15 @@ ldap_dn2ad_canonical( LDAP_CONST char *dn ) * from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK ) * * fin can be one of: - * LDAP_DN_FORMAT_LDAP (rfc 2253 and ldapbis liberal, - * plus some rfc 1779) - * LDAP_DN_FORMAT_LDAPV3 (rfc 2253 and ldapbis) - * LDAP_DN_FORMAT_LDAPV2 (rfc 1779) + * LDAP_DN_FORMAT_LDAP (RFC 4514 liberal, plus some RFC 1779) + * LDAP_DN_FORMAT_LDAPV3 (RFC 4514) + * LDAP_DN_FORMAT_LDAPV2 (RFC 1779) * LDAP_DN_FORMAT_DCE (?) * * fout can be any of the above except * LDAP_DN_FORMAT_LDAP * plus: - * LDAP_DN_FORMAT_UFN (rfc 1781, partial and with extensions) + * LDAP_DN_FORMAT_UFN (RFC 1781, partial and with extensions) * LDAP_DN_FORMAT_AD_CANONICAL (?) */ int @@ -303,11 +353,11 @@ ldap_dn_normalize( LDAP_CONST char *dnin, unsigned fin, char **dnout, unsigned fout ) { int rc; - LDAPDN *tmpDN = NULL; + LDAPDN tmpDN = NULL; Debug( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n", 0, 0, 0 ); - assert( dnout ); + assert( dnout != NULL ); *dnout = NULL; @@ -381,13 +431,28 @@ ldap_dn_normalize( LDAP_CONST char *dnin, #define LDAP_DN_ESCAPE(c) ( (c) == '\\' ) #define LDAP_DN_VALUE_END(c) \ ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) ) + +/* NOTE: according to RFC 4514, '=' can be escaped and treated as special, + * i.e. escaped both as "\" and * as "\=", but it is treated as + * a regular char, i.e. it can also appear as '='. + * + * As such, in 2.2 we used to allow reading unescaped '=', but we always + * produced escaped '\3D'; this changes since 2.3, if compatibility issues + * do not arise + */ #define LDAP_DN_NE(c) \ ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \ - || LDAP_DN_QUOTES(c) || (c) == '<' || (c) == '>' ) + || LDAP_DN_QUOTES(c) \ + || (c) == '<' || (c) == '>' ) +#define LDAP_DN_MAYESCAPE(c) \ + ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \ + || LDAP_DN_AVA_EQUALS(c) \ + || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) ) +#define LDAP_DN_SHOULDESCAPE(c) ( LDAP_DN_AVA_EQUALS(c) ) + #define LDAP_DN_NEEDESCAPE(c) \ ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) ) -#define LDAP_DN_NEEDESCAPE_LEAD(c) \ - ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) || LDAP_DN_NE(c) ) +#define LDAP_DN_NEEDESCAPE_LEAD(c) LDAP_DN_MAYESCAPE(c) #define LDAP_DN_NEEDESCAPE_TRAIL(c) \ ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) ) #define LDAP_DN_WILLESCAPE_CHAR(c) \ @@ -458,13 +523,13 @@ ldap_dn_normalize( LDAP_CONST char *dnin, #define LDAP_DC_ATTR "dc" #define LDAP_DC_ATTRU "DC" #define LDAP_DN_IS_RDN_DC( r ) \ - ( (r) && (r)[0][0] && !(r)[0][1] \ - && ((r)[0][0]->la_flags == LDAP_AVA_STRING) \ - && ((r)[0][0]->la_attr.bv_len == 2) \ - && (((r)[0][0]->la_attr.bv_val[0] == LDAP_DC_ATTR[0]) \ - || ((r)[0][0]->la_attr.bv_val[0] == LDAP_DC_ATTRU[0])) \ - && (((r)[0][0]->la_attr.bv_val[1] == LDAP_DC_ATTR[1]) \ - || ((r)[0][0]->la_attr.bv_val[1] == LDAP_DC_ATTRU[1]))) + ( (r) && (r)[0] && !(r)[1] \ + && ((r)[0]->la_flags & LDAP_AVA_STRING) \ + && ((r)[0]->la_attr.bv_len == 2) \ + && (((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTR[0]) \ + || ((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTRU[0])) \ + && (((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTR[1]) \ + || ((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTRU[1]))) /* Composite rules */ #define LDAP_DN_ALLOW_ONE_SPACE(f) \ @@ -491,39 +556,36 @@ ldap_dn_normalize( LDAP_CONST char *dnin, * LDAPAVA helpers (will become part of the API for operations * on structural representations of DNs). */ -LDAPAVA * +static LDAPAVA * ldapava_new( const struct berval *attr, const struct berval *val, - unsigned flags ) + unsigned flags, void *ctx ) { - LDAPAVA *ava; + LDAPAVA *ava; - assert( attr ); - assert( val ); + assert( attr != NULL ); + assert( val != NULL ); - ava = LDAP_MALLOC( sizeof( LDAPAVA ) + attr->bv_len + 1 ); - - /* should we test it? */ - if ( ava == NULL ) { - return( NULL ); - } + ava = LDAP_MALLOCX( sizeof( LDAPAVA ) + attr->bv_len + 1, ctx ); - ava->la_attr.bv_len = attr->bv_len; - ava->la_attr.bv_val = (char *)(ava+1); - AC_MEMCPY( ava->la_attr.bv_val, attr->bv_val, attr->bv_len ); - ava->la_attr.bv_val[attr->bv_len] = '\0'; + if ( ava ) { + ava->la_attr.bv_len = attr->bv_len; + ava->la_attr.bv_val = (char *)(ava+1); + AC_MEMCPY( ava->la_attr.bv_val, attr->bv_val, attr->bv_len ); + ava->la_attr.bv_val[attr->bv_len] = '\0'; - ava->la_value = *val; - ava->la_flags = flags; + ava->la_value = *val; + ava->la_flags = flags | LDAP_AVA_FREE_VALUE; - ava->la_private = NULL; + ava->la_private = NULL; + } return( ava ); } void -ldap_avafree( LDAPAVA *ava ) +ldapava_free( LDAPAVA *ava, void *ctx ) { - assert( ava ); + assert( ava != NULL ); #if 0 /* ava's private must be freed by caller @@ -532,17 +594,20 @@ ldap_avafree( LDAPAVA *ava ) assert( ava->la_private == NULL ); #endif -#if 0 - /* la_attr is now contiguous with ava, not freed separately */ - LDAP_FREE( ava->la_attr.bv_val ); -#endif - LDAP_FREE( ava->la_value.bv_val ); + if (ava->la_flags & LDAP_AVA_FREE_VALUE) + LDAP_FREEX( ava->la_value.bv_val, ctx ); - LDAP_FREE( ava ); + LDAP_FREEX( ava, ctx ); } void -ldap_rdnfree( LDAPRDN *rdn ) +ldap_rdnfree( LDAPRDN rdn ) +{ + ldap_rdnfree_x( rdn, NULL ); +} + +void +ldap_rdnfree_x( LDAPRDN rdn, void *ctx ) { int iAVA; @@ -550,15 +615,21 @@ ldap_rdnfree( LDAPRDN *rdn ) return; } - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - ldap_avafree( rdn[ 0 ][ iAVA ] ); + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + ldapava_free( rdn[ iAVA ], ctx ); } - LDAP_FREE( rdn ); + LDAP_FREEX( rdn, ctx ); } void -ldap_dnfree( LDAPDN *dn ) +ldap_dnfree( LDAPDN dn ) +{ + ldap_dnfree_x( dn, NULL ); +} + +void +ldap_dnfree_x( LDAPDN dn, void *ctx ) { int iRDN; @@ -566,11 +637,11 @@ ldap_dnfree( LDAPDN *dn ) return; } - for ( iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) { - ldap_rdnfree( dn[ 0 ][ iRDN ] ); + for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { + ldap_rdnfree_x( dn[ iRDN ], ctx ); } - LDAP_FREE( dn ); + LDAP_FREEX( dn, ctx ); } /* @@ -587,32 +658,79 @@ ldap_dnfree( LDAPDN *dn ) * and readable as soon as it works as expected. */ -#define TMP_SLOTS 1024 +/* + * Default sizes of AVA and RDN static working arrays; if required + * the are dynamically resized. The values can be tuned in case + * of special requirements (e.g. very deep DN trees or high number + * of AVAs per RDN). + */ +#define TMP_AVA_SLOTS 8 +#define TMP_RDN_SLOTS 32 + +int +ldap_str2dn( LDAP_CONST char *str, LDAPDN *dn, unsigned flags ) +{ + struct berval bv; + + assert( str != NULL ); + + bv.bv_len = strlen( str ); + bv.bv_val = (char *) str; + + return ldap_bv2dn_x( &bv, dn, flags, NULL ); +} int -ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags ) +ldap_bv2dn( struct berval *bv, LDAPDN *dn, unsigned flags ) +{ + return ldap_bv2dn_x( bv, dn, flags, NULL ); +} + +int +ldap_bv2dn_x( struct berval *bvin, LDAPDN *dn, unsigned flags, void *ctx ) { const char *p; int rc = LDAP_DECODING_ERROR; int nrdns = 0; - LDAPDN *newDN = NULL; - LDAPRDN *newRDN = NULL, *tmpDN[TMP_SLOTS]; + LDAPDN newDN = NULL; + LDAPRDN newRDN = NULL, tmpDN_[TMP_RDN_SLOTS], *tmpDN = tmpDN_; + int num_slots = TMP_RDN_SLOTS; + char *str, *end; + struct berval bvtmp, *bv = &bvtmp; - assert( str ); - assert( dn ); + assert( bvin != NULL ); + assert( bvin->bv_val != NULL ); + assert( dn != NULL ); + + *bv = *bvin; + str = bv->bv_val; + end = str + bv->bv_len; - Debug( LDAP_DEBUG_TRACE, "=> ldap_str2dn(%s,%u)\n%s", str, flags, "" ); + Debug( LDAP_DEBUG_ARGS, "=> ldap_bv2dn(%s,%u)\n", str, flags, 0 ); *dn = NULL; switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV3: - case LDAP_DN_FORMAT_LDAPV2: case LDAP_DN_FORMAT_DCE: break; + /* allow DN enclosed in brackets */ + case LDAP_DN_FORMAT_LDAPV2: + if ( str[0] == '<' ) { + if ( bv->bv_len < 2 || end[ -1 ] != '>' ) { + rc = LDAP_DECODING_ERROR; + goto parsing_error; + } + bv->bv_val++; + bv->bv_len -= 2; + str++; + end--; + } + break; + /* unsupported in str2dn */ case LDAP_DN_FORMAT_UFN: case LDAP_DN_FORMAT_AD_CANONICAL: @@ -623,10 +741,15 @@ ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags ) return LDAP_PARAM_ERROR; } - if ( str[ 0 ] == '\0' ) { + if ( bv->bv_len == 0 ) { return LDAP_SUCCESS; } + if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { + /* value must have embedded NULs */ + return LDAP_DECODING_ERROR; + } + p = str; if ( LDAP_DN_DCE( flags ) ) { @@ -638,7 +761,12 @@ ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags ) goto parsing_error; } p++; - + + /* + * actually we do not want to accept by default the DCE form, + * we do not want to auto-detect it + */ +#if 0 } else if ( LDAP_DN_LDAP( flags ) ) { /* * if dn starts with '/' let's make it a DCE dn @@ -647,12 +775,16 @@ ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags ) flags |= LDAP_DN_FORMAT_DCE; p++; } +#endif } - for ( ; p[ 0 ]; p++ ) { + for ( ; p < end; p++ ) { int err; + struct berval tmpbv; + tmpbv.bv_len = bv->bv_len - ( p - str ); + tmpbv.bv_val = (char *)p; - err = ldap_str2rdn( p, &newRDN, (char **) &p, flags ); + err = ldap_bv2rdn_x( &tmpbv, &newRDN, (char **) &p, flags,ctx); if ( err != LDAP_SUCCESS ) { goto parsing_error; } @@ -660,7 +792,7 @@ ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags ) /* * We expect a rdn separator */ - if ( p[ 0 ] ) { + if ( p < end && p[ 0 ] ) { switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: if ( !LDAP_DN_RDN_SEP( p[ 0 ] ) ) { @@ -690,44 +822,52 @@ ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags ) tmpDN[nrdns++] = newRDN; newRDN = NULL; -#if 0 - /* - * prone to attacks? - */ - assert (nrdns < TMP_SLOTS); -#else /* - * make the static AVA array dynamically rescalable + * make the static RDN array dynamically rescalable */ - if (nrdns >= TMP_SLOTS) { - rc = LDAP_DECODING_ERROR; - goto parsing_error; + if ( nrdns == num_slots ) { + LDAPRDN *tmp; + + if ( tmpDN == tmpDN_ ) { + tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPRDN * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) ); + + } else { + tmp = LDAP_REALLOCX( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + } + + tmpDN = tmp; + num_slots *= 2; } -#endif - if ( p[ 0 ] == '\0' ) { + if ( p >= end || p[ 0 ] == '\0' ) { /* * the DN is over, phew */ - newDN = (LDAPDN *)LDAP_MALLOC( sizeof(LDAPDN) + - sizeof(LDAPRDN *) * (nrdns+1)); + newDN = (LDAPDN)LDAP_MALLOCX( sizeof(LDAPRDN *) * (nrdns+1), ctx ); if ( newDN == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } else { int i; - newDN[0] = (LDAPRDN **)(newDN+1); - if ( LDAP_DN_DCE( flags ) ) { /* add in reversed order */ for ( i=0; i=0; nrdns-- ) - ldap_rdnfree( tmpDN[nrdns] ); + for ( nrdns-- ;nrdns >= 0; nrdns-- ) { + ldap_rdnfree_x( tmpDN[nrdns], ctx ); + } return_result:; - Debug( LDAP_DEBUG_TRACE, "<= ldap_str2dn(%s,%u)=%d\n", str, flags, rc ); + + if ( tmpDN != tmpDN_ ) { + LDAP_FREEX( tmpDN, ctx ); + } + + Debug( LDAP_DEBUG_ARGS, "<= ldap_bv2dn(%s)=%d %s\n", str, rc, + rc ? ldap_err2string( rc ) : "" ); *dn = newDN; return( rc ); @@ -758,10 +905,32 @@ return_result:; * corresponds to the rdn separator or to '\0' in case the string is over. */ int -ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, +ldap_str2rdn( LDAP_CONST char *str, LDAPRDN *rdn, + char **n_in, unsigned flags ) +{ + struct berval bv; + + assert( str != NULL ); + assert( str[ 0 ] != '\0' ); /* FIXME: is this required? */ + + bv.bv_len = strlen( str ); + bv.bv_val = (char *) str; + + return ldap_bv2rdn_x( &bv, rdn, n_in, flags, NULL ); +} + +int +ldap_bv2rdn( struct berval *bv, LDAPRDN *rdn, char **n_in, unsigned flags ) { - const char **n = (const char **) n_in; + return ldap_bv2rdn_x( bv, rdn, n_in, flags, NULL ); +} + +int +ldap_bv2rdn_x( struct berval *bv, LDAPRDN *rdn, + char **n_in, unsigned flags, void *ctx ) +{ + const char **n = (const char **) n_in; const char *p; int navas = 0; int state = B4AVA; @@ -769,17 +938,24 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, int attrTypeEncoding = LDAP_AVA_STRING, attrValueEncoding = LDAP_AVA_STRING; - struct berval attrType = { 0, NULL }; - struct berval attrValue = { 0, NULL }; + struct berval attrType = BER_BVNULL; + struct berval attrValue = BER_BVNULL; + + LDAPRDN newRDN = NULL; + LDAPAVA *tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_; + int num_slots = TMP_AVA_SLOTS; - LDAPRDN *newRDN = NULL; - LDAPAVA *tmpRDN[TMP_SLOTS]; + char *str; + ber_len_t stoplen; - assert( str ); + assert( bv != NULL ); + assert( bv->bv_len != 0 ); + assert( bv->bv_val != NULL ); assert( rdn || flags & LDAP_DN_SKIP ); - assert( n ); + assert( n != NULL ); - Debug( LDAP_DEBUG_TRACE, "=> ldap_str2rdn(%s,%u)\n%s", str, flags, "" ); + str = bv->bv_val; + stoplen = bv->bv_len; if ( rdn ) { *rdn = NULL; @@ -803,8 +979,14 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, return LDAP_PARAM_ERROR; } - if ( str[ 0 ] == '\0' ) { + if ( bv->bv_len == 0 ) { return LDAP_SUCCESS; + + } + + if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) { + /* value must have embedded NULs */ + return LDAP_DECODING_ERROR; } p = str; @@ -820,15 +1002,8 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, * an AttributeType can be encoded as: * - its string representation; in detail, implementations * MUST recognize AttributeType string type names listed - * in section 2.3 of draft-ietf-ldapbis-dn-XX.txt, and - * MAY recognize other names. - * - its numeric OID (a dotted decimal string); in detail - * RFC 2253 asserts that ``Implementations MUST allow - * an oid in the attribute type to be prefixed by one - * of the character strings "oid." or "OID."''. As soon - * as draft-ietf-ldapbis-dn-XX.txt obsoletes RFC 2253 - * I'm not sure whether this is required or not any - * longer; to be liberal, we still implement it. + * in Section 3 of RFC 4514, and MAY recognize other names. + * - its numeric OID (a dotted decimal string) */ case B4AVA: if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) { @@ -928,9 +1103,8 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) { /* - * RFC 2253 does not explicitly - * allow lang extensions to attribute - * types in DNs ... + * RFC 4514 explicitly does not allow attribute + * description options, such as language tags. */ if ( flags & LDAP_DN_PEDANTIC ) { goto parsing_error; @@ -1050,7 +1224,7 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, } /* - * here STRING means RFC 2253 string + * here STRING means RFC 4514 string * FIXME: what about DCE strings? */ if ( !p[ 0 ] ) { @@ -1062,7 +1236,7 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, break; case B4BINARYVALUE: - if ( hexstr2binval( p, &attrValue, &p, flags ) ) { + if ( hexstr2binval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } @@ -1073,14 +1247,15 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAP: case LDAP_DN_FORMAT_LDAPV3: - if ( str2strval( p, &attrValue, &p, flags, - &attrValueEncoding ) ) { + if ( str2strval( p, stoplen - ( p - str ), + &attrValue, &p, flags, + &attrValueEncoding, ctx ) ) { goto parsing_error; } break; case LDAP_DN_FORMAT_DCE: - if ( DCE2strval( p, &attrValue, &p, flags ) ) { + if ( DCE2strval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } break; @@ -1093,7 +1268,7 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, break; case B4IA5VALUE: - if ( IA52strval( p, &attrValue, &p, flags ) ) { + if ( IA52strval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } @@ -1104,7 +1279,7 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, /* lead quote already stripped */ if ( quotedIA52strval( p, &attrValue, - &p, flags ) ) { + &p, flags, ctx ) ) { goto parsing_error; } @@ -1121,8 +1296,7 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, * we accept empty values */ ava = ldapava_new( &attrType, &attrValue, - attrValueEncoding ); - + attrValueEncoding, ctx ); if ( ava == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; @@ -1132,7 +1306,31 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, attrValue.bv_val = NULL; attrValue.bv_len = 0; - assert(navas < TMP_SLOTS); + /* + * prepare room for new AVAs if needed + */ + if (navas == num_slots) { + LDAPAVA **tmp; + + if ( tmpRDN == tmpRDN_ ) { + tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPAVA * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) ); + + } else { + tmp = LDAP_REALLOCX( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ), ctx ); + if ( tmp == NULL ) { + rc = LDAP_NO_MEMORY; + goto parsing_error; + } + } + + tmpRDN = tmp; + num_slots *= 2; + } } /* @@ -1162,19 +1360,14 @@ ldap_str2rdn( LDAP_CONST char *str, LDAPRDN **rdn, */ *n = p; if ( !( flags & LDAP_DN_SKIP ) ) { - newRDN = (LDAPRDN *)LDAP_MALLOC( sizeof(LDAPRDN) - + sizeof(LDAPAVA *) * (navas+1) ); + newRDN = (LDAPRDN)LDAP_MALLOCX( + sizeof(LDAPAVA) * (navas+1), ctx ); if ( newRDN == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; } else { - int i; - - newRDN[0] = (LDAPAVA**)(newRDN+1); - - for (i=0; i=0; navas-- ) - ldap_avafree( tmpRDN[navas] ); + for ( navas-- ; navas >= 0; navas-- ) { + ldapava_free( tmpRDN[navas], ctx ); + } return_result:; - Debug( LDAP_DEBUG_TRACE, "<= ldap_str2rdn(%*s)=%d\n", - p - str, str, rc ); + if ( tmpRDN != tmpRDN_ ) { + LDAP_FREEX( tmpRDN, ctx ); + } + if ( rdn ) { *rdn = newRDN; } @@ -1225,26 +1421,24 @@ return_result:; * '\' + HEXPAIR(p) -> unhex(p) */ static int -str2strval( const char *str, struct berval *val, const char **next, unsigned flags, unsigned *retFlags ) +str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char **next, unsigned flags, int *retFlags, void *ctx ) { - const char *p, *startPos, *endPos = NULL; - ber_len_t len, escapes, unescapes; + const char *p, *end, *startPos, *endPos = NULL; + ber_len_t len, escapes; - assert( str ); - assert( val ); - assert( next ); + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); *next = NULL; - - for ( startPos = p = str, escapes = 0, unescapes = 0; p[ 0 ]; p++ ) { + end = str + stoplen; + for ( startPos = p = str, escapes = 0; p < end; p++ ) { if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) { p++; if ( p[ 0 ] == '\0' ) { return( 1 ); } - if ( ( p == startPos + 1 && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) - || ( LDAP_DN_VALUE_END( p[ 1 ] ) && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) - || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) { + if ( LDAP_DN_MAYESCAPE( p[ 0 ] ) ) { escapes++; continue; } @@ -1271,16 +1465,17 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla return( 1 ); } /* - * FIXME: we allow escaping + * we do not allow escaping * of chars that don't need * to and do not belong to - * HEXDIGITS (we also allow - * single hexdigit; maybe we - * shouldn't). + * HEXDIGITS */ - unescapes++; + return( 1 ); - } else if (!LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) { + } else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) { + if ( p[ 0 ] == '\0' ) { + return( 1 ); + } *retFlags = LDAP_AVA_NONPRINTABLE; } else if ( ( LDAP_DN_LDAP( flags ) && LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) @@ -1324,22 +1519,26 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla /* * FIXME: test memory? */ - len = ( endPos ? endPos : p ) - startPos - escapes - unescapes; + len = ( endPos ? endPos : p ) - startPos - escapes; val->bv_len = len; - if ( escapes == 0 && unescapes == 0 ) { - val->bv_val = LDAP_STRNDUP( startPos, len ); + if ( escapes == 0 ) { + if ( *retFlags & LDAP_AVA_NONPRINTABLE ) { + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); + AC_MEMCPY( val->bv_val, startPos, len ); + val->bv_val[ len ] = '\0'; + } else { + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); + } } else { ber_len_t s, d; - val->bv_val = LDAP_MALLOC( len + 1 ); + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); for ( s = 0, d = 0; d < len; ) { if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { s++; - if ( ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( startPos[ s ] ) ) - || ( s == len - 1 && LDAP_DN_NEEDESCAPE_TRAIL( startPos[ s ] ) ) - || LDAP_DN_NEEDESCAPE( startPos[ s ] ) ) { + if ( LDAP_DN_MAYESCAPE( startPos[ s ] ) ) { val->bv_val[ d++ ] = startPos[ s++ ]; @@ -1351,12 +1550,8 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla s += 2; } else { - /* - * we allow escaping of chars - * that do not need to - */ - val->bv_val[ d++ ] = - startPos[ s++ ]; + /* we should never get here */ + assert( 0 ); } } else { @@ -1365,21 +1560,21 @@ str2strval( const char *str, struct berval *val, const char **next, unsigned fla } val->bv_val[ d ] = '\0'; - assert( strlen( val->bv_val ) == len ); + assert( d == len ); } return( 0 ); } static int -DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags ) +DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len, escapes; - assert( str ); - assert( val ); - assert( next ); + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); *next = NULL; @@ -1431,12 +1626,12 @@ DCE2strval( const char *str, struct berval *val, const char **next, unsigned fla len = ( endPos ? endPos : p ) - startPos - escapes; val->bv_len = len; if ( escapes == 0 ){ - val->bv_val = LDAP_STRNDUP( startPos, len ); + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); } else { ber_len_t s, d; - val->bv_val = LDAP_MALLOC( len + 1 ); + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); for ( s = 0, d = 0; d < len; ) { /* * This point is reached only if escapes @@ -1457,14 +1652,14 @@ DCE2strval( const char *str, struct berval *val, const char **next, unsigned fla } static int -IA52strval( const char *str, struct berval *val, const char **next, unsigned flags ) +IA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len, escapes; - assert( str ); - assert( val ); - assert( next ); + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); *next = NULL; @@ -1512,12 +1707,12 @@ IA52strval( const char *str, struct berval *val, const char **next, unsigned fla len = ( endPos ? endPos : p ) - startPos - escapes; val->bv_len = len; if ( escapes == 0 ) { - val->bv_val = LDAP_STRNDUP( startPos, len ); + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); } else { ber_len_t s, d; - val->bv_val = LDAP_MALLOC( len + 1 ); + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); for ( s = 0, d = 0; d < len; ) { if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) { s++; @@ -1532,15 +1727,15 @@ IA52strval( const char *str, struct berval *val, const char **next, unsigned fla } static int -quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags ) +quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len; unsigned escapes = 0; - assert( str ); - assert( val ); - assert( next ); + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); *next = NULL; @@ -1599,15 +1794,15 @@ quotedIA52strval( const char *str, struct berval *val, const char **next, unsign } len = endPos - startPos - escapes; - assert( len >= 0 ); + assert( endPos >= startPos + escapes ); val->bv_len = len; if ( escapes == 0 ) { - val->bv_val = LDAP_STRNDUP( startPos, len ); + val->bv_val = LDAP_STRNDUPX( startPos, len, ctx ); } else { ber_len_t s, d; - val->bv_val = LDAP_MALLOC( len + 1 ); + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); val->bv_len = len; for ( s = d = 0; d < len; ) { @@ -1628,8 +1823,8 @@ hexstr2bin( const char *str, char *c ) { char c1, c2; - assert( str ); - assert( c ); + assert( str != NULL ); + assert( c != NULL ); c1 = str[ 0 ]; c2 = str[ 1 ]; @@ -1664,15 +1859,15 @@ hexstr2bin( const char *str, char *c ) } static int -hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags ) +hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx ) { const char *p, *startPos, *endPos = NULL; ber_len_t len; ber_len_t s, d; - assert( str ); - assert( val ); - assert( next ); + assert( str != NULL ); + assert( val != NULL ); + assert( next != NULL ); *next = NULL; @@ -1746,7 +1941,7 @@ end_of_value:; assert( 2 * len == (ber_len_t) (( endPos ? endPos : p ) - startPos )); val->bv_len = len; - val->bv_val = LDAP_MALLOC( len + 1 ); + val->bv_val = LDAP_MALLOCX( len + 1, ctx ); if ( val->bv_val == NULL ) { return( LDAP_NO_MEMORY ); } @@ -1772,8 +1967,8 @@ byte2hexpair( const char *val, char *pair ) { static const char hexdig[] = "0123456789ABCDEF"; - assert( val ); - assert( pair ); + assert( val != NULL ); + assert( pair != NULL ); /* * we assume the string has enough room for the hex encoding @@ -1794,8 +1989,8 @@ binval2hexstr( struct berval *val, char *str ) { ber_len_t s, d; - assert( val ); - assert( str ); + assert( val != NULL ); + assert( str != NULL ); if ( val->bv_len == 0 ) { return( 0 ); @@ -1821,22 +2016,33 @@ static int strval2strlen( struct berval *val, unsigned flags, ber_len_t *len ) { ber_len_t l, cl = 1; - char *p; + char *p, *end; int escaped_byte_len = LDAP_DN_IS_PRETTY( flags ) ? 1 : 3; #ifdef PRETTY_ESCAPE int escaped_ascii_len = LDAP_DN_IS_PRETTY( flags ) ? 2 : 3; #endif /* PRETTY_ESCAPE */ - assert( val ); - assert( len ); + assert( val != NULL ); + assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { return( 0 ); } - for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) { - cl = LDAP_UTF8_CHARLEN( p ); + end = val->bv_val + val->bv_len - 1; + for ( l = 0, p = val->bv_val; p <= end; p += cl ) { + + /* + * escape '%x00' + */ + if ( p[ 0 ] == '\0' ) { + cl = 1; + l += 3; + continue; + } + + cl = LDAP_UTF8_CHARLEN2( p, cl ); if ( cl == 0 ) { /* illegal utf-8 char! */ return( -1 ); @@ -1845,17 +2051,22 @@ strval2strlen( struct berval *val, unsigned flags, ber_len_t *len ) ber_len_t cnt; for ( cnt = 1; cnt < cl; cnt++ ) { - if ( ( p[ cnt ] & 0x80 ) == 0x00 ) { + if ( ( p[ cnt ] & 0xc0 ) != 0x80 ) { return( -1 ); } } l += escaped_byte_len * cl; } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) + || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) - || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { + || ( p == end && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { #ifdef PRETTY_ESCAPE +#if 0 if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) { +#else + if ( LDAP_DN_WILLESCAPE_CHAR( p[ 0 ] ) ) { +#endif /* * there might be some chars we want @@ -1890,9 +2101,9 @@ strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { ber_len_t s, d, end; - assert( val ); - assert( str ); - assert( len ); + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; @@ -1904,7 +2115,26 @@ strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) * of the value */ for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { - ber_len_t cl = LDAP_UTF8_CHARLEN( &val->bv_val[ s ] ); + ber_len_t cl; + + /* + * escape '%x00' + */ + if ( val->bv_val[ s ] == '\0' ) { + cl = 1; + str[ d++ ] = '\\'; + str[ d++ ] = '0'; + str[ d++ ] = '0'; + s++; + continue; + } + + /* + * The length was checked in strval2strlen(); + * LDAP_UTF8_CHARLEN() should suffice + */ + cl = LDAP_UTF8_CHARLEN2( &val->bv_val[ s ], cl ); + assert( cl > 0 ); /* * there might be some chars we want to escape in form @@ -1912,9 +2142,14 @@ strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) */ if ( ( cl > 1 && !LDAP_DN_IS_PRETTY( flags ) ) #ifdef PRETTY_ESCAPE +#if 0 || LDAP_DN_WILLESCAPE_HEX( flags, val->bv_val[ s ] ) +#else + || LDAP_DN_WILLESCAPE_CHAR( val->bv_val[ s ] ) +#endif #else /* ! PRETTY_ESCAPE */ || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) + || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) @@ -1935,6 +2170,7 @@ strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) } else { #ifdef PRETTY_ESCAPE if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) + || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { str[ d++ ] = '\\'; @@ -1964,8 +2200,8 @@ strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len ) ber_len_t l; char *p; - assert( val ); - assert( len ); + assert( val != NULL ); + assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { @@ -1981,6 +2217,7 @@ strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len ) } else { for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) + || LDAP_DN_SHOULDESCAPE( p[ 0 ] ) || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) ) || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) { l += 2; @@ -2005,9 +2242,9 @@ strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { ber_len_t s, d, end; - assert( val ); - assert( str ); - assert( len ); + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; @@ -2029,6 +2266,7 @@ strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) { if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) + || LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] ) || ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) ) || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) { str[ d++ ] = '\\'; @@ -2052,8 +2290,8 @@ strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len ) ber_len_t l; char *p; - assert( val ); - assert( len ); + assert( val != NULL ); + assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { @@ -2092,9 +2330,9 @@ strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { ber_len_t s, d; - assert( val ); - assert( str ); - assert( len ); + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; @@ -2130,81 +2368,71 @@ strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) /* * Length of the (supposedly) AD canonical string representation, - * accounting for escaped hex of UTF-8 chars + * accounting for chars that need to be escaped */ static int strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len ) { - ber_len_t l; + ber_len_t l, cl; char *p; - assert( val ); - assert( len ); + assert( val != NULL ); + assert( len != NULL ); *len = 0; if ( val->bv_len == 0 ) { return( 0 ); } - if ( flags & LDAP_AVA_NONPRINTABLE ) { - /* - * FIXME: Turn the value into a binary encoded BER? - */ - return( -1 ); - - } else { - for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) { - if ( LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) { - l += 2; - - } else { - l++; - } + for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) { + cl = LDAP_UTF8_CHARLEN2( p, cl ); + if ( cl == 0 ) { + /* illegal utf-8 char */ + return -1; + } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) { + l += 2; + } else { + l += cl; } } *len = l; - + return( 0 ); } /* - * convert to (supposedly) AD string representation, - * escaping with hex the UTF-8 stuff; + * convert to (supposedly) AD string representation, * assume the destination has enough room for escaping */ static int strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) { - ber_len_t s, d; + ber_len_t s, d, cl; - assert( val ); - assert( str ); - assert( len ); + assert( val != NULL ); + assert( str != NULL ); + assert( len != NULL ); if ( val->bv_len == 0 ) { *len = 0; return( 0 ); } - if ( flags & LDAP_AVA_NONPRINTABLE ) { - /* - * FIXME: Turn the value into a binary encoded BER? - */ - *len = 0; - return( -1 ); - - } else { - - /* - * we assume the string has enough room for the hex encoding - * of the value - */ + /* + * we assume the string has enough room for the escaping + * of the value + */ - for ( s = 0, d = 0; s < val->bv_len; ) { - if ( LDAP_DN_NEEDESCAPE_AD( val->bv_val[ s ] ) ) { - str[ d++ ] = '\\'; - } + for ( s = 0, d = 0; s < val->bv_len; ) { + cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl ); + if ( cl == 0 ) { + /* illegal utf-8 char */ + return -1; + } else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) { + str[ d++ ] = '\\'; + } + for (; cl--;) { str[ d++ ] = val->bv_val[ s++ ]; } } @@ -2221,7 +2449,7 @@ strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len ) * by Luke Howard, http://www.padl.com/~lukeh) */ static int -dn2domain( LDAPDN *dn, struct berval *bv, int pos, int *iRDN ) +dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN ) { int i; int domain = 0, first = 1; @@ -2231,22 +2459,22 @@ dn2domain( LDAPDN *dn, struct berval *bv, int pos, int *iRDN ) /* we are guaranteed there's enough memory in str */ /* sanity */ - assert( dn ); - assert( bv ); - assert( iRDN ); + assert( dn != NULL ); + assert( bv != NULL ); + assert( iRDN != NULL ); assert( *iRDN >= 0 ); str = bv->bv_val + pos; for ( i = *iRDN; i >= 0; i-- ) { - LDAPRDN *rdn; + LDAPRDN rdn; LDAPAVA *ava; - assert( dn[ 0 ][ i ] ); - rdn = dn[ 0 ][ i ]; + assert( dn[ i ] != NULL ); + rdn = dn[ i ]; - assert( rdn[ 0 ][ 0 ] ); - ava = rdn[ 0 ][ 0 ]; + assert( rdn[ 0 ] != NULL ); + ava = rdn[ 0 ]; if ( !LDAP_DN_IS_RDN_DC( rdn ) ) { break; @@ -2276,7 +2504,7 @@ dn2domain( LDAPDN *dn, struct berval *bv, int pos, int *iRDN ) } static int -rdn2strlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len, +rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len, int ( *s2l )( struct berval *v, unsigned f, ber_len_t *l ) ) { int iAVA; @@ -2284,8 +2512,8 @@ rdn2strlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len, *len = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; /* len(type) + '=' + '+' | ',' */ l += ava->la_attr.bv_len + 2; @@ -2311,14 +2539,14 @@ rdn2strlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len, } static int -rdn2str( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, +rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) ) { int iAVA; ber_len_t l = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; AC_MEMCPY( &str[ l ], ava->la_attr.bv_val, ava->la_attr.bv_len ); @@ -2342,7 +2570,7 @@ rdn2str( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, } l += vl; } - str[ l++ ] = ( rdn[ 0 ][ iAVA + 1 ] ? '+' : ',' ); + str[ l++ ] = ( rdn[ iAVA + 1] ? '+' : ',' ); } *len = l; @@ -2351,26 +2579,23 @@ rdn2str( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, } static int -rdn2DCEstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) +rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; *len = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; /* len(type) + '=' + ',' | '/' */ l += ava->la_attr.bv_len + 2; - switch ( ava->la_flags ) { - case LDAP_AVA_BINARY: + if ( ava->la_flags & LDAP_AVA_BINARY ) { /* octothorpe + twice the length */ l += 1 + 2 * ava->la_value.bv_len; - break; - - case LDAP_AVA_STRING: { + } else { ber_len_t vl; unsigned f = flags | ava->la_flags; @@ -2378,11 +2603,6 @@ rdn2DCEstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2392,13 +2612,13 @@ rdn2DCEstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) } static int -rdn2DCEstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) +rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) { int iAVA; ber_len_t l = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; if ( first ) { first = 0; @@ -2412,16 +2632,13 @@ rdn2DCEstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) str[ l++ ] = '='; - switch ( ava->la_flags ) { - case LDAP_AVA_BINARY: + if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ l++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { return( -1 ); } l += 2 * ava->la_value.bv_len; - break; - - case LDAP_AVA_STRING: { + } else { ber_len_t vl; unsigned f = flags | ava->la_flags; @@ -2429,11 +2646,6 @@ rdn2DCEstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2443,21 +2655,21 @@ rdn2DCEstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) } static int -rdn2UFNstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) +rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; - assert( rdn ); - assert( len ); + assert( rdn != NULL ); + assert( len != NULL ); *len = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; /* ' + ' | ', ' */ - l += ( rdn[ 0 ][ iAVA + 1 ] ? 3 : 2 ); + l += ( rdn[ iAVA + 1 ] ? 3 : 2 ); /* FIXME: are binary values allowed in UFN? */ if ( ava->la_flags & LDAP_AVA_BINARY ) { @@ -2481,13 +2693,13 @@ rdn2UFNstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) } static int -rdn2UFNstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len ) +rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ l++ ] = '#'; @@ -2506,7 +2718,7 @@ rdn2UFNstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len ) l += vl; } - if ( rdn[ 0 ][ iAVA + 1 ]) { + if ( rdn[ iAVA + 1 ] ) { AC_MEMCPY( &str[ l ], " + ", 3 ); l += 3; @@ -2522,30 +2734,27 @@ rdn2UFNstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len ) } static int -rdn2ADstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) +rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len ) { int iAVA; ber_len_t l = 0; - assert( rdn ); - assert( len ); + assert( rdn != NULL ); + assert( len != NULL ); *len = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; /* ',' | '/' */ l++; /* FIXME: are binary values allowed in UFN? */ - switch ( ava->la_flags ) { - case LDAP_AVA_BINARY: + if ( ava->la_flags & LDAP_AVA_BINARY ) { /* octothorpe + twice the value */ l += 1 + 2 * ava->la_value.bv_len; - break; - - case LDAP_AVA_STRING: { + } else { ber_len_t vl; unsigned f = flags | ava->la_flags; @@ -2553,11 +2762,6 @@ rdn2ADstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2567,13 +2771,13 @@ rdn2ADstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) } static int -rdn2ADstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) +rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first ) { int iAVA; ber_len_t l = 0; - for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { - LDAPAVA *ava = rdn[ 0 ][ iAVA ]; + for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { + LDAPAVA *ava = rdn[ iAVA ]; if ( first ) { first = 0; @@ -2581,16 +2785,13 @@ rdn2ADstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) str[ l++ ] = ( iAVA ? ',' : '/' ); } - switch ( ava->la_flags ) { - case LDAP_AVA_BINARY: + if ( ava->la_flags & LDAP_AVA_BINARY ) { str[ l++ ] = '#'; if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) { return( -1 ); } l += 2 * ava->la_value.bv_len; - break; - - case LDAP_AVA_STRING: { + } else { ber_len_t vl; unsigned f = flags | ava->la_flags; @@ -2598,11 +2799,6 @@ rdn2ADstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2619,35 +2815,41 @@ rdn2ADstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) * this is wanted to reduce the allocation of temporary buffers. */ int -ldap_rdn2str( LDAPRDN *rdn, char **str, unsigned flags ) +ldap_rdn2str( LDAPRDN rdn, char **str, unsigned flags ) { struct berval bv; int rc; - assert( str ); + assert( str != NULL ); if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { return LDAP_PARAM_ERROR; } - rc = ldap_rdn2bv( rdn, &bv, flags ); + rc = ldap_rdn2bv_x( rdn, &bv, flags, NULL ); *str = bv.bv_val; return rc; } int -ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags ) +ldap_rdn2bv( LDAPRDN rdn, struct berval *bv, unsigned flags ) +{ + return ldap_rdn2bv_x( rdn, bv, flags, NULL ); +} + +int +ldap_rdn2bv_x( LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx ) { int rc, back; ber_len_t l; - assert( bv ); + assert( bv != NULL ); bv->bv_len = 0; bv->bv_val = NULL; if ( rdn == NULL ) { - bv->bv_val = LDAP_STRDUP( "" ); + bv->bv_val = LDAP_STRDUPX( "", ctx ); return( LDAP_SUCCESS ); } @@ -2687,10 +2889,10 @@ ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags ) break; default: - return( LDAP_PARAM_ERROR ); + return LDAP_PARAM_ERROR; } - bv->bv_val = LDAP_MALLOC( l + 1 ); + bv->bv_val = LDAP_MALLOCX( l + 1, ctx ); switch ( LDAP_DN_FORMAT( flags ) ) { case LDAP_DN_FORMAT_LDAPV3: @@ -2724,7 +2926,7 @@ ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags ) } if ( rc ) { - ldap_memfree( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); return rc; } @@ -2746,23 +2948,28 @@ ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags ) * c) what do we do when binary values must be converted in UTF/DCE/AD? * use binary encoded BER */ -int ldap_dn2str( LDAPDN *dn, char **str, unsigned flags ) +int ldap_dn2str( LDAPDN dn, char **str, unsigned flags ) { struct berval bv; int rc; - assert( str ); + assert( str != NULL ); if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) { return LDAP_PARAM_ERROR; } - rc = ldap_dn2bv( dn, &bv, flags ); + rc = ldap_dn2bv_x( dn, &bv, flags, NULL ); *str = bv.bv_val; return rc; } -int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) +int ldap_dn2bv( LDAPDN dn, struct berval *bv, unsigned flags ) +{ + return ldap_dn2bv_x( dn, bv, flags, NULL ); +} + +int ldap_dn2bv_x( LDAPDN dn, struct berval *bv, unsigned flags, void *ctx ) { int iRDN; int rc = LDAP_ENCODING_ERROR; @@ -2772,19 +2979,18 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l ); int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l ); - assert( bv ); - + assert( bv != NULL ); bv->bv_len = 0; bv->bv_val = NULL; - Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2bv(%u)\n%s%s", flags, "", "" ); + Debug( LDAP_DEBUG_ARGS, "=> ldap_dn2bv(%u)\n", flags, 0, 0 ); /* * a null dn means an empty dn string * FIXME: better raise an error? */ if ( dn == NULL ) { - bv->bv_val = LDAP_STRDUP( "" ); + bv->bv_val = LDAP_STRDUPX( "", ctx ); return( LDAP_SUCCESS ); } @@ -2792,36 +2998,33 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) case LDAP_DN_FORMAT_LDAPV3: sv2l = strval2strlen; sv2s = strval2str; - goto got_funcs; + if( 0 ) { case LDAP_DN_FORMAT_LDAPV2: - sv2l = strval2IA5strlen; - sv2s = strval2IA5str; -got_funcs: - - for ( iRDN = 0, len = 0; dn[ 0 ][ iRDN ]; iRDN++ ) { + sv2l = strval2IA5strlen; + sv2s = strval2IA5str; + } + + for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - - if ( rdn2strlen( rdn, flags, &rdnl, sv2l ) ) { + if ( rdn2strlen( dn[ iRDN ], flags, &rdnl, sv2l ) ) { goto return_results; } len += rdnl; } - if ( ( bv->bv_val = LDAP_MALLOC( len + 1 ) ) == NULL ) { + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { rc = LDAP_NO_MEMORY; break; } - for ( l = 0, iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) { + for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - if ( rdn2str( rdn, &bv->bv_val[ l ], flags, + if ( rdn2str( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, sv2s ) ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } @@ -2841,7 +3044,6 @@ got_funcs: break; case LDAP_DN_FORMAT_UFN: { - /* * FIXME: quoting from RFC 1781: * @@ -2881,17 +3083,16 @@ got_funcs: int last_iRDN = -1; #endif /* DC_IN_UFN */ - for ( iRDN = 0, len = 0; dn[ 0 ][ iRDN ]; iRDN++ ) { + for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - if ( rdn2UFNstrlen( rdn, flags, &rdnl ) ) { + if ( rdn2UFNstrlen( dn[ iRDN ], flags, &rdnl ) ) { goto return_results; } len += rdnl; #ifdef DC_IN_UFN - if ( LDAP_DN_IS_RDN_DC( rdn ) ) { + if ( LDAP_DN_IS_RDN_DC( dn[ iRDN ] ) ) { if ( leftmost_dc == -1 ) { leftmost_dc = iRDN; } @@ -2901,7 +3102,7 @@ got_funcs: #endif /* DC_IN_UFN */ } - if ( ( bv->bv_val = LDAP_MALLOC( len + 1 ) ) == NULL ) { + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { rc = LDAP_NO_MEMORY; break; } @@ -2909,13 +3110,12 @@ got_funcs: #ifdef DC_IN_UFN if ( leftmost_dc == -1 ) { #endif /* DC_IN_UFN */ - for ( l = 0, iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) { + for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t vl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - if ( rdn2UFNstr( rdn, &bv->bv_val[ l ], + if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &vl ) ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } @@ -2934,11 +3134,10 @@ got_funcs: for ( l = 0, iRDN = 0; iRDN < leftmost_dc; iRDN++ ) { ber_len_t vl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - if ( rdn2UFNstr( rdn, &bv->bv_val[ l ], + if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &vl ) ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } @@ -2946,7 +3145,7 @@ got_funcs: } if ( !dn2domain( dn, bv, l, &last_iRDN ) ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } @@ -2956,34 +3155,30 @@ got_funcs: #endif /* DC_IN_UFN */ rc = LDAP_SUCCESS; - break; - } - case LDAP_DN_FORMAT_DCE: + } break; - for ( iRDN = 0, len = 0; dn[ 0 ][ iRDN ]; iRDN++ ) { + case LDAP_DN_FORMAT_DCE: + for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - - if ( rdn2DCEstrlen( rdn, flags, &rdnl ) ) { + if ( rdn2DCEstrlen( dn[ iRDN ], flags, &rdnl ) ) { goto return_results; } len += rdnl; } - if ( ( bv->bv_val = LDAP_MALLOC( len + 1 ) ) == NULL ) { + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) { rc = LDAP_NO_MEMORY; break; } for ( l = 0; iRDN--; ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - if ( rdn2DCEstr( rdn, &bv->bv_val[ l ], flags, + if ( rdn2DCEstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, 0 ) ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } @@ -2999,7 +3194,8 @@ got_funcs: break; case LDAP_DN_FORMAT_AD_CANONICAL: { - + int trailing_slash = 1; + /* * Sort of UFN for DCE DNs: a slash ('/') separated * global->local DN with no types; strictly speaking, @@ -3014,31 +3210,34 @@ got_funcs: * * "microsoft.com/People/Bill,Gates" */ - for ( iRDN = 0, len = -1; dn[ 0 ][ iRDN ]; iRDN++ ) { + for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - if ( rdn2ADstrlen( rdn, flags, &rdnl ) ) { + if ( rdn2ADstrlen( dn[ iRDN ], flags, &rdnl ) ) { goto return_results; } len += rdnl; } - if ( ( bv->bv_val = LDAP_MALLOC( len + 1 ) ) == NULL ) { + /* reserve room for trailing '/' in case the DN + * is exactly a domain */ + if ( ( bv->bv_val = LDAP_MALLOCX( len + 1 + 1, ctx ) ) == NULL ) + { rc = LDAP_NO_MEMORY; break; } iRDN--; - if ( iRDN && dn2domain( dn, bv, 0, &iRDN ) ) { + if ( iRDN && dn2domain( dn, bv, 0, &iRDN ) != 0 ) { for ( l = bv->bv_len; iRDN >= 0 ; iRDN-- ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; + + trailing_slash = 0; - if ( rdn2ADstr( rdn, &bv->bv_val[ l ], + if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, 0 ) ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } @@ -3054,7 +3253,7 @@ got_funcs: * i.e. terminated by a domain component */ if ( flags & LDAP_DN_PEDANTIC ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; rc = LDAP_ENCODING_ERROR; break; @@ -3062,11 +3261,10 @@ got_funcs: for ( l = 0; iRDN >= 0 ; iRDN-- ) { ber_len_t rdnl; - LDAPRDN *rdn = dn[ 0 ][ iRDN ]; - if ( rdn2ADstr( rdn, &bv->bv_val[ l ], + if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ], flags, &rdnl, first ) ) { - LDAP_FREE( bv->bv_val ); + LDAP_FREEX( bv->bv_val, ctx ); bv->bv_val = NULL; goto return_results; } @@ -3077,19 +3275,26 @@ got_funcs: } } + if ( trailing_slash ) { + /* the DN is exactly a domain -- need a trailing + * slash; room was reserved in advance */ + bv->bv_val[ len ] = '/'; + len++; + } + bv->bv_len = len; bv->bv_val[ bv->bv_len ] = '\0'; rc = LDAP_SUCCESS; - break; - } + } break; default: return LDAP_PARAM_ERROR; } - Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2bv(%s,%u)=%d\n", - bv->bv_val, flags, rc ); + Debug( LDAP_DEBUG_ARGS, "<= ldap_dn2bv(%s)=%d %s\n", + bv->bv_val, rc, rc ? ldap_err2string( rc ) : "" ); + return_results:; return( rc ); }