X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Flibldap%2Fgetdn.c;h=d43287172576ff1174dffff2afaf20f26ebb5137;hb=3d39ff68a94e4455074707d763138f01aaa1c5b1;hp=ceb199427d542d0bcc6fed4d35f02519cdc9aa29;hpb=6939c531700652491f4be4688c6a1f35a1ab8a18;p=openldap diff --git a/libraries/libldap/getdn.c b/libraries/libldap/getdn.c index ceb199427d..d432871725 100644 --- a/libraries/libldap/getdn.c +++ b/libraries/libldap/getdn.c @@ -1,13 +1,19 @@ /* $OpenLDAP$ */ -/* - * Copyright 1998-2003 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. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. * - * getdn.c + * 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, ber_len_t stoplen, struct berval *val, - const char **next, unsigned flags, unsigned *retFlags ); + 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 @@ -84,11 +89,7 @@ ldap_get_dn( LDAP *ld, LDAPMessage *entry ) char *dn; BerElement tmp; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_get_dn\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 ); -#endif assert( ld != NULL ); assert( LDAP_VALID(ld) ); @@ -111,11 +112,7 @@ ldap_get_dn_ber( LDAP *ld, LDAPMessage *entry, BerElement **berout, ber_len_t len = 0; int rc = LDAP_SUCCESS; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_get_dn_ber\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n", 0, 0, 0 ); -#endif assert( ld != NULL ); assert( LDAP_VALID(ld) ); @@ -162,11 +159,7 @@ ldap_dn2ufn( LDAP_CONST char *dn ) { char *out = NULL; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2ufn\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 ); -#endif ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, &out, LDAP_DN_FORMAT_UFN ); @@ -180,16 +173,12 @@ 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; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_explode_dn\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 ); -#endif if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAP ) != LDAP_SUCCESS ) { @@ -204,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 ) { @@ -212,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; @@ -224,16 +213,12 @@ 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; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_explode_rdn\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 ); -#endif /* * we only parse the first rdn @@ -245,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 { @@ -281,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; @@ -314,11 +299,7 @@ ldap_dn2dcedn( LDAP_CONST char *dn ) { char *out = NULL; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2dcedn\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 ); -#endif ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, &out, LDAP_DN_FORMAT_DCE ); @@ -331,11 +312,7 @@ ldap_dcedn2dn( LDAP_CONST char *dce ) { char *out = NULL; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_dcedn2dn\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 ); -#endif ( void )ldap_dn_normalize( dce, LDAP_DN_FORMAT_DCE, &out, LDAP_DN_FORMAT_LDAPV3 ); @@ -347,11 +324,7 @@ ldap_dn2ad_canonical( LDAP_CONST char *dn ) { char *out = NULL; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2ad_canonical\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n", 0, 0, 0 ); -#endif ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP, &out, LDAP_DN_FORMAT_AD_CANONICAL ); @@ -364,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 @@ -381,15 +353,11 @@ ldap_dn_normalize( LDAP_CONST char *dnin, unsigned fin, char **dnout, unsigned fout ) { int rc; - LDAPDN *tmpDN = NULL; + LDAPDN tmpDN = NULL; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ENTRY, "ldap_dn_normalize\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n", 0, 0, 0 ); -#endif - assert( dnout ); + assert( dnout != NULL ); *dnout = NULL; @@ -463,12 +431,25 @@ 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_MAYESCAPE(c) @@ -542,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) \ @@ -575,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 @@ -616,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_FREEX( ava, ctx ); +} - LDAP_FREE( ava ); +void +ldap_rdnfree( LDAPRDN rdn ) +{ + ldap_rdnfree_x( rdn, NULL ); } void -ldap_rdnfree( LDAPRDN *rdn ) +ldap_rdnfree_x( LDAPRDN rdn, void *ctx ) { int iAVA; @@ -634,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_x( dn, NULL ); } void -ldap_dnfree( LDAPDN *dn ) +ldap_dnfree_x( LDAPDN dn, void *ctx ) { int iRDN; @@ -650,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 ); } /* @@ -681,50 +668,69 @@ ldap_dnfree( LDAPDN *dn ) #define TMP_RDN_SLOTS 32 int -ldap_str2dn( LDAP_CONST char *str, LDAPDN **dn, unsigned flags ) +ldap_str2dn( LDAP_CONST char *str, LDAPDN *dn, unsigned flags ) { struct berval bv; - assert( str ); + assert( str != NULL ); bv.bv_len = strlen( str ); bv.bv_val = (char *) str; - return ldap_bv2dn( &bv, dn, flags ); + return ldap_bv2dn_x( &bv, dn, flags, NULL ); +} + +int +ldap_bv2dn( struct berval *bv, LDAPDN *dn, unsigned flags ) +{ + return ldap_bv2dn_x( bv, dn, flags, NULL ); } int -ldap_bv2dn( struct berval *bv, LDAPDN **dn, unsigned flags ) +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_RDN_SLOTS], **tmpDN = tmpDN_; + LDAPDN newDN = NULL; + LDAPRDN newRDN = NULL, tmpDN_[TMP_RDN_SLOTS], *tmpDN = tmpDN_; int num_slots = TMP_RDN_SLOTS; - char *str = bv->bv_val; - char *end = str + bv->bv_len; + char *str, *end; + struct berval bvtmp, *bv = &bvtmp; - assert( bv ); - assert( bv->bv_val ); - assert( dn ); + assert( bvin != NULL ); + assert( bvin->bv_val != NULL ); + assert( dn != NULL ); -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ARGS, "ldap_bv2dn(%s,%u)\n%s", str, flags, "" ); -#else - Debug( LDAP_DEBUG_TRACE, "=> ldap_bv2dn(%s,%u)\n%s", str, flags, "" ); -#endif + *bv = *bvin; + str = bv->bv_val; + end = str + bv->bv_len; + + 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: @@ -778,7 +784,7 @@ ldap_bv2dn( struct berval *bv, LDAPDN **dn, unsigned flags ) tmpbv.bv_len = bv->bv_len - ( p - str ); tmpbv.bv_val = (char *)p; - err = ldap_bv2rdn( &tmpbv, &newRDN, (char **) &p, flags ); + err = ldap_bv2rdn_x( &tmpbv, &newRDN, (char **) &p, flags,ctx); if ( err != LDAP_SUCCESS ) { goto parsing_error; } @@ -820,10 +826,10 @@ ldap_bv2dn( struct berval *bv, LDAPDN **dn, unsigned flags ) * make the static RDN array dynamically rescalable */ if ( nrdns == num_slots ) { - LDAPRDN **tmp; + LDAPRDN *tmp; if ( tmpDN == tmpDN_ ) { - tmp = LDAP_MALLOC( num_slots * 2 * sizeof( LDAPRDN * ) ); + tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPRDN * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; @@ -831,7 +837,7 @@ ldap_bv2dn( struct berval *bv, LDAPDN **dn, unsigned flags ) AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) ); } else { - tmp = LDAP_REALLOC( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ) ); + tmp = LDAP_REALLOCX( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; @@ -846,25 +852,22 @@ ldap_bv2dn( struct berval *bv, LDAPDN **dn, unsigned flags ) /* * 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] ); + ldap_rdnfree_x( tmpDN[nrdns], ctx ); } return_result:; if ( tmpDN != tmpDN_ ) { - LDAP_FREE( tmpDN ); + LDAP_FREEX( tmpDN, ctx ); } -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, RESULTS, "<= ldap_bv2dn(%s,%u)=%d\n", - str, flags, rc ); -#else - Debug( LDAP_DEBUG_TRACE, "<= ldap_bv2dn(%s,%u)=%d\n", str, flags, rc ); -#endif + Debug( LDAP_DEBUG_ARGS, "<= ldap_bv2dn(%s)=%d %s\n", str, rc, + rc ? ldap_err2string( rc ) : "" ); *dn = newDN; return( rc ); @@ -906,23 +905,30 @@ 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 ); + assert( str != NULL ); assert( str[ 0 ] != '\0' ); /* FIXME: is this required? */ bv.bv_len = strlen( str ); bv.bv_val = (char *) str; - return ldap_bv2rdn( &bv, rdn, n_in, flags ); + return ldap_bv2rdn_x( &bv, rdn, n_in, flags, NULL ); } int -ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, +ldap_bv2rdn( struct berval *bv, LDAPRDN *rdn, char **n_in, unsigned flags ) +{ + 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; @@ -932,21 +938,21 @@ ldap_bv2rdn( struct berval *bv, 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; + LDAPRDN newRDN = NULL; LDAPAVA *tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_; int num_slots = TMP_AVA_SLOTS; char *str; ber_len_t stoplen; - assert( bv ); - assert( bv->bv_len ); - assert( bv->bv_val ); + assert( bv != NULL ); + assert( bv->bv_len != 0 ); + assert( bv->bv_val != NULL ); assert( rdn || flags & LDAP_DN_SKIP ); - assert( n ); + assert( n != NULL ); str = bv->bv_val; stoplen = bv->bv_len; @@ -996,15 +1002,8 @@ ldap_bv2rdn( struct berval *bv, 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 ] ) ) { @@ -1104,9 +1103,8 @@ ldap_bv2rdn( struct berval *bv, 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; @@ -1226,7 +1224,7 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, } /* - * here STRING means RFC 2253 string + * here STRING means RFC 4514 string * FIXME: what about DCE strings? */ if ( !p[ 0 ] ) { @@ -1238,7 +1236,7 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, break; case B4BINARYVALUE: - if ( hexstr2binval( p, &attrValue, &p, flags ) ) { + if ( hexstr2binval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } @@ -1251,13 +1249,13 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, case LDAP_DN_FORMAT_LDAPV3: if ( str2strval( p, stoplen - ( p - str ), &attrValue, &p, flags, - &attrValueEncoding ) ) { + &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; @@ -1270,7 +1268,7 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, break; case B4IA5VALUE: - if ( IA52strval( p, &attrValue, &p, flags ) ) { + if ( IA52strval( p, &attrValue, &p, flags, ctx ) ) { goto parsing_error; } @@ -1281,7 +1279,7 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, /* lead quote already stripped */ if ( quotedIA52strval( p, &attrValue, - &p, flags ) ) { + &p, flags, ctx ) ) { goto parsing_error; } @@ -1298,8 +1296,7 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, * we accept empty values */ ava = ldapava_new( &attrType, &attrValue, - attrValueEncoding ); - + attrValueEncoding, ctx ); if ( ava == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; @@ -1316,7 +1313,7 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, LDAPAVA **tmp; if ( tmpRDN == tmpRDN_ ) { - tmp = LDAP_MALLOC( num_slots * 2 * sizeof( LDAPAVA * ) ); + tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPAVA * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; @@ -1324,7 +1321,7 @@ ldap_bv2rdn( struct berval *bv, LDAPRDN **rdn, AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) ); } else { - tmp = LDAP_REALLOC( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ) ); + tmp = LDAP_REALLOCX( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ), ctx ); if ( tmp == NULL ) { rc = LDAP_NO_MEMORY; goto parsing_error; @@ -1363,19 +1360,14 @@ ldap_bv2rdn( struct berval *bv, 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] ); + ldapava_free( tmpRDN[navas], ctx ); } return_result:; if ( tmpRDN != tmpRDN_ ) { - LDAP_FREE( tmpRDN ); + LDAP_FREEX( tmpRDN, ctx ); } if ( rdn ) { @@ -1429,14 +1421,14 @@ return_result:; * '\' + HEXPAIR(p) -> unhex(p) */ static int -str2strval( const char *str, ber_len_t stoplen, 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, *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; end = str + stoplen; @@ -1480,7 +1472,7 @@ str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char * */ return( 1 ); - } else if (!LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) { + } else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) { if ( p[ 0 ] == '\0' ) { return( 1 ); } @@ -1531,18 +1523,18 @@ str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char * val->bv_len = len; if ( escapes == 0 ) { - if ( *retFlags == LDAP_AVA_NONPRINTABLE ) { - val->bv_val = LDAP_MALLOC( len + 1 ); + 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_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++; @@ -1575,14 +1567,14 @@ str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char * } 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; @@ -1634,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 @@ -1660,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; @@ -1715,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++; @@ -1735,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; @@ -1805,12 +1797,12 @@ quotedIA52strval( const char *str, struct berval *val, const char **next, unsign 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; ) { @@ -1831,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 ]; @@ -1867,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; @@ -1949,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 ); } @@ -1975,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 @@ -1997,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 ); @@ -2024,21 +2016,22 @@ 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 < val->bv_val + val->bv_len; p += cl ) { + end = val->bv_val + val->bv_len - 1; + for ( l = 0, p = val->bv_val; p <= end; p += cl ) { /* * escape '%x00' @@ -2065,8 +2058,9 @@ strval2strlen( struct berval *val, unsigned flags, ber_len_t *len ) 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 ] ) ) { @@ -2107,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; @@ -2155,6 +2149,7 @@ strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len ) #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 ] ) ) @@ -2175,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++ ] = '\\'; @@ -2204,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 ) { @@ -2221,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; @@ -2245,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; @@ -2269,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++ ] = '\\'; @@ -2292,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 ) { @@ -2332,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; @@ -2370,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++ ]; } } @@ -2461,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; @@ -2471,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; @@ -2516,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; @@ -2524,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; @@ -2551,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 ); @@ -2582,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; @@ -2591,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; @@ -2618,11 +2603,6 @@ rdn2DCEstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2632,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; @@ -2652,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; @@ -2669,11 +2646,6 @@ rdn2DCEstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2683,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 ) { @@ -2721,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++ ] = '#'; @@ -2746,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; @@ -2762,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; @@ -2793,11 +2762,6 @@ rdn2ADstrlen( LDAPRDN *rdn, unsigned flags, ber_len_t *len ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2807,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; @@ -2821,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; @@ -2838,11 +2799,6 @@ rdn2ADstr( LDAPRDN *rdn, char *str, unsigned flags, ber_len_t *len, int first ) return( -1 ); } l += vl; - break; - } - - default: - return( -1 ); } } @@ -2859,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 ); } @@ -2930,7 +2892,7 @@ ldap_rdn2bv( LDAPRDN *rdn, struct berval *bv, unsigned flags ) 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: @@ -2964,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; } @@ -2986,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; @@ -3012,23 +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; -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ARGS, "=> ldap_dn2bv(%u)\n%s%s", - flags, "", "" ); -#else - Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2bv(%u)\n%s%s", flags, "", "" ); -#endif + 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 ); } @@ -3043,29 +3005,26 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) sv2s = strval2IA5str; } - 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 ( 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; } @@ -3124,17 +3083,16 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) 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; } @@ -3144,7 +3102,7 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) #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; } @@ -3152,13 +3110,12 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) #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; } @@ -3177,11 +3134,10 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) 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; } @@ -3189,7 +3145,7 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) } 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; } @@ -3203,29 +3159,26 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) } break; case LDAP_DN_FORMAT_DCE: - 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 ( 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; } @@ -3241,6 +3194,8 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) 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, @@ -3255,31 +3210,34 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) * * "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; } @@ -3295,7 +3253,7 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) * 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; @@ -3303,11 +3261,10 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) 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; } @@ -3318,6 +3275,13 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) } } + 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'; @@ -3328,214 +3292,10 @@ int ldap_dn2bv( LDAPDN *dn, struct berval *bv, unsigned flags ) return LDAP_PARAM_ERROR; } -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, RESULTS, "<= ldap_dn2bv(%s,%u)=%d\n", - bv->bv_val, flags, rc ); -#else - Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2bv(%s,%u)=%d\n", - bv->bv_val, flags, rc ); -#endif + Debug( LDAP_DEBUG_ARGS, "<= ldap_dn2bv(%s)=%d %s\n", + bv->bv_val, rc, rc ? ldap_err2string( rc ) : "" ); return_results:; return( rc ); } -#ifdef HAVE_TLS -#include -#include - -/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN. - * x509_name must be an (X509_NAME *). If func is non-NULL, the - * constructed DN will use numeric OIDs to identify attributeTypes, - * and the func() will be invoked to rewrite the DN with the given - * flags. - * - * Otherwise the DN will use shortNames as defined in the OpenSSL - * library. - * - * It's preferable to let slapd do the OID to attributeType mapping, - * because the OpenSSL tables are known to have many typos in versions - * up to (at least) 0.9.6c. However, the LDAP client has no schema tables, - * so we're forced to use OpenSSL's mapping there. - * -- Howard Chu 2002-04-18 - */ - -int -ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func, - unsigned flags ) -{ - LDAPDN *newDN; - LDAPRDN *newRDN; - LDAPAVA *newAVA, *baseAVA; - X509_NAME_ENTRY *ne; - ASN1_OBJECT *obj; - ASN1_STRING *str; - char oids[8192], *oidptr = oids, *oidbuf = NULL; - void *ptrs[2048]; - int i, j, k = 0, navas, nrdns, rc = LDAP_SUCCESS; - int set = -1; - size_t dnsize, oidrem = sizeof(oids), oidsize = 0; - int csize; - - struct berval Val; - - assert( bv ); - bv->bv_len = 0; - bv->bv_val = NULL; - - /* Get the number of AVAs. This is not necessarily the same as - * the number of RDNs. - */ - navas = X509_NAME_entry_count( x509_name ); - - /* Get the last element, to see how many RDNs there are */ - ne = X509_NAME_get_entry( x509_name, navas - 1 ); - nrdns = ne->set + 1; - - /* Allocate the DN/RDN/AVA stuff as a single block */ - dnsize = sizeof(LDAPDN) + sizeof(LDAPRDN *) * (nrdns+1); - dnsize += sizeof(LDAPRDN) * nrdns + sizeof(LDAPAVA *) * (navas+nrdns); - dnsize += sizeof(LDAPAVA) * navas; - if (dnsize > sizeof(ptrs)) { - newDN = (LDAPDN *)LDAP_MALLOC( dnsize ); - if ( newDN == NULL ) - return LDAP_NO_MEMORY; - } else { - newDN = (LDAPDN *)ptrs; - } - - newDN[0] = (LDAPRDN**)(newDN+1); - newDN[0][nrdns] = NULL; - newRDN = (LDAPRDN*)(newDN[0] + nrdns+1); - newAVA = (LDAPAVA*)(newRDN + navas + nrdns*2); - baseAVA = newAVA; - - /* Retrieve RDNs in reverse order; LDAP is backwards from X.500. */ - for ( i = nrdns - 1, j = 0; i >= 0; i-- ) { - ne = X509_NAME_get_entry( x509_name, i ); - obj = X509_NAME_ENTRY_get_object( ne ); - str = X509_NAME_ENTRY_get_data( ne ); - - /* If set changed, move to next RDN */ - if ( set != ne->set ) { - /* If this is not the first time, end the - * previous RDN and advance. - */ - if ( j > 0 ) { - newRDN[0][k] = NULL; - newRDN = (LDAPRDN*)(newRDN[0]+k+1); - } - newDN[0][j++] = newRDN; - - newRDN[0] = (LDAPAVA**)(newRDN+1); - k = 0; - set = ne->set; - } - newAVA->la_private = NULL; - newAVA->la_flags = LDAP_AVA_STRING; - - if ( !func ) { - int n = OBJ_obj2nid( obj ); - - if (n == NID_undef) - goto get_oid; - newAVA->la_attr.bv_val = (char *)OBJ_nid2sn( n ); - newAVA->la_attr.bv_len = strlen( newAVA->la_attr.bv_val ); -#ifdef HAVE_EBCDIC - newAVA->la_attr.bv_val = LDAP_STRDUP( newAVA->la_attr.bv_val ); - __etoa( newAVA->la_attr.bv_val ); -#endif - } else { -get_oid: newAVA->la_attr.bv_val = oidptr; - newAVA->la_attr.bv_len = OBJ_obj2txt( oidptr, oidrem, obj, 1 ); -#ifdef HAVE_EBCDIC - __etoa( newAVA->la_attr.bv_val ); -#endif - oidptr += newAVA->la_attr.bv_len + 1; - oidrem -= newAVA->la_attr.bv_len + 1; - - /* Running out of OID buffer space? */ - if (oidrem < 128) { - if ( oidsize == 0 ) { - oidsize = sizeof(oids) * 2; - oidrem = oidsize; - oidbuf = LDAP_MALLOC( oidsize ); - if ( oidbuf == NULL ) goto nomem; - oidptr = oidbuf; - } else { - char *old = oidbuf; - oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 ); - if ( oidbuf == NULL ) goto nomem; - /* Buffer moved! Fix AVA pointers */ - if ( old != oidbuf ) { - LDAPAVA *a; - long dif = oidbuf - old; - - for (a=baseAVA; a<=newAVA; a++){ - if (a->la_attr.bv_val >= old && - a->la_attr.bv_val <= (old + oidsize)) - a->la_attr.bv_val += dif; - } - } - oidptr = oidbuf + oidsize - oidrem; - oidrem += oidsize; - oidsize *= 2; - } - } - } - Val.bv_val = str->data; - Val.bv_len = str->length; - switch( str->type ) { - case V_ASN1_UNIVERSALSTRING: - /* This uses 32-bit ISO 10646-1 */ - csize = 4; goto to_utf8; - case V_ASN1_BMPSTRING: - /* This uses 16-bit ISO 10646-1 */ - csize = 2; goto to_utf8; - case V_ASN1_T61STRING: - /* This uses 8-bit, assume ISO 8859-1 */ - csize = 1; -to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value ); - if (rc != LDAP_SUCCESS) goto nomem; - newAVA->la_flags = LDAP_AVA_NONPRINTABLE; - break; - case V_ASN1_UTF8STRING: - newAVA->la_flags = LDAP_AVA_NONPRINTABLE; - /* This is already in UTF-8 encoding */ - case V_ASN1_IA5STRING: - case V_ASN1_PRINTABLESTRING: - /* These are always 7-bit strings */ - ber_dupbv( &newAVA->la_value, &Val ); - default: - ; - } - newRDN[0][k] = newAVA; - newAVA++; - k++; - } - newRDN[0][k] = NULL; - - if ( func ) { - rc = func( newDN, flags ); - if ( rc != LDAP_SUCCESS ) - goto nomem; - } - - rc = ldap_dn2bv( newDN, bv, LDAP_DN_FORMAT_LDAPV3 ); - -nomem: - for (;baseAVA < newAVA; baseAVA++) { - LDAP_FREE( baseAVA->la_value.bv_val ); -#ifdef HAVE_EBCDIC - if ( !func ) LDAP_FREE( baseAVA->la_attr.bv_val ); -#endif - } - - if ( oidsize != 0 ) - LDAP_FREE( oidbuf ); - if ( newDN != (LDAPDN*) ptrs ) - LDAP_FREE( newDN ); - return rc; -} -#endif /* HAVE_TLS */ -