Home | History | Annotate | Line # | Download | only in libldap
      1 /*	$NetBSD: getdn.c,v 1.4 2025/09/05 21:16:21 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 The OpenLDAP Foundation.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted only as authorized by the OpenLDAP
     11  * Public License.
     12  *
     13  * A copy of this license is available in the file LICENSE in the
     14  * top-level directory of the distribution or, alternatively, at
     15  * <http://www.OpenLDAP.org/license.html>.
     16  */
     17 /* Portions Copyright (c) 1994 Regents of the University of Michigan.
     18  * All rights reserved.
     19  */
     20 
     21 #include <sys/cdefs.h>
     22 __RCSID("$NetBSD: getdn.c,v 1.4 2025/09/05 21:16:21 christos Exp $");
     23 
     24 #include "portable.h"
     25 
     26 #include <stdio.h>
     27 
     28 #include <ac/stdlib.h>
     29 #include <ac/socket.h>
     30 #include <ac/string.h>
     31 #include <ac/time.h>
     32 
     33 #include "ldap-int.h"
     34 #include "ldap_schema.h"
     35 #include "ldif.h"
     36 
     37 /* extension to UFN that turns trailing "dc=value" rdns in DNS style,
     38  * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */
     39 #define DC_IN_UFN
     40 
     41 /* parsing/printing routines */
     42 static int str2strval( const char *str, ber_len_t stoplen, struct berval *val,
     43 		const char **next, unsigned flags, int *retFlags, void *ctx );
     44 static int DCE2strval( const char *str, struct berval *val,
     45 		const char **next, unsigned flags, void *ctx );
     46 static int IA52strval( const char *str, struct berval *val,
     47 		const char **next, unsigned flags, void *ctx );
     48 static int quotedIA52strval( const char *str, struct berval *val,
     49 		const char **next, unsigned flags, void *ctx );
     50 static int hexstr2binval( const char *str, struct berval *val,
     51 		const char **next, unsigned flags, void *ctx );
     52 static int hexstr2bin( const char *str, char *c );
     53 static int byte2hexpair( const char *val, char *pair );
     54 static int binval2hexstr( struct berval *val, char *str );
     55 static int strval2strlen( struct berval *val, unsigned flags,
     56 		ber_len_t *len );
     57 static int strval2str( struct berval *val, char *str, unsigned flags,
     58 		ber_len_t *len );
     59 static int strval2IA5strlen( struct berval *val, unsigned flags,
     60 		ber_len_t *len );
     61 static int strval2IA5str( struct berval *val, char *str, unsigned flags,
     62 		ber_len_t *len );
     63 static int strval2DCEstrlen( struct berval *val, unsigned flags,
     64 		ber_len_t *len );
     65 static int strval2DCEstr( struct berval *val, char *str, unsigned flags,
     66 		ber_len_t *len );
     67 static int strval2ADstrlen( struct berval *val, unsigned flags,
     68 		ber_len_t *len );
     69 static int strval2ADstr( struct berval *val, char *str, unsigned flags,
     70 		ber_len_t *len );
     71 static int dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN );
     72 
     73 /* AVA helpers */
     74 static LDAPAVA * ldapava_new(
     75 	const struct berval *attr, const struct berval *val, unsigned flags, void *ctx );
     76 
     77 /* Higher level helpers */
     78 static int rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len,
     79 		int ( *s2l )( struct berval *, unsigned, ber_len_t * ) );
     80 static int rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len,
     81 		int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * ));
     82 static int rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len  );
     83 static int rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len );
     84 static int rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len );
     85 static int rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flag, ber_len_t *len, int first );
     86 static int rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len );
     87 static int rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first );
     88 
     89 /*
     90  * RFC 1823 ldap_get_dn
     91  */
     92 char *
     93 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
     94 {
     95 	char		*dn;
     96 	BerElement	tmp;
     97 
     98 	Debug0( LDAP_DEBUG_TRACE, "ldap_get_dn\n" );
     99 
    100 	assert( ld != NULL );
    101 	assert( LDAP_VALID(ld) );
    102 	assert( entry != NULL );
    103 
    104 	tmp = *entry->lm_ber;	/* struct copy */
    105 	if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) {
    106 		ld->ld_errno = LDAP_DECODING_ERROR;
    107 		return( NULL );
    108 	}
    109 
    110 	return( dn );
    111 }
    112 
    113 int
    114 ldap_get_dn_ber( LDAP *ld, LDAPMessage *entry, BerElement **berout,
    115 	BerValue *dn )
    116 {
    117 	BerElement	tmp, *ber;
    118 	ber_len_t	len = 0;
    119 	int rc = LDAP_SUCCESS;
    120 
    121 	Debug0( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n" );
    122 
    123 	assert( ld != NULL );
    124 	assert( LDAP_VALID(ld) );
    125 	assert( entry != NULL );
    126 	assert( dn != NULL );
    127 
    128 	dn->bv_val = NULL;
    129 	dn->bv_len = 0;
    130 
    131 	if ( berout ) {
    132 		*berout = NULL;
    133 		ber = ldap_alloc_ber_with_options( ld );
    134 		if( ber == NULL ) {
    135 			return LDAP_NO_MEMORY;
    136 		}
    137 		*berout = ber;
    138 	} else {
    139 		ber = &tmp;
    140 	}
    141 
    142 	*ber = *entry->lm_ber;	/* struct copy */
    143 	if ( ber_scanf( ber, "{ml{" /*}*/, dn, &len ) == LBER_ERROR ) {
    144 		rc = ld->ld_errno = LDAP_DECODING_ERROR;
    145 	}
    146 	if ( rc == LDAP_SUCCESS ) {
    147 		/* set the length to avoid overrun */
    148 		rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len );
    149 		if( rc != LBER_OPT_SUCCESS ) {
    150 			rc = ld->ld_errno = LDAP_LOCAL_ERROR;
    151 		}
    152 	}
    153 	if ( rc != LDAP_SUCCESS && berout ) {
    154 		ber_free( ber, 0 );
    155 		*berout = NULL;
    156 	}
    157 	return rc;
    158 }
    159 
    160 /*
    161  * RFC 1823 ldap_dn2ufn
    162  */
    163 char *
    164 ldap_dn2ufn( LDAP_CONST char *dn )
    165 {
    166 	char	*out = NULL;
    167 
    168 	Debug0( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n" );
    169 
    170 	( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
    171 		&out, LDAP_DN_FORMAT_UFN );
    172 
    173 	return( out );
    174 }
    175 
    176 /*
    177  * RFC 1823 ldap_explode_dn
    178  */
    179 char **
    180 ldap_explode_dn( LDAP_CONST char *dn, int notypes )
    181 {
    182 	LDAPDN	tmpDN;
    183 	char	**values = NULL;
    184 	int	iRDN;
    185 	unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3;
    186 
    187 	Debug0( LDAP_DEBUG_TRACE, "ldap_explode_dn\n" );
    188 
    189 	if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAP )
    190 			!= LDAP_SUCCESS ) {
    191 		return NULL;
    192 	}
    193 
    194 	if( tmpDN == NULL ) {
    195 		values = LDAP_MALLOC( sizeof( char * ) );
    196 		if( values == NULL ) return NULL;
    197 
    198 		values[0] = NULL;
    199 		return values;
    200 	}
    201 
    202 	for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ );
    203 
    204 	values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iRDN ) );
    205 	if ( values == NULL ) {
    206 		ldap_dnfree( tmpDN );
    207 		return NULL;
    208 	}
    209 
    210 	for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) {
    211 		ldap_rdn2str( tmpDN[ iRDN ], &values[ iRDN ], flag );
    212 	}
    213 	ldap_dnfree( tmpDN );
    214 	values[ iRDN ] = NULL;
    215 
    216 	return values;
    217 }
    218 
    219 char **
    220 ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
    221 {
    222 	LDAPRDN		tmpRDN;
    223 	char		**values = NULL;
    224 	const char 	*p;
    225 	int		iAVA;
    226 
    227 	Debug0( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n" );
    228 
    229 	/*
    230 	 * we only parse the first rdn
    231 	 * FIXME: we prefer efficiency over checking if the _ENTIRE_
    232 	 * dn can be parsed
    233 	 */
    234 	if ( ldap_str2rdn( rdn, &tmpRDN, (char **) &p, LDAP_DN_FORMAT_LDAP )
    235 			!= LDAP_SUCCESS ) {
    236 		return( NULL );
    237 	}
    238 
    239 	for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) ;
    240 	values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iAVA ) );
    241 	if ( values == NULL ) {
    242 		ldap_rdnfree( tmpRDN );
    243 		return( NULL );
    244 	}
    245 
    246 	for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) {
    247 		ber_len_t	l = 0, vl, al = 0;
    248 		char		*str;
    249 		LDAPAVA		*ava = tmpRDN[ iAVA ];
    250 
    251 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
    252 			vl = 1 + 2 * ava->la_value.bv_len;
    253 
    254 		} else {
    255 			if ( strval2strlen( &ava->la_value,
    256 						ava->la_flags, &vl ) ) {
    257 				goto error_return;
    258 			}
    259 		}
    260 
    261 		if ( !notypes ) {
    262 			al = ava->la_attr.bv_len;
    263 			l = vl + ava->la_attr.bv_len + 1;
    264 
    265 			str = LDAP_MALLOC( l + 1 );
    266 			if ( str == NULL ) {
    267 				goto error_return;
    268 			}
    269 			AC_MEMCPY( str, ava->la_attr.bv_val,
    270 					ava->la_attr.bv_len );
    271 			str[ al++ ] = '=';
    272 
    273 		} else {
    274 			l = vl;
    275 			str = LDAP_MALLOC( l + 1 );
    276 			if ( str == NULL ) {
    277 				goto error_return;
    278 			}
    279 		}
    280 
    281 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
    282 			str[ al++ ] = '#';
    283 			if ( binval2hexstr( &ava->la_value, &str[ al ] ) ) {
    284 				goto error_return;
    285 			}
    286 
    287 		} else {
    288 			if ( strval2str( &ava->la_value, &str[ al ],
    289 					ava->la_flags, &vl ) ) {
    290 				goto error_return;
    291 			}
    292 		}
    293 
    294 		str[ l ] = '\0';
    295 		values[ iAVA ] = str;
    296 	}
    297 	values[ iAVA ] = NULL;
    298 
    299 	ldap_rdnfree( tmpRDN );
    300 
    301 	return( values );
    302 
    303 error_return:;
    304 	LBER_VFREE( values );
    305 	ldap_rdnfree( tmpRDN );
    306 	return( NULL );
    307 }
    308 
    309 char *
    310 ldap_dn2dcedn( LDAP_CONST char *dn )
    311 {
    312 	char	*out = NULL;
    313 
    314 	Debug0( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n" );
    315 
    316 	( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
    317 				   &out, LDAP_DN_FORMAT_DCE );
    318 
    319 	return( out );
    320 }
    321 
    322 char *
    323 ldap_dcedn2dn( LDAP_CONST char *dce )
    324 {
    325 	char	*out = NULL;
    326 
    327 	Debug0( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n" );
    328 
    329 	( void )ldap_dn_normalize( dce, LDAP_DN_FORMAT_DCE, &out, LDAP_DN_FORMAT_LDAPV3 );
    330 
    331 	return( out );
    332 }
    333 
    334 char *
    335 ldap_dn2ad_canonical( LDAP_CONST char *dn )
    336 {
    337 	char	*out = NULL;
    338 
    339 	Debug0( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n" );
    340 
    341 	( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
    342 		       &out, LDAP_DN_FORMAT_AD_CANONICAL );
    343 
    344 	return( out );
    345 }
    346 
    347 /*
    348  * function that changes the string representation of dnin
    349  * from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK )
    350  *
    351  * fin can be one of:
    352  * 	LDAP_DN_FORMAT_LDAP		(RFC 4514 liberal, plus some RFC 1779)
    353  * 	LDAP_DN_FORMAT_LDAPV3	(RFC 4514)
    354  * 	LDAP_DN_FORMAT_LDAPV2	(RFC 1779)
    355  * 	LDAP_DN_FORMAT_DCE		(?)
    356  *
    357  * fout can be any of the above except
    358  * 	LDAP_DN_FORMAT_LDAP
    359  * plus:
    360  * 	LDAP_DN_FORMAT_UFN		(RFC 1781, partial and with extensions)
    361  * 	LDAP_DN_FORMAT_AD_CANONICAL	(?)
    362  */
    363 int
    364 ldap_dn_normalize( LDAP_CONST char *dnin,
    365 	unsigned fin, char **dnout, unsigned fout )
    366 {
    367 	int	rc;
    368 	LDAPDN	tmpDN = NULL;
    369 
    370 	Debug0( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n" );
    371 
    372 	assert( dnout != NULL );
    373 
    374 	*dnout = NULL;
    375 
    376 	if ( dnin == NULL ) {
    377 		return( LDAP_SUCCESS );
    378 	}
    379 
    380 	rc = ldap_str2dn( dnin , &tmpDN, fin );
    381 	if ( rc != LDAP_SUCCESS ) {
    382 		return( rc );
    383 	}
    384 
    385 	rc = ldap_dn2str( tmpDN, dnout, fout );
    386 
    387 	ldap_dnfree( tmpDN );
    388 
    389 	return( rc );
    390 }
    391 
    392 /* States */
    393 #define B4AVA			0x0000
    394 
    395 /* #define	B4ATTRTYPE		0x0001 */
    396 #define B4OIDATTRTYPE		0x0002
    397 #define B4STRINGATTRTYPE	0x0003
    398 
    399 #define B4AVAEQUALS		0x0100
    400 #define B4AVASEP		0x0200
    401 #define B4RDNSEP		0x0300
    402 #define GOTAVA			0x0400
    403 
    404 #define B4ATTRVALUE		0x0010
    405 #define B4STRINGVALUE		0x0020
    406 #define B4IA5VALUEQUOTED	0x0030
    407 #define B4IA5VALUE		0x0040
    408 #define B4BINARYVALUE		0x0050
    409 
    410 /*
    411  * Helpers (mostly from slap.h)
    412  * c is assumed to Unicode in an ASCII compatible format (UTF-8)
    413  * Macros assume "C" Locale (ASCII)
    414  */
    415 #define LDAP_DN_ASCII_SPACE(c) \
    416 	( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' )
    417 #define LDAP_DN_ASCII_LOWER(c)		LDAP_LOWER(c)
    418 #define LDAP_DN_ASCII_UPPER(c)		LDAP_UPPER(c)
    419 #define LDAP_DN_ASCII_ALPHA(c)		LDAP_ALPHA(c)
    420 
    421 #define LDAP_DN_ASCII_DIGIT(c)		LDAP_DIGIT(c)
    422 #define LDAP_DN_ASCII_LCASE_HEXALPHA(c)	LDAP_HEXLOWER(c)
    423 #define LDAP_DN_ASCII_UCASE_HEXALPHA(c)	LDAP_HEXUPPER(c)
    424 #define LDAP_DN_ASCII_HEXDIGIT(c)	LDAP_HEX(c)
    425 #define LDAP_DN_ASCII_ALNUM(c)		LDAP_ALNUM(c)
    426 #define LDAP_DN_ASCII_PRINTABLE(c)	( (c) >= ' ' && (c) <= '~' )
    427 
    428 /* attribute type */
    429 #define LDAP_DN_OID_LEADCHAR(c)		LDAP_DIGIT(c)
    430 #define LDAP_DN_DESC_LEADCHAR(c)	LDAP_ALPHA(c)
    431 #define LDAP_DN_DESC_CHAR(c)		LDAP_LDH(c)
    432 #define LDAP_DN_LANG_SEP(c)		( (c) == ';' )
    433 #define LDAP_DN_ATTRDESC_CHAR(c) \
    434 	( LDAP_DN_DESC_CHAR(c) || LDAP_DN_LANG_SEP(c) )
    435 
    436 /* special symbols */
    437 #define LDAP_DN_AVA_EQUALS(c)		( (c) == '=' )
    438 #define LDAP_DN_AVA_SEP(c)		( (c) == '+' )
    439 #define LDAP_DN_RDN_SEP(c)		( (c) == ',' )
    440 #define LDAP_DN_RDN_SEP_V2(c)		( LDAP_DN_RDN_SEP(c) || (c) == ';' )
    441 #define LDAP_DN_OCTOTHORPE(c)		( (c) == '#' )
    442 #define LDAP_DN_QUOTES(c)		( (c) == '\"' )
    443 #define LDAP_DN_ESCAPE(c)		( (c) == '\\' )
    444 #define LDAP_DN_VALUE_END(c) \
    445 	( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) )
    446 
    447 /* NOTE: according to RFC 4514, '=' can be escaped and treated as special,
    448  * i.e. escaped both as "\<hexpair>" and * as "\=", but it is treated as
    449  * a regular char, i.e. it can also appear as '='.
    450  *
    451  * As such, in 2.2 we used to allow reading unescaped '=', but we always
    452  * produced escaped '\3D'; this changes since 2.3, if compatibility issues
    453  * do not arise
    454  */
    455 #define LDAP_DN_NE(c) \
    456 	( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
    457 	  || LDAP_DN_QUOTES(c) \
    458 	  || (c) == '<' || (c) == '>' )
    459 #define LDAP_DN_MAYESCAPE(c) \
    460 	( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \
    461 	  || LDAP_DN_AVA_EQUALS(c) \
    462 	  || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) )
    463 #define LDAP_DN_SHOULDESCAPE(c)		( LDAP_DN_AVA_EQUALS(c) )
    464 
    465 #define LDAP_DN_NEEDESCAPE(c) \
    466 	( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) )
    467 #define LDAP_DN_NEEDESCAPE_LEAD(c) 	LDAP_DN_MAYESCAPE(c)
    468 #define LDAP_DN_NEEDESCAPE_TRAIL(c) \
    469 	( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) )
    470 #define LDAP_DN_WILLESCAPE_CHAR(c) \
    471 	( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) || LDAP_DN_ESCAPE(c) )
    472 #define LDAP_DN_IS_PRETTY(f)		( (f) & LDAP_DN_PRETTY )
    473 #define LDAP_DN_WILLESCAPE_HEX(f, c) \
    474 	( ( !LDAP_DN_IS_PRETTY( f ) ) && LDAP_DN_WILLESCAPE_CHAR(c) )
    475 
    476 /* LDAPv2 */
    477 #define	LDAP_DN_VALUE_END_V2(c) \
    478 	( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) )
    479 /* RFC 1779 */
    480 #define	LDAP_DN_V2_SPECIAL(c) \
    481 	  ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_EQUALS(c) \
    482 	    || LDAP_DN_AVA_SEP(c) || (c) == '<' || (c) == '>' \
    483 	    || LDAP_DN_OCTOTHORPE(c) )
    484 #define LDAP_DN_V2_PAIR(c) \
    485 	  ( LDAP_DN_V2_SPECIAL(c) || LDAP_DN_ESCAPE(c) || LDAP_DN_QUOTES(c) )
    486 
    487 /*
    488  * DCE (mostly from Luke Howard and IBM implementation for AIX)
    489  *
    490  * From: "Application Development Guide - Directory Services" (FIXME: add link?)
    491  * Here escapes and valid chars for GDS are considered; as soon as more
    492  * specific info is found, the macros will be updated.
    493  *
    494  * Chars:	'a'-'z', 'A'-'Z', '0'-'9',
    495  *		'.', ':', ',', ''', '+', '-', '=', '(', ')', '?', '/', ' '.
    496  *
    497  * Metachars:	'/', ',', '=', '\'.
    498  *
    499  * the '\' is used to escape other metachars.
    500  *
    501  * Assertion:		'='
    502  * RDN separator:	'/'
    503  * AVA separator:	','
    504  *
    505  * Attribute types must start with alphabetic chars and can contain
    506  * alphabetic chars and digits (FIXME: no '-'?). OIDs are allowed.
    507  */
    508 #define LDAP_DN_RDN_SEP_DCE(c)		( (c) == '/' )
    509 #define LDAP_DN_AVA_SEP_DCE(c)		( (c) == ',' )
    510 #define LDAP_DN_ESCAPE_DCE(c)		( LDAP_DN_ESCAPE(c) )
    511 #define	LDAP_DN_VALUE_END_DCE(c) \
    512 	( LDAP_DN_RDN_SEP_DCE(c) || LDAP_DN_AVA_SEP_DCE(c) )
    513 #define LDAP_DN_NEEDESCAPE_DCE(c) \
    514 	( LDAP_DN_VALUE_END_DCE(c) || LDAP_DN_AVA_EQUALS(c) )
    515 
    516 /* AD Canonical */
    517 #define LDAP_DN_RDN_SEP_AD(c)		( (c) == '/' )
    518 #define LDAP_DN_ESCAPE_AD(c)		( LDAP_DN_ESCAPE(c) )
    519 #define LDAP_DN_AVA_SEP_AD(c)		( (c) == ',' )	/* assume same as DCE */
    520 #define	LDAP_DN_VALUE_END_AD(c) \
    521 	( LDAP_DN_RDN_SEP_AD(c) || LDAP_DN_AVA_SEP_AD(c) )
    522 #define LDAP_DN_NEEDESCAPE_AD(c) \
    523 	( LDAP_DN_VALUE_END_AD(c) || LDAP_DN_AVA_EQUALS(c) )
    524 
    525 /* generics */
    526 #define LDAP_DN_HEXPAIR(s) \
    527 	( LDAP_DN_ASCII_HEXDIGIT((s)[0]) && LDAP_DN_ASCII_HEXDIGIT((s)[1]) )
    528 /* better look at the AttributeDescription? */
    529 
    530 /* FIXME: no composite rdn or non-"dc" types, right?
    531  * (what about "dc" in OID form?) */
    532 /* FIXME: we do not allow binary values in domain, right? */
    533 /* NOTE: use this macro only when ABSOLUTELY SURE rdn IS VALID! */
    534 /* NOTE: don't use strcasecmp() as it is locale specific! */
    535 #define	LDAP_DC_ATTR	"dc"
    536 #define	LDAP_DC_ATTRU	"DC"
    537 #define LDAP_DN_IS_RDN_DC( r ) \
    538 	( (r) && (r)[0] && !(r)[1] \
    539 	  && ((r)[0]->la_flags & LDAP_AVA_STRING) \
    540 	  && ((r)[0]->la_attr.bv_len == 2) \
    541 	  && (((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTR[0]) \
    542 		|| ((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTRU[0])) \
    543 	  && (((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTR[1]) \
    544 		|| ((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTRU[1])))
    545 
    546 /* Composite rules */
    547 #define LDAP_DN_ALLOW_ONE_SPACE(f) \
    548 	( LDAP_DN_LDAPV2(f) \
    549 	  || !( (f) & LDAP_DN_P_NOSPACEAFTERRDN ) )
    550 #define LDAP_DN_ALLOW_SPACES(f) \
    551 	( LDAP_DN_LDAPV2(f) \
    552 	  || !( (f) & ( LDAP_DN_P_NOLEADTRAILSPACES | LDAP_DN_P_NOSPACEAFTERRDN ) ) )
    553 #define LDAP_DN_LDAP(f) \
    554 	( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAP )
    555 #define LDAP_DN_LDAPV3(f) \
    556 	( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV3 )
    557 #define LDAP_DN_LDAPV2(f) \
    558 	( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV2 )
    559 #define LDAP_DN_DCE(f) \
    560 	( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_DCE )
    561 #define LDAP_DN_UFN(f) \
    562 	( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_UFN )
    563 #define LDAP_DN_ADC(f) \
    564 	( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_AD_CANONICAL )
    565 #define LDAP_DN_FORMAT(f)		( (f) & LDAP_DN_FORMAT_MASK )
    566 
    567 /*
    568  * LDAPAVA helpers (will become part of the API for operations
    569  * on structural representations of DNs).
    570  */
    571 static LDAPAVA *
    572 ldapava_new( const struct berval *attr, const struct berval *val,
    573 		unsigned flags, void *ctx )
    574 {
    575 	LDAPAVA *ava;
    576 
    577 	assert( attr != NULL );
    578 	assert( val != NULL );
    579 
    580 	ava = LDAP_MALLOCX( sizeof( LDAPAVA ) + attr->bv_len + 1, ctx );
    581 
    582 	if ( ava ) {
    583 		ava->la_attr.bv_len = attr->bv_len;
    584 		ava->la_attr.bv_val = (char *)(ava+1);
    585 		AC_MEMCPY( ava->la_attr.bv_val, attr->bv_val, attr->bv_len );
    586 		ava->la_attr.bv_val[attr->bv_len] = '\0';
    587 
    588 		ava->la_value = *val;
    589 		ava->la_flags = flags | LDAP_AVA_FREE_VALUE;
    590 
    591 		ava->la_private = NULL;
    592 	}
    593 
    594 	return( ava );
    595 }
    596 
    597 static void
    598 ldapava_free( LDAPAVA *ava, void *ctx )
    599 {
    600 	assert( ava != NULL );
    601 
    602 #if 0
    603 	/* ava's private must be freed by caller
    604 	 * (at present let's skip this check because la_private
    605 	 * basically holds static data) */
    606 	assert( ava->la_private == NULL );
    607 #endif
    608 
    609 	if (ava->la_flags & LDAP_AVA_FREE_VALUE)
    610 		LDAP_FREEX( ava->la_value.bv_val, ctx );
    611 
    612 	LDAP_FREEX( ava, ctx );
    613 }
    614 
    615 void
    616 ldap_rdnfree( LDAPRDN rdn )
    617 {
    618 	ldap_rdnfree_x( rdn, NULL );
    619 }
    620 
    621 void
    622 ldap_rdnfree_x( LDAPRDN rdn, void *ctx )
    623 {
    624 	int iAVA;
    625 
    626 	if ( rdn == NULL ) {
    627 		return;
    628 	}
    629 
    630 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
    631 		ldapava_free( rdn[ iAVA ], ctx );
    632 	}
    633 
    634 	LDAP_FREEX( rdn, ctx );
    635 }
    636 
    637 void
    638 ldap_dnfree( LDAPDN dn )
    639 {
    640 	ldap_dnfree_x( dn, NULL );
    641 }
    642 
    643 void
    644 ldap_dnfree_x( LDAPDN dn, void *ctx )
    645 {
    646 	int iRDN;
    647 
    648 	if ( dn == NULL ) {
    649 		return;
    650 	}
    651 
    652 	for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
    653 		ldap_rdnfree_x( dn[ iRDN ], ctx );
    654 	}
    655 
    656 	LDAP_FREEX( dn, ctx );
    657 }
    658 
    659 /*
    660  * Converts a string representation of a DN (in LDAPv3, LDAPv2 or DCE)
    661  * into a structural representation of the DN, by separating attribute
    662  * types and values encoded in the more appropriate form, which is
    663  * string or OID for attribute types and binary form of the BER encoded
    664  * value or Unicode string. Formats different from LDAPv3 are parsed
    665  * according to their own rules and turned into the more appropriate
    666  * form according to LDAPv3.
    667  *
    668  * NOTE: I realize the code is getting spaghettish; it is rather
    669  * experimental and will hopefully turn into something more simple
    670  * and readable as soon as it works as expected.
    671  */
    672 
    673 /*
    674  * Default sizes of AVA and RDN static working arrays; if required
    675  * the are dynamically resized.  The values can be tuned in case
    676  * of special requirements (e.g. very deep DN trees or high number
    677  * of AVAs per RDN).
    678  */
    679 #define	TMP_AVA_SLOTS	8
    680 #define	TMP_RDN_SLOTS	32
    681 
    682 int
    683 ldap_str2dn( LDAP_CONST char *str, LDAPDN *dn, unsigned flags )
    684 {
    685 	struct berval	bv;
    686 
    687 	assert( str != NULL );
    688 
    689 	bv.bv_len = strlen( str );
    690 	bv.bv_val = (char *) str;
    691 
    692 	return ldap_bv2dn_x( &bv, dn, flags, NULL );
    693 }
    694 
    695 int
    696 ldap_bv2dn( struct berval *bv, LDAPDN *dn, unsigned flags )
    697 {
    698 	return ldap_bv2dn_x( bv, dn, flags, NULL );
    699 }
    700 
    701 int
    702 ldap_bv2dn_x( struct berval *bvin, LDAPDN *dn, unsigned flags, void *ctx )
    703 {
    704 	const char 	*p;
    705 	int		rc = LDAP_DECODING_ERROR;
    706 	int		nrdns = 0;
    707 
    708 	LDAPDN		newDN = NULL;
    709 	LDAPRDN		newRDN = NULL, tmpDN_[TMP_RDN_SLOTS], *tmpDN = tmpDN_;
    710 	int		num_slots = TMP_RDN_SLOTS;
    711 	char		*str, *end;
    712 	struct berval	bvtmp, *bv = &bvtmp;
    713 
    714 	assert( bvin != NULL );
    715 	assert( bvin->bv_val != NULL );
    716 	assert( dn != NULL );
    717 
    718 	*bv = *bvin;
    719 	str = bv->bv_val;
    720 	end = str + bv->bv_len;
    721 
    722 	Debug2( LDAP_DEBUG_ARGS, "=> ldap_bv2dn(%s,%u)\n", str, flags );
    723 
    724 	*dn = NULL;
    725 
    726 	switch ( LDAP_DN_FORMAT( flags ) ) {
    727 	case LDAP_DN_FORMAT_LDAP:
    728 	case LDAP_DN_FORMAT_LDAPV3:
    729 	case LDAP_DN_FORMAT_DCE:
    730 		break;
    731 
    732 		/* allow DN enclosed in brackets */
    733 	case LDAP_DN_FORMAT_LDAPV2:
    734 		if ( str[0] == '<' ) {
    735 			if ( bv->bv_len < 2 || end[ -1 ] != '>' ) {
    736 				rc = LDAP_DECODING_ERROR;
    737 				goto parsing_error;
    738 			}
    739 			bv->bv_val++;
    740 			bv->bv_len -= 2;
    741 			str++;
    742 			end--;
    743 		}
    744 		break;
    745 
    746 	/* unsupported in str2dn */
    747 	case LDAP_DN_FORMAT_UFN:
    748 	case LDAP_DN_FORMAT_AD_CANONICAL:
    749 		return LDAP_PARAM_ERROR;
    750 
    751 	case LDAP_DN_FORMAT_LBER:
    752 	default:
    753 		return LDAP_PARAM_ERROR;
    754 	}
    755 
    756 	if ( bv->bv_len == 0 ) {
    757 		return LDAP_SUCCESS;
    758 	}
    759 
    760 	if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) {
    761 		/* value must have embedded NULs */
    762 		return LDAP_DECODING_ERROR;
    763 	}
    764 
    765 	p = str;
    766 	if ( LDAP_DN_DCE( flags ) ) {
    767 
    768 		/*
    769 		 * (from Luke Howard: thnx) A RDN separator is required
    770 		 * at the beginning of an (absolute) DN.
    771 		 */
    772 		if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
    773 			goto parsing_error;
    774 		}
    775 		p++;
    776 
    777 	/*
    778 	 * actually we do not want to accept by default the DCE form,
    779 	 * we do not want to auto-detect it
    780 	 */
    781 #if 0
    782 	} else if ( LDAP_DN_LDAP( flags ) ) {
    783 		/*
    784 		 * if dn starts with '/' let's make it a DCE dn
    785 		 */
    786 		if ( LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
    787 			flags |= LDAP_DN_FORMAT_DCE;
    788 			p++;
    789 		}
    790 #endif
    791 	}
    792 
    793 	for ( ; p < end; p++ ) {
    794 		int		err;
    795 		struct berval 	tmpbv;
    796 		tmpbv.bv_len = bv->bv_len - ( p - str );
    797 		tmpbv.bv_val = (char *)p;
    798 
    799 		err = ldap_bv2rdn_x( &tmpbv, &newRDN, (char **) &p, flags,ctx);
    800 		if ( err != LDAP_SUCCESS ) {
    801 			goto parsing_error;
    802 		}
    803 
    804 		/*
    805 		 * We expect a rdn separator
    806 		 */
    807 		if ( p < end && p[ 0 ] ) {
    808 			switch ( LDAP_DN_FORMAT( flags ) ) {
    809 			case LDAP_DN_FORMAT_LDAPV3:
    810 				if ( !LDAP_DN_RDN_SEP( p[ 0 ] ) ) {
    811 					rc = LDAP_DECODING_ERROR;
    812 					goto parsing_error;
    813 				}
    814 				break;
    815 
    816 			case LDAP_DN_FORMAT_LDAP:
    817 			case LDAP_DN_FORMAT_LDAPV2:
    818 				if ( !LDAP_DN_RDN_SEP_V2( p[ 0 ] ) ) {
    819 					rc = LDAP_DECODING_ERROR;
    820 					goto parsing_error;
    821 				}
    822 				break;
    823 
    824 			case LDAP_DN_FORMAT_DCE:
    825 				if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
    826 					rc = LDAP_DECODING_ERROR;
    827 					goto parsing_error;
    828 				}
    829 				break;
    830 			}
    831 		}
    832 
    833 
    834 		tmpDN[nrdns++] = newRDN;
    835 		newRDN = NULL;
    836 
    837 		/*
    838 		 * make the static RDN array dynamically rescalable
    839 		 */
    840 		if ( nrdns == num_slots ) {
    841 			LDAPRDN	*tmp;
    842 
    843 			if ( tmpDN == tmpDN_ ) {
    844 				tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPRDN * ), ctx );
    845 				if ( tmp == NULL ) {
    846 					rc = LDAP_NO_MEMORY;
    847 					goto parsing_error;
    848 				}
    849 				AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) );
    850 
    851 			} else {
    852 				tmp = LDAP_REALLOCX( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ), ctx );
    853 				if ( tmp == NULL ) {
    854 					rc = LDAP_NO_MEMORY;
    855 					goto parsing_error;
    856 				}
    857 			}
    858 
    859 			tmpDN = tmp;
    860 			num_slots *= 2;
    861 		}
    862 
    863 		if ( p >= end || p[ 0 ] == '\0' ) {
    864 			/*
    865 			 * the DN is over, phew
    866 			 */
    867 			newDN = (LDAPDN)LDAP_MALLOCX( sizeof(LDAPRDN *) * (nrdns+1), ctx );
    868 			if ( newDN == NULL ) {
    869 				rc = LDAP_NO_MEMORY;
    870 				goto parsing_error;
    871 			} else {
    872 				int i;
    873 
    874 				if ( LDAP_DN_DCE( flags ) ) {
    875 					/* add in reversed order */
    876 					for ( i=0; i<nrdns; i++ )
    877 						newDN[i] = tmpDN[nrdns-1-i];
    878 				} else {
    879 					for ( i=0; i<nrdns; i++ )
    880 						newDN[i] = tmpDN[i];
    881 				}
    882 				newDN[nrdns] = NULL;
    883 				rc = LDAP_SUCCESS;
    884 			}
    885 			goto return_result;
    886 		}
    887 	}
    888 
    889 parsing_error:;
    890 	if ( newRDN ) {
    891 		ldap_rdnfree_x( newRDN, ctx );
    892 	}
    893 
    894 	for ( nrdns-- ;nrdns >= 0; nrdns-- ) {
    895 		ldap_rdnfree_x( tmpDN[nrdns], ctx );
    896 	}
    897 
    898 return_result:;
    899 
    900 	if ( tmpDN != tmpDN_ ) {
    901 		LDAP_FREEX( tmpDN, ctx );
    902 	}
    903 
    904 	Debug3( LDAP_DEBUG_ARGS, "<= ldap_bv2dn(%s)=%d %s\n", str, rc,
    905 			rc ? ldap_err2string( rc ) : "" );
    906 	*dn = newDN;
    907 
    908 	return( rc );
    909 }
    910 
    911 /*
    912  * ldap_str2rdn
    913  *
    914  * Parses a relative DN according to flags up to a rdn separator
    915  * or to the end of str.
    916  * Returns the rdn and a pointer to the string continuation, which
    917  * corresponds to the rdn separator or to '\0' in case the string is over.
    918  */
    919 int
    920 ldap_str2rdn( LDAP_CONST char *str, LDAPRDN *rdn,
    921 	char **n_in, unsigned flags )
    922 {
    923 	struct berval	bv;
    924 
    925 	assert( str != NULL );
    926 	assert( str[ 0 ] != '\0' );	/* FIXME: is this required? */
    927 
    928 	bv.bv_len = strlen( str );
    929 	bv.bv_val = (char *) str;
    930 
    931 	return ldap_bv2rdn_x( &bv, rdn, n_in, flags, NULL );
    932 }
    933 
    934 int
    935 ldap_bv2rdn( struct berval *bv, LDAPRDN *rdn,
    936 	char **n_in, unsigned flags )
    937 {
    938 	return ldap_bv2rdn_x( bv, rdn, n_in, flags, NULL );
    939 }
    940 
    941 int
    942 ldap_bv2rdn_x( struct berval *bv, LDAPRDN *rdn,
    943 	char **n_in, unsigned flags, void *ctx )
    944 {
    945 	const char  	**n = (const char **) n_in;
    946 	const char 	*p;
    947 	int		navas = 0;
    948 	int 		state = B4AVA;
    949 	int		rc = LDAP_DECODING_ERROR;
    950 	int		attrTypeEncoding = LDAP_AVA_STRING,
    951 			attrValueEncoding = LDAP_AVA_STRING;
    952 
    953 	struct berval	attrType = BER_BVNULL;
    954 	struct berval 	attrValue = BER_BVNULL;
    955 
    956 	LDAPRDN		newRDN = NULL;
    957 	LDAPAVA		*tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_;
    958 	int		num_slots = TMP_AVA_SLOTS;
    959 
    960 	char		*str;
    961 	ber_len_t	stoplen;
    962 
    963 	assert( bv != NULL );
    964 	assert( bv->bv_len != 0 );
    965 	assert( bv->bv_val != NULL );
    966 	assert( rdn || flags & LDAP_DN_SKIP );
    967 	assert( n != NULL );
    968 
    969 	str = bv->bv_val;
    970 	stoplen = bv->bv_len;
    971 
    972 	if ( rdn ) {
    973 		*rdn = NULL;
    974 	}
    975 	*n = NULL;
    976 
    977 	switch ( LDAP_DN_FORMAT( flags ) ) {
    978 	case LDAP_DN_FORMAT_LDAP:
    979 	case LDAP_DN_FORMAT_LDAPV3:
    980 	case LDAP_DN_FORMAT_LDAPV2:
    981 	case LDAP_DN_FORMAT_DCE:
    982 		break;
    983 
    984 	/* unsupported in str2dn */
    985 	case LDAP_DN_FORMAT_UFN:
    986 	case LDAP_DN_FORMAT_AD_CANONICAL:
    987 		return LDAP_PARAM_ERROR;
    988 
    989 	case LDAP_DN_FORMAT_LBER:
    990 	default:
    991 		return LDAP_PARAM_ERROR;
    992 	}
    993 
    994 	if ( bv->bv_len == 0 ) {
    995 		return LDAP_SUCCESS;
    996 
    997 	}
    998 
    999 	if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) {
   1000 		/* value must have embedded NULs */
   1001 		return LDAP_DECODING_ERROR;
   1002 	}
   1003 
   1004 	p = str;
   1005 	for ( ; p[ 0 ] || state == GOTAVA; ) {
   1006 
   1007 		/*
   1008 		 * The parser in principle advances one token a time,
   1009 		 * or toggles state if preferable.
   1010 		 */
   1011 		switch (state) {
   1012 
   1013 		/*
   1014 		 * an AttributeType can be encoded as:
   1015 		 * - its string representation; in detail, implementations
   1016 		 *   MUST recognize AttributeType string type names listed
   1017 		 *   in Section 3 of RFC 4514, and MAY recognize other names.
   1018 		 * - its numeric OID (a dotted decimal string)
   1019 		 */
   1020 		case B4AVA:
   1021 			if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
   1022 				if ( !LDAP_DN_ALLOW_ONE_SPACE( flags ) ) {
   1023 					/* error */
   1024 					goto parsing_error;
   1025 				}
   1026 				p++;
   1027 			}
   1028 
   1029 			if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
   1030 				if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
   1031 					/* error */
   1032 					goto parsing_error;
   1033 				}
   1034 
   1035 				/* whitespace is allowed (and trimmed) */
   1036 				p++;
   1037 				while ( p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
   1038 					p++;
   1039 				}
   1040 
   1041 				if ( !p[ 0 ] ) {
   1042 					/* error: we expected an AVA */
   1043 					goto parsing_error;
   1044 				}
   1045 			}
   1046 
   1047 			/* oid */
   1048 			if ( LDAP_DN_OID_LEADCHAR( p[ 0 ] ) ) {
   1049 				state = B4OIDATTRTYPE;
   1050 				break;
   1051 			}
   1052 
   1053 			/* else must be alpha */
   1054 			if ( !LDAP_DN_DESC_LEADCHAR( p[ 0 ] ) ) {
   1055 				goto parsing_error;
   1056 			}
   1057 
   1058 			/* LDAPv2 "oid." prefix */
   1059 			if ( LDAP_DN_LDAPV2( flags ) ) {
   1060 				/*
   1061 				 * to be overly pedantic, we only accept
   1062 				 * "OID." or "oid."
   1063 				 */
   1064 				if ( flags & LDAP_DN_PEDANTIC ) {
   1065 					if ( !strncmp( p, "OID.", 4 )
   1066 						|| !strncmp( p, "oid.", 4 ) ) {
   1067 						p += 4;
   1068 						state = B4OIDATTRTYPE;
   1069 						break;
   1070 					}
   1071 				} else {
   1072 				       if ( !strncasecmp( p, "oid.", 4 ) ) {
   1073 					       p += 4;
   1074 					       state = B4OIDATTRTYPE;
   1075 					       break;
   1076 				       }
   1077 				}
   1078 			}
   1079 
   1080 			state = B4STRINGATTRTYPE;
   1081 			break;
   1082 
   1083 		case B4OIDATTRTYPE: {
   1084 			int 		err = LDAP_SUCCESS;
   1085 
   1086 			attrType.bv_val = ldap_int_parse_numericoid( &p, &err,
   1087 				LDAP_SCHEMA_SKIP);
   1088 
   1089 			if ( err != LDAP_SUCCESS ) {
   1090 				goto parsing_error;
   1091 			}
   1092 			attrType.bv_len = p - attrType.bv_val;
   1093 
   1094 			attrTypeEncoding = LDAP_AVA_BINARY;
   1095 
   1096 			state = B4AVAEQUALS;
   1097 			break;
   1098 		}
   1099 
   1100 		case B4STRINGATTRTYPE: {
   1101 			const char 	*startPos, *endPos = NULL;
   1102 			ber_len_t 	len;
   1103 
   1104 			/*
   1105 			 * the starting char has been found to be
   1106 			 * a LDAP_DN_DESC_LEADCHAR so we don't re-check it
   1107 			 * FIXME: DCE attr types seem to have a more
   1108 			 * restrictive syntax (no '-' ...)
   1109 			 */
   1110 			for ( startPos = p++; p[ 0 ]; p++ ) {
   1111 				if ( LDAP_DN_DESC_CHAR( p[ 0 ] ) ) {
   1112 					continue;
   1113 				}
   1114 
   1115 				if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) {
   1116 
   1117 					/*
   1118 					 * RFC 4514 explicitly does not allow attribute
   1119 					 * description options, such as language tags.
   1120 					 */
   1121 					if ( flags & LDAP_DN_PEDANTIC ) {
   1122 						goto parsing_error;
   1123 					}
   1124 
   1125 					/*
   1126 					 * we trim ';' and following lang
   1127 					 * and so from attribute types
   1128 					 */
   1129 					endPos = p;
   1130 					for ( ; LDAP_DN_ATTRDESC_CHAR( p[ 0 ] )
   1131 							|| LDAP_DN_LANG_SEP( p[ 0 ] ); p++ ) {
   1132 						/* no op */ ;
   1133 					}
   1134 					break;
   1135 				}
   1136 				break;
   1137 			}
   1138 
   1139 			len = ( endPos ? endPos : p ) - startPos;
   1140 			if ( len == 0 ) {
   1141 				goto parsing_error;
   1142 			}
   1143 
   1144 			attrTypeEncoding = LDAP_AVA_STRING;
   1145 
   1146 			/*
   1147 			 * here we need to decide whether to use it as is
   1148 			 * or turn it in OID form; as a consequence, we
   1149 			 * need to decide whether to binary encode the value
   1150 			 */
   1151 
   1152 			state = B4AVAEQUALS;
   1153 
   1154 			if ( flags & LDAP_DN_SKIP ) {
   1155 				break;
   1156 			}
   1157 
   1158 			attrType.bv_val = (char *)startPos;
   1159 			attrType.bv_len = len;
   1160 
   1161 			break;
   1162 		}
   1163 
   1164 		case B4AVAEQUALS:
   1165 			/* spaces may not be allowed */
   1166 			if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
   1167 				if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
   1168 					goto parsing_error;
   1169 				}
   1170 
   1171 				/* trim spaces */
   1172 				for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
   1173 					/* no op */
   1174 				}
   1175 			}
   1176 
   1177 			/* need equal sign */
   1178 			if ( !LDAP_DN_AVA_EQUALS( p[ 0 ] ) ) {
   1179 				goto parsing_error;
   1180 			}
   1181 			p++;
   1182 
   1183 			/* spaces may not be allowed */
   1184 			if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
   1185 				if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
   1186 					goto parsing_error;
   1187 				}
   1188 
   1189 				/* trim spaces */
   1190 				for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
   1191 					/* no op */
   1192 				}
   1193 			}
   1194 
   1195 			/*
   1196 			 * octothorpe means a BER encoded value will follow
   1197 			 * FIXME: I don't think DCE will allow it
   1198 			 */
   1199 			if ( LDAP_DN_OCTOTHORPE( p[ 0 ] ) ) {
   1200 				p++;
   1201 				attrValueEncoding = LDAP_AVA_BINARY;
   1202 				state = B4BINARYVALUE;
   1203 				break;
   1204 			}
   1205 
   1206 			/* STRING value expected */
   1207 
   1208 			/*
   1209 			 * if we're pedantic, an attribute type in OID form
   1210 			 * SHOULD imply a BER encoded attribute value; we
   1211 			 * should at least issue a warning
   1212 			 */
   1213 			if ( ( flags & LDAP_DN_PEDANTIC )
   1214 				&& ( attrTypeEncoding == LDAP_AVA_BINARY ) ) {
   1215 				/* OID attrType SHOULD use binary encoding */
   1216 				goto parsing_error;
   1217 			}
   1218 
   1219 			attrValueEncoding = LDAP_AVA_STRING;
   1220 
   1221 			/*
   1222 			 * LDAPv2 allows the attribute value to be quoted;
   1223 			 * also, IA5 values are expected, in principle
   1224 			 */
   1225 			if ( LDAP_DN_LDAPV2( flags ) || LDAP_DN_LDAP( flags ) ) {
   1226 				if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
   1227 					p++;
   1228 					state = B4IA5VALUEQUOTED;
   1229 					break;
   1230 				}
   1231 
   1232 				if ( LDAP_DN_LDAPV2( flags ) ) {
   1233 					state = B4IA5VALUE;
   1234 					break;
   1235 				}
   1236 			}
   1237 
   1238 			/*
   1239 			 * here STRING means RFC 4514 string
   1240 			 * FIXME: what about DCE strings?
   1241 			 */
   1242 			if ( !p[ 0 ] ) {
   1243 				/* empty value */
   1244 				state = GOTAVA;
   1245 			} else {
   1246 				state = B4STRINGVALUE;
   1247 			}
   1248 			break;
   1249 
   1250 		case B4BINARYVALUE:
   1251 			if ( hexstr2binval( p, &attrValue, &p, flags, ctx ) ) {
   1252 				goto parsing_error;
   1253 			}
   1254 
   1255 			state = GOTAVA;
   1256 			break;
   1257 
   1258 		case B4STRINGVALUE:
   1259 			switch ( LDAP_DN_FORMAT( flags ) ) {
   1260 			case LDAP_DN_FORMAT_LDAP:
   1261 			case LDAP_DN_FORMAT_LDAPV3:
   1262 				if ( str2strval( p, stoplen - ( p - str ),
   1263 							&attrValue, &p, flags,
   1264 							&attrValueEncoding, ctx ) ) {
   1265 					goto parsing_error;
   1266 				}
   1267 				break;
   1268 
   1269 			case LDAP_DN_FORMAT_DCE:
   1270 				if ( DCE2strval( p, &attrValue, &p, flags, ctx ) ) {
   1271 					goto parsing_error;
   1272 				}
   1273 				break;
   1274 
   1275 			default:
   1276 				assert( 0 );
   1277 			}
   1278 
   1279 			state = GOTAVA;
   1280 			break;
   1281 
   1282 		case B4IA5VALUE:
   1283 			if ( IA52strval( p, &attrValue, &p, flags, ctx ) ) {
   1284 				goto parsing_error;
   1285 			}
   1286 
   1287 			state = GOTAVA;
   1288 			break;
   1289 
   1290 		case B4IA5VALUEQUOTED:
   1291 
   1292 			/* lead quote already stripped */
   1293 			if ( quotedIA52strval( p, &attrValue,
   1294 						&p, flags, ctx ) ) {
   1295 				goto parsing_error;
   1296 			}
   1297 
   1298 			state = GOTAVA;
   1299 			break;
   1300 
   1301 		case GOTAVA: {
   1302 			int	rdnsep = 0;
   1303 
   1304 			if ( !( flags & LDAP_DN_SKIP ) ) {
   1305 				LDAPAVA *ava;
   1306 
   1307 				/*
   1308 				 * we accept empty values
   1309 				 */
   1310 				ava = ldapava_new( &attrType, &attrValue,
   1311 						attrValueEncoding, ctx );
   1312 				if ( ava == NULL ) {
   1313 					rc = LDAP_NO_MEMORY;
   1314 					goto parsing_error;
   1315 				}
   1316 				tmpRDN[navas++] = ava;
   1317 
   1318 				attrValue.bv_val = NULL;
   1319 				attrValue.bv_len = 0;
   1320 
   1321 				/*
   1322 				 * prepare room for new AVAs if needed
   1323 				 */
   1324 				if (navas == num_slots) {
   1325 					LDAPAVA **tmp;
   1326 
   1327 					if ( tmpRDN == tmpRDN_ ) {
   1328 						tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPAVA * ), ctx );
   1329 						if ( tmp == NULL ) {
   1330 							rc = LDAP_NO_MEMORY;
   1331 							goto parsing_error;
   1332 						}
   1333 						AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) );
   1334 
   1335 					} else {
   1336 						tmp = LDAP_REALLOCX( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ), ctx );
   1337 						if ( tmp == NULL ) {
   1338 							rc = LDAP_NO_MEMORY;
   1339 							goto parsing_error;
   1340 						}
   1341 					}
   1342 
   1343 					tmpRDN = tmp;
   1344 					num_slots *= 2;
   1345 				}
   1346 			}
   1347 
   1348 			/*
   1349 			 * if we got an AVA separator ('+', or ',' for DCE )
   1350 			 * we expect a new AVA for this RDN; otherwise
   1351 			 * we add the RDN to the DN
   1352 			 */
   1353 			switch ( LDAP_DN_FORMAT( flags ) ) {
   1354 			case LDAP_DN_FORMAT_LDAP:
   1355 			case LDAP_DN_FORMAT_LDAPV3:
   1356 			case LDAP_DN_FORMAT_LDAPV2:
   1357 				if ( !LDAP_DN_AVA_SEP( p[ 0 ] ) ) {
   1358 					rdnsep = 1;
   1359 				}
   1360 				break;
   1361 
   1362 			case LDAP_DN_FORMAT_DCE:
   1363 				if ( !LDAP_DN_AVA_SEP_DCE( p[ 0 ] ) ) {
   1364 					rdnsep = 1;
   1365 				}
   1366 				break;
   1367 			}
   1368 
   1369 			if ( rdnsep ) {
   1370 				/*
   1371 				 * the RDN is over, phew
   1372 				 */
   1373 				*n = p;
   1374 				if ( !( flags & LDAP_DN_SKIP ) ) {
   1375 					newRDN = (LDAPRDN)LDAP_MALLOCX(
   1376 						sizeof(LDAPAVA) * (navas+1), ctx );
   1377 					if ( newRDN == NULL ) {
   1378 						rc = LDAP_NO_MEMORY;
   1379 						goto parsing_error;
   1380 					} else {
   1381 						AC_MEMCPY( newRDN, tmpRDN, sizeof(LDAPAVA *) * navas);
   1382 						newRDN[navas] = NULL;
   1383 					}
   1384 
   1385 				}
   1386 				rc = LDAP_SUCCESS;
   1387 				goto return_result;
   1388 			}
   1389 
   1390 			/* they should have been used in an AVA */
   1391 			attrType.bv_val = NULL;
   1392 			attrValue.bv_val = NULL;
   1393 
   1394 			p++;
   1395 			state = B4AVA;
   1396 			break;
   1397 		}
   1398 
   1399 		default:
   1400 			assert( 0 );
   1401 			goto parsing_error;
   1402 		}
   1403 	}
   1404 	*n = p;
   1405 
   1406 parsing_error:;
   1407 	/* They are set to NULL after they're used in an AVA */
   1408 
   1409 	if ( attrValue.bv_val ) {
   1410 		LDAP_FREEX( attrValue.bv_val, ctx );
   1411 	}
   1412 
   1413 	for ( navas-- ; navas >= 0; navas-- ) {
   1414 		ldapava_free( tmpRDN[navas], ctx );
   1415 	}
   1416 
   1417 return_result:;
   1418 
   1419 	if ( tmpRDN != tmpRDN_ ) {
   1420 		LDAP_FREEX( tmpRDN, ctx );
   1421 	}
   1422 
   1423 	if ( rdn ) {
   1424 		*rdn = newRDN;
   1425 	}
   1426 
   1427 	return( rc );
   1428 }
   1429 
   1430 /*
   1431  * reads in a UTF-8 string value, unescaping stuff:
   1432  * '\' + LDAP_DN_NEEDESCAPE(c) -> 'c'
   1433  * '\' + HEXPAIR(p) -> unhex(p)
   1434  */
   1435 static int
   1436 str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char **next, unsigned flags, int *retFlags, void *ctx )
   1437 {
   1438 	const char 	*p, *end, *startPos, *endPos = NULL;
   1439 	ber_len_t	len, escapes;
   1440 
   1441 	assert( str != NULL );
   1442 	assert( val != NULL );
   1443 	assert( next != NULL );
   1444 
   1445 	*next = NULL;
   1446 	end = str + stoplen;
   1447 	for ( startPos = p = str, escapes = 0; p < end; p++ ) {
   1448 		if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
   1449 			p++;
   1450 			if ( p[ 0 ] == '\0' ) {
   1451 				return( 1 );
   1452 			}
   1453 			if ( LDAP_DN_MAYESCAPE( p[ 0 ] ) ) {
   1454 				escapes++;
   1455 				continue;
   1456 			}
   1457 
   1458 			if ( LDAP_DN_HEXPAIR( p ) ) {
   1459 				char c;
   1460 
   1461 				hexstr2bin( p, &c );
   1462 				escapes += 2;
   1463 
   1464 				if ( !LDAP_DN_ASCII_PRINTABLE( c ) ) {
   1465 
   1466 					/*
   1467 					 * we assume the string is UTF-8
   1468 					 */
   1469 					*retFlags = LDAP_AVA_NONPRINTABLE;
   1470 				}
   1471 				p++;
   1472 
   1473 				continue;
   1474 			}
   1475 
   1476 			if ( LDAP_DN_PEDANTIC & flags ) {
   1477 				return( 1 );
   1478 			}
   1479 			/*
   1480 			 * we do not allow escaping
   1481 			 * of chars that don't need
   1482 			 * to and do not belong to
   1483 			 * HEXDIGITS
   1484 			 */
   1485 			return( 1 );
   1486 
   1487 		} else if ( !LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) {
   1488 			if ( p[ 0 ] == '\0' ) {
   1489 				return( 1 );
   1490 			}
   1491 			*retFlags = LDAP_AVA_NONPRINTABLE;
   1492 
   1493 		} else if ( ( LDAP_DN_LDAP( flags ) && LDAP_DN_VALUE_END_V2( p[ 0 ] ) )
   1494 				|| ( LDAP_DN_LDAPV3( flags ) && LDAP_DN_VALUE_END( p[ 0 ] ) ) ) {
   1495 			break;
   1496 
   1497 		} else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
   1498 			/*
   1499 			 * FIXME: maybe we can add
   1500 			 * escapes if not pedantic?
   1501 			 */
   1502 			return( 1 );
   1503 		}
   1504 	}
   1505 
   1506 	/*
   1507 	 * we do allow unescaped spaces at the end
   1508 	 * of the value only in non-pedantic mode
   1509 	 */
   1510 	if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
   1511 			!LDAP_DN_ESCAPE( p[ -2 ] ) ) {
   1512 		if ( flags & LDAP_DN_PEDANTIC ) {
   1513 			return( 1 );
   1514 		}
   1515 
   1516 		/* strip trailing (unescaped) spaces */
   1517 		for ( endPos = p - 1;
   1518 				endPos > startPos + 1 &&
   1519 				LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
   1520 				!LDAP_DN_ESCAPE( endPos[ -2 ] );
   1521 				endPos-- ) {
   1522 			/* no op */
   1523 		}
   1524 	}
   1525 
   1526 	*next = p;
   1527 	if ( flags & LDAP_DN_SKIP ) {
   1528 		return( 0 );
   1529 	}
   1530 
   1531 	/*
   1532 	 * FIXME: test memory?
   1533 	 */
   1534 	len = ( endPos ? endPos : p ) - startPos - escapes;
   1535 	val->bv_len = len;
   1536 
   1537 	if ( escapes == 0 ) {
   1538 		if ( *retFlags & LDAP_AVA_NONPRINTABLE ) {
   1539 			val->bv_val = LDAP_MALLOCX( len + 1, ctx );
   1540 			if ( val->bv_val == NULL ) {
   1541 				return( 1 );
   1542 			}
   1543 
   1544 			AC_MEMCPY( val->bv_val, startPos, len );
   1545 			val->bv_val[ len ] = '\0';
   1546 		} else {
   1547 			val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
   1548 		}
   1549 
   1550 	} else {
   1551 		ber_len_t	s, d;
   1552 
   1553 		val->bv_val = LDAP_MALLOCX( len + 1, ctx );
   1554 		if ( val->bv_val == NULL ) {
   1555 			return( 1 );
   1556 		}
   1557 
   1558 		for ( s = 0, d = 0; d < len; ) {
   1559 			if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
   1560 				s++;
   1561 				if ( LDAP_DN_MAYESCAPE( startPos[ s ] ) ) {
   1562 					val->bv_val[ d++ ] =
   1563 						startPos[ s++ ];
   1564 
   1565 				} else if ( LDAP_DN_HEXPAIR( &startPos[ s ] ) ) {
   1566 					char 	c;
   1567 
   1568 					hexstr2bin( &startPos[ s ], &c );
   1569 					val->bv_val[ d++ ] = c;
   1570 					s += 2;
   1571 
   1572 				} else {
   1573 					/* we should never get here */
   1574 					assert( 0 );
   1575 				}
   1576 
   1577 			} else {
   1578 				val->bv_val[ d++ ] = startPos[ s++ ];
   1579 			}
   1580 		}
   1581 
   1582 		val->bv_val[ d ] = '\0';
   1583 		assert( d == len );
   1584 	}
   1585 
   1586 	return( 0 );
   1587 }
   1588 
   1589 static int
   1590 DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
   1591 {
   1592 	const char 	*p, *startPos, *endPos = NULL;
   1593 	ber_len_t	len, escapes;
   1594 
   1595 	assert( str != NULL );
   1596 	assert( val != NULL );
   1597 	assert( next != NULL );
   1598 
   1599 	*next = NULL;
   1600 
   1601 	for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
   1602 		if ( LDAP_DN_ESCAPE_DCE( p[ 0 ] ) ) {
   1603 			p++;
   1604 			if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
   1605 				escapes++;
   1606 
   1607 			} else {
   1608 				return( 1 );
   1609 			}
   1610 
   1611 		} else if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
   1612 			break;
   1613 		}
   1614 
   1615 		/*
   1616 		 * FIXME: can we accept anything else? I guess we need
   1617 		 * to stop if a value is not legal
   1618 		 */
   1619 	}
   1620 
   1621 	/*
   1622 	 * (unescaped) trailing spaces are trimmed must be silently ignored;
   1623 	 * so we eat them
   1624 	 */
   1625 	if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
   1626 			!LDAP_DN_ESCAPE( p[ -2 ] ) ) {
   1627 		if ( flags & LDAP_DN_PEDANTIC ) {
   1628 			return( 1 );
   1629 		}
   1630 
   1631 		/* strip trailing (unescaped) spaces */
   1632 		for ( endPos = p - 1;
   1633 				endPos > startPos + 1 &&
   1634 				LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
   1635 				!LDAP_DN_ESCAPE( endPos[ -2 ] );
   1636 				endPos-- ) {
   1637 			/* no op */
   1638 		}
   1639 	}
   1640 
   1641 	*next = p;
   1642 	if ( flags & LDAP_DN_SKIP ) {
   1643 		return( 0 );
   1644 	}
   1645 
   1646 	len = ( endPos ? endPos : p ) - startPos - escapes;
   1647 	val->bv_len = len;
   1648 	if ( escapes == 0 ){
   1649 		val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
   1650 
   1651 	} else {
   1652 		ber_len_t	s, d;
   1653 
   1654 		val->bv_val = LDAP_MALLOCX( len + 1, ctx );
   1655 		if ( val->bv_val == NULL ) {
   1656 			return( 1 );
   1657 		}
   1658 
   1659 		for ( s = 0, d = 0; d < len; ) {
   1660 			/*
   1661 			 * This point is reached only if escapes
   1662 			 * are properly used, so all we need to
   1663 			 * do is eat them
   1664 			 */
   1665 			if (  LDAP_DN_ESCAPE_DCE( startPos[ s ] ) ) {
   1666 				s++;
   1667 
   1668 			}
   1669 			val->bv_val[ d++ ] = startPos[ s++ ];
   1670 		}
   1671 		val->bv_val[ d ] = '\0';
   1672 		assert( strlen( val->bv_val ) == len );
   1673 	}
   1674 
   1675 	return( 0 );
   1676 }
   1677 
   1678 static int
   1679 IA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
   1680 {
   1681 	const char 	*p, *startPos, *endPos = NULL;
   1682 	ber_len_t	len, escapes;
   1683 
   1684 	assert( str != NULL );
   1685 	assert( val != NULL );
   1686 	assert( next != NULL );
   1687 
   1688 	*next = NULL;
   1689 
   1690 	/*
   1691 	 * LDAPv2 (RFC 1779)
   1692 	 */
   1693 
   1694 	for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
   1695 		if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
   1696 			p++;
   1697 			if ( p[ 0 ] == '\0' ) {
   1698 				return( 1 );
   1699 			}
   1700 
   1701 			if ( !LDAP_DN_NEEDESCAPE( p[ 0 ] )
   1702 					&& ( LDAP_DN_PEDANTIC & flags ) ) {
   1703 				return( 1 );
   1704 			}
   1705 			escapes++;
   1706 
   1707 		} else if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
   1708 			break;
   1709 		}
   1710 
   1711 		/*
   1712 		 * FIXME: can we accept anything else? I guess we need
   1713 		 * to stop if a value is not legal
   1714 		 */
   1715 	}
   1716 
   1717 	/* strip trailing (unescaped) spaces */
   1718 	for ( endPos = p;
   1719 			endPos > startPos + 1 &&
   1720 			LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
   1721 			!LDAP_DN_ESCAPE( endPos[ -2 ] );
   1722 			endPos-- ) {
   1723 		/* no op */
   1724 	}
   1725 
   1726 	*next = p;
   1727 	if ( flags & LDAP_DN_SKIP ) {
   1728 		return( 0 );
   1729 	}
   1730 
   1731 	len = ( endPos ? endPos : p ) - startPos - escapes;
   1732 	val->bv_len = len;
   1733 	if ( escapes == 0 ) {
   1734 		val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
   1735 
   1736 	} else {
   1737 		ber_len_t	s, d;
   1738 
   1739 		val->bv_val = LDAP_MALLOCX( len + 1, ctx );
   1740 		if ( val->bv_val == NULL ) {
   1741 			return( 1 );
   1742 		}
   1743 
   1744 		for ( s = 0, d = 0; d < len; ) {
   1745 			if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
   1746 				s++;
   1747 			}
   1748 			val->bv_val[ d++ ] = startPos[ s++ ];
   1749 		}
   1750 		val->bv_val[ d ] = '\0';
   1751 		assert( strlen( val->bv_val ) == len );
   1752 	}
   1753 
   1754 	return( 0 );
   1755 }
   1756 
   1757 static int
   1758 quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
   1759 {
   1760 	const char 	*p, *startPos, *endPos = NULL;
   1761 	ber_len_t	len;
   1762 	unsigned	escapes = 0;
   1763 
   1764 	assert( str != NULL );
   1765 	assert( val != NULL );
   1766 	assert( next != NULL );
   1767 
   1768 	*next = NULL;
   1769 
   1770 	/* initial quote already eaten */
   1771 	for ( startPos = p = str; p[ 0 ]; p++ ) {
   1772 		/*
   1773 		 * According to RFC 1779, the quoted value can
   1774 		 * contain escaped as well as unescaped special values;
   1775 		 * as a consequence we tolerate escaped values
   1776 		 * (e.g. '"\,"' -> '\,') and escape unescaped specials
   1777 		 * (e.g. '","' -> '\,').
   1778 		 */
   1779 		if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
   1780 			if ( p[ 1 ] == '\0' ) {
   1781 				return( 1 );
   1782 			}
   1783 			p++;
   1784 
   1785 			if ( !LDAP_DN_V2_PAIR( p[ 0 ] )
   1786 					&& ( LDAP_DN_PEDANTIC & flags ) ) {
   1787 				/*
   1788 				 * do we allow to escape normal chars?
   1789 				 * LDAPv2 does not allow any mechanism
   1790 				 * for escaping chars with '\' and hex
   1791 				 * pair
   1792 				 */
   1793 				return( 1 );
   1794 			}
   1795 			escapes++;
   1796 
   1797 		} else if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
   1798 			endPos = p;
   1799 			/* eat closing quotes */
   1800 			p++;
   1801 			break;
   1802 		}
   1803 
   1804 		/*
   1805 		 * FIXME: can we accept anything else? I guess we need
   1806 		 * to stop if a value is not legal
   1807 		 */
   1808 	}
   1809 
   1810 	if ( endPos == NULL ) {
   1811 		return( 1 );
   1812 	}
   1813 
   1814 	/* Strip trailing (unescaped) spaces */
   1815 	for ( ; p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
   1816 		/* no op */
   1817 	}
   1818 
   1819 	*next = p;
   1820 	if ( flags & LDAP_DN_SKIP ) {
   1821 		return( 0 );
   1822 	}
   1823 
   1824 	len = endPos - startPos - escapes;
   1825 	assert( endPos >= startPos + escapes );
   1826 	val->bv_len = len;
   1827 	if ( escapes == 0 ) {
   1828 		val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
   1829 
   1830 	} else {
   1831 		ber_len_t	s, d;
   1832 
   1833 		val->bv_val = LDAP_MALLOCX( len + 1, ctx );
   1834 		if ( val->bv_val == NULL ) {
   1835 			return( 1 );
   1836 		}
   1837 
   1838 		val->bv_len = len;
   1839 
   1840 		for ( s = d = 0; d < len; ) {
   1841 			if ( LDAP_DN_ESCAPE( str[ s ] ) ) {
   1842 				s++;
   1843 			}
   1844 			val->bv_val[ d++ ] = str[ s++ ];
   1845 		}
   1846 		val->bv_val[ d ] = '\0';
   1847 		assert( strlen( val->bv_val ) == len );
   1848 	}
   1849 
   1850 	return( 0 );
   1851 }
   1852 
   1853 static int
   1854 hexstr2bin( const char *str, char *c )
   1855 {
   1856 	char	c1, c2;
   1857 
   1858 	assert( str != NULL );
   1859 	assert( c != NULL );
   1860 
   1861 	c1 = str[ 0 ];
   1862 	c2 = str[ 1 ];
   1863 
   1864 	if ( LDAP_DN_ASCII_DIGIT( c1 ) ) {
   1865 		*c = c1 - '0';
   1866 
   1867 	} else {
   1868 		if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c1 ) ) {
   1869 			*c = c1 - 'A' + 10;
   1870 		} else {
   1871 			assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c1 ) );
   1872 			*c = c1 - 'a' + 10;
   1873 		}
   1874 	}
   1875 
   1876 	*c <<= 4;
   1877 
   1878 	if ( LDAP_DN_ASCII_DIGIT( c2 ) ) {
   1879 		*c += c2 - '0';
   1880 
   1881 	} else {
   1882 		if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c2 ) ) {
   1883 			*c += c2 - 'A' + 10;
   1884 		} else {
   1885 			assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c2 ) );
   1886 			*c += c2 - 'a' + 10;
   1887 		}
   1888 	}
   1889 
   1890 	return( 0 );
   1891 }
   1892 
   1893 static int
   1894 hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
   1895 {
   1896 	const char 	*p, *startPos, *endPos = NULL;
   1897 	ber_len_t	len;
   1898 	ber_len_t	s, d;
   1899 
   1900 	assert( str != NULL );
   1901 	assert( val != NULL );
   1902 	assert( next != NULL );
   1903 
   1904 	*next = NULL;
   1905 
   1906 	for ( startPos = p = str; p[ 0 ]; p += 2 ) {
   1907 		switch ( LDAP_DN_FORMAT( flags ) ) {
   1908 		case LDAP_DN_FORMAT_LDAPV3:
   1909 			if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
   1910 				goto end_of_value;
   1911 			}
   1912 			break;
   1913 
   1914 		case LDAP_DN_FORMAT_LDAP:
   1915 		case LDAP_DN_FORMAT_LDAPV2:
   1916 			if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
   1917 				goto end_of_value;
   1918 			}
   1919 			break;
   1920 
   1921 		case LDAP_DN_FORMAT_DCE:
   1922 			if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
   1923 				goto end_of_value;
   1924 			}
   1925 			break;
   1926 		}
   1927 
   1928 		if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
   1929 			if ( flags & LDAP_DN_PEDANTIC ) {
   1930 				return( 1 );
   1931 			}
   1932 			endPos = p;
   1933 
   1934 			for ( ; p[ 0 ]; p++ ) {
   1935 				switch ( LDAP_DN_FORMAT( flags ) ) {
   1936 				case LDAP_DN_FORMAT_LDAPV3:
   1937 					if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
   1938 						goto end_of_value;
   1939 					}
   1940 					break;
   1941 
   1942 				case LDAP_DN_FORMAT_LDAP:
   1943 				case LDAP_DN_FORMAT_LDAPV2:
   1944 					if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
   1945 						goto end_of_value;
   1946 					}
   1947 					break;
   1948 
   1949 				case LDAP_DN_FORMAT_DCE:
   1950 					if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
   1951 						goto end_of_value;
   1952 					}
   1953 					break;
   1954 				}
   1955 			}
   1956 			break;
   1957 		}
   1958 
   1959 		if ( !LDAP_DN_HEXPAIR( p ) ) {
   1960 			return( 1 );
   1961 		}
   1962 	}
   1963 
   1964 end_of_value:;
   1965 
   1966 	*next = p;
   1967 	if ( flags & LDAP_DN_SKIP ) {
   1968 		return( 0 );
   1969 	}
   1970 
   1971 	len = ( ( endPos ? endPos : p ) - startPos ) / 2;
   1972 	/* must be even! */
   1973 	assert( 2 * len == (ber_len_t) (( endPos ? endPos : p ) - startPos ));
   1974 
   1975 	val->bv_len = len;
   1976 	val->bv_val = LDAP_MALLOCX( len + 1, ctx );
   1977 	if ( val->bv_val == NULL ) {
   1978 		return( LDAP_NO_MEMORY );
   1979 	}
   1980 
   1981 	for ( s = 0, d = 0; d < len; s += 2, d++ ) {
   1982 		char 	c;
   1983 
   1984 		hexstr2bin( &startPos[ s ], &c );
   1985 
   1986 		val->bv_val[ d ] = c;
   1987 	}
   1988 
   1989 	val->bv_val[ d ] = '\0';
   1990 
   1991 	return( 0 );
   1992 }
   1993 
   1994 /*
   1995  * convert a byte in a hexadecimal pair
   1996  */
   1997 static int
   1998 byte2hexpair( const char *val, char *pair )
   1999 {
   2000 	static const char	hexdig[] = "0123456789ABCDEF";
   2001 
   2002 	assert( val != NULL );
   2003 	assert( pair != NULL );
   2004 
   2005 	/*
   2006 	 * we assume the string has enough room for the hex encoding
   2007 	 * of the value
   2008 	 */
   2009 
   2010 	pair[ 0 ] = hexdig[ 0x0f & ( val[ 0 ] >> 4 ) ];
   2011 	pair[ 1 ] = hexdig[ 0x0f & val[ 0 ] ];
   2012 
   2013 	return( 0 );
   2014 }
   2015 
   2016 /*
   2017  * convert a binary value in hexadecimal pairs
   2018  */
   2019 static int
   2020 binval2hexstr( struct berval *val, char *str )
   2021 {
   2022 	ber_len_t	s, d;
   2023 
   2024 	assert( val != NULL );
   2025 	assert( str != NULL );
   2026 
   2027 	if ( val->bv_len == 0 ) {
   2028 		return( 0 );
   2029 	}
   2030 
   2031 	/*
   2032 	 * we assume the string has enough room for the hex encoding
   2033 	 * of the value
   2034 	 */
   2035 
   2036 	for ( s = 0, d = 0; s < val->bv_len; s++, d += 2 ) {
   2037 		byte2hexpair( &val->bv_val[ s ], &str[ d ] );
   2038 	}
   2039 
   2040 	return( 0 );
   2041 }
   2042 
   2043 /*
   2044  * Length of the string representation, accounting for escaped hex
   2045  * of UTF-8 chars
   2046  */
   2047 static int
   2048 strval2strlen( struct berval *val, unsigned flags, ber_len_t *len )
   2049 {
   2050 	ber_len_t	l, cl = 1;
   2051 	char		*p, *end;
   2052 	int		escaped_byte_len = LDAP_DN_IS_PRETTY( flags ) ? 1 : 3;
   2053 #ifdef PRETTY_ESCAPE
   2054 	int		escaped_ascii_len = LDAP_DN_IS_PRETTY( flags ) ? 2 : 3;
   2055 #endif /* PRETTY_ESCAPE */
   2056 
   2057 	assert( val != NULL );
   2058 	assert( len != NULL );
   2059 
   2060 	*len = 0;
   2061 	if ( val->bv_len == 0 ) {
   2062 		return( 0 );
   2063 	}
   2064 
   2065 	end = val->bv_val + val->bv_len - 1;
   2066 	for ( l = 0, p = val->bv_val; p <= end; p += cl ) {
   2067 
   2068 		/*
   2069 		 * escape '%x00'
   2070 		 */
   2071 		if ( p[ 0 ] == '\0' ) {
   2072 			cl = 1;
   2073 			l += 3;
   2074 			continue;
   2075 		}
   2076 
   2077 		cl = LDAP_UTF8_CHARLEN2( p, cl );
   2078 		if ( cl == 0 ) {
   2079 			/* illegal utf-8 char! */
   2080 			return( -1 );
   2081 
   2082 		} else if ( cl > 1 ) {
   2083 			ber_len_t cnt;
   2084 
   2085 			for ( cnt = 1; cnt < cl; cnt++ ) {
   2086 				if ( ( p[ cnt ] & 0xc0 ) != 0x80 ) {
   2087 					return( -1 );
   2088 				}
   2089 			}
   2090 			l += escaped_byte_len * cl;
   2091 
   2092 		} else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
   2093 				|| LDAP_DN_SHOULDESCAPE( p[ 0 ] )
   2094 				|| ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
   2095 				|| ( p == end && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
   2096 #ifdef PRETTY_ESCAPE
   2097 #if 0
   2098 			if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) {
   2099 #else
   2100 			if ( LDAP_DN_WILLESCAPE_CHAR( p[ 0 ] ) ) {
   2101 #endif
   2102 
   2103 				/*
   2104 				 * there might be some chars we want
   2105 				 * to escape in form of a couple
   2106 				 * of hexdigits for optimization purposes
   2107 				 */
   2108 				l += 3;
   2109 
   2110 			} else {
   2111 				l += escaped_ascii_len;
   2112 			}
   2113 #else /* ! PRETTY_ESCAPE */
   2114 			l += 3;
   2115 #endif /* ! PRETTY_ESCAPE */
   2116 
   2117 		} else {
   2118 			l++;
   2119 		}
   2120 	}
   2121 
   2122 	*len = l;
   2123 
   2124 	return( 0 );
   2125 }
   2126 
   2127 /*
   2128  * convert to string representation, escaping with hex the UTF-8 stuff;
   2129  * assume the destination has enough room for escaping
   2130  */
   2131 static int
   2132 strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
   2133 {
   2134 	ber_len_t	s, d, end;
   2135 
   2136 	assert( val != NULL );
   2137 	assert( str != NULL );
   2138 	assert( len != NULL );
   2139 
   2140 	if ( val->bv_len == 0 ) {
   2141 		*len = 0;
   2142 		return( 0 );
   2143 	}
   2144 
   2145 	/*
   2146 	 * we assume the string has enough room for the hex encoding
   2147 	 * of the value
   2148 	 */
   2149 	for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
   2150 		ber_len_t	cl;
   2151 
   2152 		/*
   2153 		 * escape '%x00'
   2154 		 */
   2155 		if ( val->bv_val[ s ] == '\0' ) {
   2156 			cl = 1;
   2157 			str[ d++ ] = '\\';
   2158 			str[ d++ ] = '0';
   2159 			str[ d++ ] = '0';
   2160 			s++;
   2161 			continue;
   2162 		}
   2163 
   2164 		/*
   2165 		 * The length was checked in strval2strlen();
   2166 		 */
   2167 		cl = LDAP_UTF8_CHARLEN( &val->bv_val[ s ] );
   2168 
   2169 		/*
   2170 		 * there might be some chars we want to escape in form
   2171 		 * of a couple of hexdigits for optimization purposes
   2172 		 */
   2173 		if ( ( cl > 1 && !LDAP_DN_IS_PRETTY( flags ) )
   2174 #ifdef PRETTY_ESCAPE
   2175 #if 0
   2176 				|| LDAP_DN_WILLESCAPE_HEX( flags, val->bv_val[ s ] )
   2177 #else
   2178 				|| LDAP_DN_WILLESCAPE_CHAR( val->bv_val[ s ] )
   2179 #endif
   2180 #else /* ! PRETTY_ESCAPE */
   2181 				|| LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
   2182 				|| LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
   2183 				|| ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
   2184 				|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
   2185 
   2186 #endif /* ! PRETTY_ESCAPE */
   2187 				) {
   2188 			for ( ; cl--; ) {
   2189 				str[ d++ ] = '\\';
   2190 				byte2hexpair( &val->bv_val[ s ], &str[ d ] );
   2191 				s++;
   2192 				d += 2;
   2193 			}
   2194 
   2195 		} else if ( cl > 1 ) {
   2196 			for ( ; cl--; ) {
   2197 				str[ d++ ] = val->bv_val[ s++ ];
   2198 			}
   2199 
   2200 		} else {
   2201 #ifdef PRETTY_ESCAPE
   2202 			if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
   2203 					|| LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
   2204 					|| ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
   2205 					|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
   2206 				str[ d++ ] = '\\';
   2207 				if ( !LDAP_DN_IS_PRETTY( flags ) ) {
   2208 					byte2hexpair( &val->bv_val[ s ], &str[ d ] );
   2209 					s++;
   2210 					d += 2;
   2211 					continue;
   2212 				}
   2213 			}
   2214 #endif /* PRETTY_ESCAPE */
   2215 			str[ d++ ] = val->bv_val[ s++ ];
   2216 		}
   2217 	}
   2218 
   2219 	*len = d;
   2220 
   2221 	return( 0 );
   2222 }
   2223 
   2224 /*
   2225  * Length of the IA5 string representation (no UTF-8 allowed)
   2226  */
   2227 static int
   2228 strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len )
   2229 {
   2230 	ber_len_t	l;
   2231 	char		*p;
   2232 
   2233 	assert( val != NULL );
   2234 	assert( len != NULL );
   2235 
   2236 	*len = 0;
   2237 	if ( val->bv_len == 0 ) {
   2238 		return( 0 );
   2239 	}
   2240 
   2241 	if ( flags & LDAP_AVA_NONPRINTABLE ) {
   2242 		/*
   2243 		 * Turn value into a binary encoded BER
   2244 		 */
   2245 		return( -1 );
   2246 
   2247 	} else {
   2248 		for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
   2249 			if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
   2250 					|| LDAP_DN_SHOULDESCAPE( p[ 0 ] )
   2251 					|| ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
   2252 					|| ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
   2253 				l += 2;
   2254 
   2255 			} else {
   2256 				l++;
   2257 			}
   2258 		}
   2259 	}
   2260 
   2261 	*len = l;
   2262 
   2263 	return( 0 );
   2264 }
   2265 
   2266 /*
   2267  * convert to string representation (np UTF-8)
   2268  * assume the destination has enough room for escaping
   2269  */
   2270 static int
   2271 strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
   2272 {
   2273 	ber_len_t	s, d, end;
   2274 
   2275 	assert( val != NULL );
   2276 	assert( str != NULL );
   2277 	assert( len != NULL );
   2278 
   2279 	if ( val->bv_len == 0 ) {
   2280 		*len = 0;
   2281 		return( 0 );
   2282 	}
   2283 
   2284 	if ( flags & LDAP_AVA_NONPRINTABLE ) {
   2285 		/*
   2286 		 * Turn value into a binary encoded BER
   2287 		 */
   2288 		*len = 0;
   2289 		return( -1 );
   2290 
   2291 	} else {
   2292 		/*
   2293 		 * we assume the string has enough room for the hex encoding
   2294 		 * of the value
   2295 		 */
   2296 
   2297 		for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
   2298 			if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
   2299 					|| LDAP_DN_SHOULDESCAPE( val->bv_val[ s ] )
   2300 					|| ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
   2301 					|| ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
   2302 				str[ d++ ] = '\\';
   2303 			}
   2304 			str[ d++ ] = val->bv_val[ s++ ];
   2305 		}
   2306 	}
   2307 
   2308 	*len = d;
   2309 
   2310 	return( 0 );
   2311 }
   2312 
   2313 /*
   2314  * Length of the (supposedly) DCE string representation,
   2315  * accounting for escaped hex of UTF-8 chars
   2316  */
   2317 static int
   2318 strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len )
   2319 {
   2320 	ber_len_t	l;
   2321 	char		*p;
   2322 
   2323 	assert( val != NULL );
   2324 	assert( len != NULL );
   2325 
   2326 	*len = 0;
   2327 	if ( val->bv_len == 0 ) {
   2328 		return( 0 );
   2329 	}
   2330 
   2331 	if ( flags & LDAP_AVA_NONPRINTABLE ) {
   2332 		/*
   2333 		 * FIXME: Turn the value into a binary encoded BER?
   2334 		 */
   2335 		return( -1 );
   2336 
   2337 	} else {
   2338 		for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
   2339 			if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
   2340 				l += 2;
   2341 
   2342 			} else {
   2343 				l++;
   2344 			}
   2345 		}
   2346 	}
   2347 
   2348 	*len = l;
   2349 
   2350 	return( 0 );
   2351 }
   2352 
   2353 /*
   2354  * convert to (supposedly) DCE string representation,
   2355  * escaping with hex the UTF-8 stuff;
   2356  * assume the destination has enough room for escaping
   2357  */
   2358 static int
   2359 strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
   2360 {
   2361 	ber_len_t	s, d;
   2362 
   2363 	assert( val != NULL );
   2364 	assert( str != NULL );
   2365 	assert( len != NULL );
   2366 
   2367 	if ( val->bv_len == 0 ) {
   2368 		*len = 0;
   2369 		return( 0 );
   2370 	}
   2371 
   2372 	if ( flags & LDAP_AVA_NONPRINTABLE ) {
   2373 		/*
   2374 		 * FIXME: Turn the value into a binary encoded BER?
   2375 		 */
   2376 		*len = 0;
   2377 		return( -1 );
   2378 
   2379 	} else {
   2380 
   2381 		/*
   2382 		 * we assume the string has enough room for the hex encoding
   2383 		 * of the value
   2384 		 */
   2385 
   2386 		for ( s = 0, d = 0; s < val->bv_len; ) {
   2387 			if ( LDAP_DN_NEEDESCAPE_DCE( val->bv_val[ s ] ) ) {
   2388 				str[ d++ ] = '\\';
   2389 			}
   2390 			str[ d++ ] = val->bv_val[ s++ ];
   2391 		}
   2392 	}
   2393 
   2394 	*len = d;
   2395 
   2396 	return( 0 );
   2397 }
   2398 
   2399 /*
   2400  * Length of the (supposedly) AD canonical string representation,
   2401  * accounting for chars that need to be escaped
   2402  */
   2403 static int
   2404 strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len )
   2405 {
   2406 	ber_len_t	l, cl;
   2407 	char		*p;
   2408 
   2409 	assert( val != NULL );
   2410 	assert( len != NULL );
   2411 
   2412 	*len = 0;
   2413 	if ( val->bv_len == 0 ) {
   2414 		return( 0 );
   2415 	}
   2416 
   2417 	for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) {
   2418 		cl = LDAP_UTF8_CHARLEN2( p, cl );
   2419 		if ( cl == 0 ) {
   2420 			/* illegal utf-8 char */
   2421 			return -1;
   2422 		} else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
   2423 			l += 2;
   2424 		} else {
   2425 			l += cl;
   2426 		}
   2427 	}
   2428 
   2429 	*len = l;
   2430 
   2431 	return( 0 );
   2432 }
   2433 
   2434 /*
   2435  * convert to (supposedly) AD string representation,
   2436  * assume the destination has enough room for escaping
   2437  */
   2438 static int
   2439 strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
   2440 {
   2441 	ber_len_t	s, d, cl;
   2442 
   2443 	assert( val != NULL );
   2444 	assert( str != NULL );
   2445 	assert( len != NULL );
   2446 
   2447 	if ( val->bv_len == 0 ) {
   2448 		*len = 0;
   2449 		return( 0 );
   2450 	}
   2451 
   2452 	/*
   2453 	 * we assume the string has enough room for the escaping
   2454 	 * of the value
   2455 	 */
   2456 
   2457 	for ( s = 0, d = 0; s < val->bv_len; ) {
   2458 		cl = LDAP_UTF8_CHARLEN2( val->bv_val+s, cl );
   2459 		if ( cl == 0 ) {
   2460 			/* illegal utf-8 char */
   2461 			return -1;
   2462 		} else if ( (cl == 1) && LDAP_DN_NEEDESCAPE_AD(val->bv_val[ s ]) ) {
   2463 			str[ d++ ] = '\\';
   2464 		}
   2465 		for (; cl--;) {
   2466 			str[ d++ ] = val->bv_val[ s++ ];
   2467 		}
   2468 	}
   2469 
   2470 	*len = d;
   2471 
   2472 	return( 0 );
   2473 }
   2474 
   2475 /*
   2476  * If the DN is terminated by single-AVA RDNs with attribute type of "dc",
   2477  * the first part of the AD representation of the DN is written in DNS
   2478  * form, i.e. dot separated domain name components (as suggested
   2479  * by Luke Howard, http://www.padl.com/~lukeh)
   2480  */
   2481 static int
   2482 dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN )
   2483 {
   2484 	int 		i;
   2485 	int		domain = 0, first = 1;
   2486 	ber_len_t	l = 1; /* we move the null also */
   2487 	char		*str;
   2488 
   2489 	/* we are guaranteed there's enough memory in str */
   2490 
   2491 	/* sanity */
   2492 	assert( dn != NULL );
   2493 	assert( bv != NULL );
   2494 	assert( iRDN != NULL );
   2495 	assert( *iRDN >= 0 );
   2496 
   2497 	str = bv->bv_val + pos;
   2498 
   2499 	for ( i = *iRDN; i >= 0; i-- ) {
   2500 		LDAPRDN		rdn;
   2501 		LDAPAVA		*ava;
   2502 
   2503 		assert( dn[ i ] != NULL );
   2504 		rdn = dn[ i ];
   2505 
   2506 		assert( rdn[ 0 ] != NULL );
   2507 		ava = rdn[ 0 ];
   2508 
   2509 		if ( !LDAP_DN_IS_RDN_DC( rdn ) ) {
   2510 			break;
   2511 		}
   2512 
   2513 		if ( ldif_is_not_printable( ava->la_value.bv_val, ava->la_value.bv_len ) ) {
   2514 			domain = 0;
   2515 			break;
   2516 		}
   2517 
   2518 		domain = 1;
   2519 
   2520 		if ( first ) {
   2521 			first = 0;
   2522 			AC_MEMCPY( str, ava->la_value.bv_val,
   2523 					ava->la_value.bv_len + 1);
   2524 			l += ava->la_value.bv_len;
   2525 
   2526 		} else {
   2527 			AC_MEMCPY( str + ava->la_value.bv_len + 1, bv->bv_val + pos, l);
   2528 			AC_MEMCPY( str, ava->la_value.bv_val,
   2529 					ava->la_value.bv_len );
   2530 			str[ ava->la_value.bv_len ] = '.';
   2531 			l += ava->la_value.bv_len + 1;
   2532 		}
   2533 	}
   2534 
   2535 	*iRDN = i;
   2536 	bv->bv_len = pos + l - 1;
   2537 
   2538 	return( domain );
   2539 }
   2540 
   2541 static int
   2542 rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len,
   2543 	 int ( *s2l )( struct berval *v, unsigned f, ber_len_t *l ) )
   2544 {
   2545 	int		iAVA;
   2546 	ber_len_t	l = 0;
   2547 
   2548 	*len = 0;
   2549 
   2550 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2551 		LDAPAVA		*ava = rdn[ iAVA ];
   2552 
   2553 		/* len(type) + '=' + '+' | ',' */
   2554 		l += ava->la_attr.bv_len + 2;
   2555 
   2556 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2557 			/* octothorpe + twice the length */
   2558 			l += 1 + 2 * ava->la_value.bv_len;
   2559 
   2560 		} else {
   2561 			ber_len_t	vl;
   2562 			unsigned	f = flags | ava->la_flags;
   2563 
   2564 			if ( ( *s2l )( &ava->la_value, f, &vl ) ) {
   2565 				return( -1 );
   2566 			}
   2567 			l += vl;
   2568 		}
   2569 	}
   2570 	if ( !iAVA )
   2571 		return( -1 );	/* RDN ::= SET SIZE (1..MAX) OF AVA */
   2572 
   2573 	*len = l;
   2574 
   2575 	return( 0 );
   2576 }
   2577 
   2578 static int
   2579 rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len,
   2580 	int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) )
   2581 {
   2582 	int		iAVA;
   2583 	ber_len_t	l = 0;
   2584 
   2585 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2586 		LDAPAVA		*ava = rdn[ iAVA ];
   2587 
   2588 		AC_MEMCPY( &str[ l ], ava->la_attr.bv_val,
   2589 				ava->la_attr.bv_len );
   2590 		l += ava->la_attr.bv_len;
   2591 
   2592 		str[ l++ ] = '=';
   2593 
   2594 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2595 			str[ l++ ] = '#';
   2596 			if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
   2597 				return( -1 );
   2598 			}
   2599 			l += 2 * ava->la_value.bv_len;
   2600 
   2601 		} else {
   2602 			ber_len_t	vl;
   2603 			unsigned	f = flags | ava->la_flags;
   2604 
   2605 			if ( ( *s2s )( &ava->la_value, &str[ l ], f, &vl ) ) {
   2606 				return( -1 );
   2607 			}
   2608 			l += vl;
   2609 		}
   2610 		str[ l++ ] = ( rdn[ iAVA + 1] ? '+' : ',' );
   2611 	}
   2612 
   2613 	*len = l;
   2614 
   2615 	return( 0 );
   2616 }
   2617 
   2618 static int
   2619 rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
   2620 {
   2621 	int		iAVA;
   2622 	ber_len_t	l = 0;
   2623 
   2624 	*len = 0;
   2625 
   2626 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2627 		LDAPAVA		*ava = rdn[ iAVA ];
   2628 
   2629 		/* len(type) + '=' + ',' | '/' */
   2630 		l += ava->la_attr.bv_len + 2;
   2631 
   2632 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2633 			/* octothorpe + twice the length */
   2634 			l += 1 + 2 * ava->la_value.bv_len;
   2635 		} else {
   2636 			ber_len_t	vl;
   2637 			unsigned	f = flags | ava->la_flags;
   2638 
   2639 			if ( strval2DCEstrlen( &ava->la_value, f, &vl ) ) {
   2640 				return( -1 );
   2641 			}
   2642 			l += vl;
   2643 		}
   2644 	}
   2645 	if ( !iAVA )
   2646 		return( -1 );	/* RDN ::= SET SIZE (1..MAX) OF AVA */
   2647 
   2648 	*len = l;
   2649 
   2650 	return( 0 );
   2651 }
   2652 
   2653 static int
   2654 rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first )
   2655 {
   2656 	int		iAVA;
   2657 	ber_len_t	l = 0;
   2658 
   2659 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2660 		LDAPAVA		*ava = rdn[ iAVA ];
   2661 
   2662 		if ( first ) {
   2663 			first = 0;
   2664 		} else {
   2665 			str[ l++ ] = ( iAVA ? ',' : '/' );
   2666 		}
   2667 
   2668 		AC_MEMCPY( &str[ l ], ava->la_attr.bv_val,
   2669 				ava->la_attr.bv_len );
   2670 		l += ava->la_attr.bv_len;
   2671 
   2672 		str[ l++ ] = '=';
   2673 
   2674 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2675 			str[ l++ ] = '#';
   2676 			if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
   2677 				return( -1 );
   2678 			}
   2679 			l += 2 * ava->la_value.bv_len;
   2680 		} else {
   2681 			ber_len_t	vl;
   2682 			unsigned	f = flags | ava->la_flags;
   2683 
   2684 			if ( strval2DCEstr( &ava->la_value, &str[ l ], f, &vl ) ) {
   2685 				return( -1 );
   2686 			}
   2687 			l += vl;
   2688 		}
   2689 	}
   2690 
   2691 	*len = l;
   2692 
   2693 	return( 0 );
   2694 }
   2695 
   2696 static int
   2697 rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
   2698 {
   2699 	int		iAVA;
   2700 	ber_len_t	l = 0;
   2701 
   2702 	assert( rdn != NULL );
   2703 	assert( len != NULL );
   2704 
   2705 	*len = 0;
   2706 
   2707 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2708 		LDAPAVA		*ava = rdn[ iAVA ];
   2709 
   2710 		/* ' + ' | ', ' */
   2711 		l += ( rdn[ iAVA + 1 ] ? 3 : 2 );
   2712 
   2713 		/* FIXME: are binary values allowed in UFN? */
   2714 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2715 			/* octothorpe + twice the value */
   2716 			l += 1 + 2 * ava->la_value.bv_len;
   2717 
   2718 		} else {
   2719 			ber_len_t	vl;
   2720 			unsigned	f = flags | ava->la_flags;
   2721 
   2722 			if ( strval2strlen( &ava->la_value, f, &vl ) ) {
   2723 				return( -1 );
   2724 			}
   2725 			l += vl;
   2726 		}
   2727 	}
   2728 	if ( !iAVA )
   2729 		return( -1 );	/* RDN ::= SET SIZE (1..MAX) OF AVA */
   2730 
   2731 	*len = l;
   2732 
   2733 	return( 0 );
   2734 }
   2735 
   2736 static int
   2737 rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len )
   2738 {
   2739 	int		iAVA;
   2740 	ber_len_t	l = 0;
   2741 
   2742 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2743 		LDAPAVA		*ava = rdn[ iAVA ];
   2744 
   2745 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2746 			str[ l++ ] = '#';
   2747 			if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
   2748 				return( -1 );
   2749 			}
   2750 			l += 2 * ava->la_value.bv_len;
   2751 
   2752 		} else {
   2753 			ber_len_t	vl;
   2754 			unsigned	f = flags | ava->la_flags;
   2755 
   2756 			if ( strval2str( &ava->la_value, &str[ l ], f, &vl ) ) {
   2757 				return( -1 );
   2758 			}
   2759 			l += vl;
   2760 		}
   2761 
   2762 		if ( rdn[ iAVA + 1 ] ) {
   2763 			AC_MEMCPY( &str[ l ], " + ", 3 );
   2764 			l += 3;
   2765 
   2766 		} else {
   2767 			AC_MEMCPY( &str[ l ], ", ", 2 );
   2768 			l += 2;
   2769 		}
   2770 	}
   2771 
   2772 	*len = l;
   2773 
   2774 	return( 0 );
   2775 }
   2776 
   2777 static int
   2778 rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
   2779 {
   2780 	int		iAVA;
   2781 	ber_len_t	l = 0;
   2782 
   2783 	assert( rdn != NULL );
   2784 	assert( len != NULL );
   2785 
   2786 	*len = 0;
   2787 
   2788 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2789 		LDAPAVA		*ava = rdn[ iAVA ];
   2790 
   2791 		/* ',' | '/' */
   2792 		l++;
   2793 
   2794 		/* FIXME: are binary values allowed in UFN? */
   2795 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2796 			/* octothorpe + twice the value */
   2797 			l += 1 + 2 * ava->la_value.bv_len;
   2798 		} else {
   2799 			ber_len_t	vl;
   2800 			unsigned	f = flags | ava->la_flags;
   2801 
   2802 			if ( strval2ADstrlen( &ava->la_value, f, &vl ) ) {
   2803 				return( -1 );
   2804 			}
   2805 			l += vl;
   2806 		}
   2807 	}
   2808 	if ( !iAVA )
   2809 		return( -1 );	/* RDN ::= SET SIZE (1..MAX) OF AVA */
   2810 
   2811 	*len = l;
   2812 
   2813 	return( 0 );
   2814 }
   2815 
   2816 static int
   2817 rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first )
   2818 {
   2819 	int		iAVA;
   2820 	ber_len_t	l = 0;
   2821 
   2822 	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
   2823 		LDAPAVA		*ava = rdn[ iAVA ];
   2824 
   2825 		if ( first ) {
   2826 			first = 0;
   2827 		} else {
   2828 			str[ l++ ] = ( iAVA ? ',' : '/' );
   2829 		}
   2830 
   2831 		if ( ava->la_flags & LDAP_AVA_BINARY ) {
   2832 			str[ l++ ] = '#';
   2833 			if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
   2834 				return( -1 );
   2835 			}
   2836 			l += 2 * ava->la_value.bv_len;
   2837 		} else {
   2838 			ber_len_t	vl;
   2839 			unsigned	f = flags | ava->la_flags;
   2840 
   2841 			if ( strval2ADstr( &ava->la_value, &str[ l ], f, &vl ) ) {
   2842 				return( -1 );
   2843 			}
   2844 			l += vl;
   2845 		}
   2846 	}
   2847 
   2848 	*len = l;
   2849 
   2850 	return( 0 );
   2851 }
   2852 
   2853 /*
   2854  * ldap_rdn2str
   2855  *
   2856  * Returns in str a string representation of rdn based on flags.
   2857  * There is some duplication of code between this and ldap_dn2str;
   2858  * this is wanted to reduce the allocation of temporary buffers.
   2859  */
   2860 int
   2861 ldap_rdn2str( LDAPRDN rdn, char **str, unsigned flags )
   2862 {
   2863 	struct berval bv;
   2864 	int rc;
   2865 
   2866 	assert( str != NULL );
   2867 
   2868 	if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
   2869 		return LDAP_PARAM_ERROR;
   2870 	}
   2871 
   2872 	rc = ldap_rdn2bv_x( rdn, &bv, flags, NULL );
   2873 	*str = bv.bv_val;
   2874 	return rc;
   2875 }
   2876 
   2877 int
   2878 ldap_rdn2bv( LDAPRDN rdn, struct berval *bv, unsigned flags )
   2879 {
   2880 	return ldap_rdn2bv_x( rdn, bv, flags, NULL );
   2881 }
   2882 
   2883 int
   2884 ldap_rdn2bv_x( LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx )
   2885 {
   2886 	int		rc, back;
   2887 	ber_len_t	l;
   2888 
   2889 	assert( bv != NULL );
   2890 
   2891 	bv->bv_len = 0;
   2892 	bv->bv_val = NULL;
   2893 
   2894 	if ( rdn == NULL ) {
   2895 		bv->bv_val = LDAP_STRDUPX( "", ctx );
   2896 		return( LDAP_SUCCESS );
   2897 	}
   2898 
   2899 	/*
   2900 	 * This routine wastes "back" bytes at the end of the string
   2901 	 */
   2902 
   2903 	switch ( LDAP_DN_FORMAT( flags ) ) {
   2904 	case LDAP_DN_FORMAT_LDAPV3:
   2905 		if ( rdn2strlen( rdn, flags, &l, strval2strlen ) ) {
   2906 			return LDAP_DECODING_ERROR;
   2907 		}
   2908 		break;
   2909 
   2910 	case LDAP_DN_FORMAT_LDAPV2:
   2911 		if ( rdn2strlen( rdn, flags, &l, strval2IA5strlen ) ) {
   2912 			return LDAP_DECODING_ERROR;
   2913 		}
   2914 		break;
   2915 
   2916 	case LDAP_DN_FORMAT_UFN:
   2917 		if ( rdn2UFNstrlen( rdn, flags, &l ) ) {
   2918 			return LDAP_DECODING_ERROR;
   2919 		}
   2920 		break;
   2921 
   2922 	case LDAP_DN_FORMAT_DCE:
   2923 		if ( rdn2DCEstrlen( rdn, flags, &l ) ) {
   2924 			return LDAP_DECODING_ERROR;
   2925 		}
   2926 		break;
   2927 
   2928 	case LDAP_DN_FORMAT_AD_CANONICAL:
   2929 		if ( rdn2ADstrlen( rdn, flags, &l ) ) {
   2930 			return LDAP_DECODING_ERROR;
   2931 		}
   2932 		break;
   2933 
   2934 	default:
   2935 		return LDAP_PARAM_ERROR;
   2936 	}
   2937 
   2938 	bv->bv_val = LDAP_MALLOCX( l + 1, ctx );
   2939 	if ( bv->bv_val == NULL ) {
   2940 		return LDAP_NO_MEMORY;
   2941 	}
   2942 
   2943 	switch ( LDAP_DN_FORMAT( flags ) ) {
   2944 	case LDAP_DN_FORMAT_LDAPV3:
   2945 		rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2str );
   2946 		back = 1;
   2947 		break;
   2948 
   2949 	case LDAP_DN_FORMAT_LDAPV2:
   2950 		rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2IA5str );
   2951 		back = 1;
   2952 		break;
   2953 
   2954 	case LDAP_DN_FORMAT_UFN:
   2955 		rc = rdn2UFNstr( rdn, bv->bv_val, flags, &l );
   2956 		back = 2;
   2957 		break;
   2958 
   2959 	case LDAP_DN_FORMAT_DCE:
   2960 		rc = rdn2DCEstr( rdn, bv->bv_val, flags, &l, 1 );
   2961 		back = 0;
   2962 		break;
   2963 
   2964 	case LDAP_DN_FORMAT_AD_CANONICAL:
   2965 		rc = rdn2ADstr( rdn, bv->bv_val, flags, &l, 1 );
   2966 		back = 0;
   2967 		break;
   2968 
   2969 	default:
   2970 		/* need at least one of the previous */
   2971 		return LDAP_PARAM_ERROR;
   2972 	}
   2973 
   2974 	if ( rc ) {
   2975 		LDAP_FREEX( bv->bv_val, ctx );
   2976 		return rc;
   2977 	}
   2978 
   2979 	bv->bv_len = l - back;
   2980 	bv->bv_val[ bv->bv_len ] = '\0';
   2981 
   2982 	return LDAP_SUCCESS;
   2983 }
   2984 
   2985 /*
   2986  * Very bulk implementation; many optimizations can be performed
   2987  *   - a NULL dn results in an empty string ""
   2988  *
   2989  * FIXME: doubts
   2990  *   a) what do we do if a UTF-8 string must be converted in LDAPv2?
   2991  *      we must encode it in binary form ('#' + HEXPAIRs)
   2992  *   b) does DCE/AD support UTF-8?
   2993  *      no clue; don't think so.
   2994  *   c) what do we do when binary values must be converted in UTF/DCE/AD?
   2995  *      use binary encoded BER
   2996  */
   2997 int ldap_dn2str( LDAPDN dn, char **str, unsigned flags )
   2998 {
   2999 	struct berval bv;
   3000 	int rc;
   3001 
   3002 	assert( str != NULL );
   3003 
   3004 	if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
   3005 		return LDAP_PARAM_ERROR;
   3006 	}
   3007 
   3008 	rc = ldap_dn2bv_x( dn, &bv, flags, NULL );
   3009 	*str = bv.bv_val;
   3010 	return rc;
   3011 }
   3012 
   3013 int ldap_dn2bv( LDAPDN dn, struct berval *bv, unsigned flags )
   3014 {
   3015 	return ldap_dn2bv_x( dn, bv, flags, NULL );
   3016 }
   3017 
   3018 int ldap_dn2bv_x( LDAPDN dn, struct berval *bv, unsigned flags, void *ctx )
   3019 {
   3020 	int		iRDN;
   3021 	int		rc = LDAP_ENCODING_ERROR;
   3022 	ber_len_t	len, l;
   3023 
   3024 	/* stringifying helpers for LDAPv3/LDAPv2 */
   3025 	int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l );
   3026 	int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l );
   3027 
   3028 	assert( bv != NULL );
   3029 	bv->bv_len = 0;
   3030 	bv->bv_val = NULL;
   3031 
   3032 	Debug1( LDAP_DEBUG_ARGS, "=> ldap_dn2bv(%u)\n", flags );
   3033 
   3034 	/*
   3035 	 * a null dn means an empty dn string
   3036 	 * FIXME: better raise an error?
   3037 	 */
   3038 	if ( dn == NULL || dn[0] == NULL ) {
   3039 		bv->bv_val = LDAP_STRDUPX( "", ctx );
   3040 		return( LDAP_SUCCESS );
   3041 	}
   3042 
   3043 	switch ( LDAP_DN_FORMAT( flags ) ) {
   3044 	case LDAP_DN_FORMAT_LDAPV3:
   3045 		sv2l = strval2strlen;
   3046 		sv2s = strval2str;
   3047 
   3048 		if( 0 ) {
   3049 	case LDAP_DN_FORMAT_LDAPV2:
   3050 			sv2l = strval2IA5strlen;
   3051 			sv2s = strval2IA5str;
   3052 		}
   3053 
   3054 		for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
   3055 			ber_len_t	rdnl;
   3056 			if ( rdn2strlen( dn[ iRDN ], flags, &rdnl, sv2l ) ) {
   3057 				goto return_results;
   3058 			}
   3059 
   3060 			len += rdnl;
   3061 		}
   3062 
   3063 		if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) {
   3064 			rc = LDAP_NO_MEMORY;
   3065 			break;
   3066 		}
   3067 
   3068 		for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
   3069 			ber_len_t	rdnl;
   3070 
   3071 			if ( rdn2str( dn[ iRDN ], &bv->bv_val[ l ], flags,
   3072 					&rdnl, sv2s ) ) {
   3073 				LDAP_FREEX( bv->bv_val, ctx );
   3074 				bv->bv_val = NULL;
   3075 				goto return_results;
   3076 			}
   3077 			l += rdnl;
   3078 		}
   3079 
   3080 		assert( l == len );
   3081 
   3082 		/*
   3083 		 * trim the last ',' (the allocated memory
   3084 		 * is one byte longer than required)
   3085 		 */
   3086 		bv->bv_len = len - 1;
   3087 		bv->bv_val[ bv->bv_len ] = '\0';
   3088 
   3089 		rc = LDAP_SUCCESS;
   3090 		break;
   3091 
   3092 	case LDAP_DN_FORMAT_UFN: {
   3093 		/*
   3094 		 * FIXME: quoting from RFC 1781:
   3095 		 *
   3096    To take a distinguished name, and generate a name of this format with
   3097    attribute types omitted, the following steps are followed.
   3098 
   3099     1.  If the first attribute is of type CommonName, the type may be
   3100 	omitted.
   3101 
   3102     2.  If the last attribute is of type Country, the type may be
   3103         omitted.
   3104 
   3105     3.  If the last attribute is of type Country, the last
   3106         Organisation attribute may have the type omitted.
   3107 
   3108     4.  All attributes of type OrganisationalUnit may have the type
   3109         omitted, unless they are after an Organisation attribute or
   3110         the first attribute is of type OrganisationalUnit.
   3111 
   3112          * this should be the pedantic implementation.
   3113 		 *
   3114 		 * Here the standard implementation reflects
   3115 		 * the one historically provided by OpenLDAP
   3116 		 * (and UMIch, I presume), with the variant
   3117 		 * of spaces and plusses (' + ') separating
   3118 		 * rdn components.
   3119 		 *
   3120 		 * A non-standard but nice implementation could
   3121 		 * be to turn the  final "dc" attributes into a
   3122 		 * dot-separated domain.
   3123 		 *
   3124 		 * Other improvements could involve the use of
   3125 		 * friendly country names and so.
   3126 		 */
   3127 #ifdef DC_IN_UFN
   3128 		int	leftmost_dc = -1;
   3129 		int	last_iRDN = -1;
   3130 #endif /* DC_IN_UFN */
   3131 
   3132 		for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
   3133 			ber_len_t	rdnl;
   3134 
   3135 			if ( rdn2UFNstrlen( dn[ iRDN ], flags, &rdnl ) ) {
   3136 				goto return_results;
   3137 			}
   3138 			len += rdnl;
   3139 
   3140 #ifdef DC_IN_UFN
   3141 			if ( LDAP_DN_IS_RDN_DC( dn[ iRDN ] ) ) {
   3142 				if ( leftmost_dc == -1 ) {
   3143 					leftmost_dc = iRDN;
   3144 				}
   3145 			} else {
   3146 				leftmost_dc = -1;
   3147 			}
   3148 #endif /* DC_IN_UFN */
   3149 		}
   3150 
   3151 		if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) {
   3152 			rc = LDAP_NO_MEMORY;
   3153 			break;
   3154 		}
   3155 
   3156 #ifdef DC_IN_UFN
   3157 		if ( leftmost_dc == -1 ) {
   3158 #endif /* DC_IN_UFN */
   3159 			for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
   3160 				ber_len_t	vl;
   3161 
   3162 				if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ],
   3163 						flags, &vl ) ) {
   3164 					LDAP_FREEX( bv->bv_val, ctx );
   3165 					bv->bv_val = NULL;
   3166 					goto return_results;
   3167 				}
   3168 				l += vl;
   3169 			}
   3170 
   3171 			/*
   3172 			 * trim the last ', ' (the allocated memory
   3173 			 * is two bytes longer than required)
   3174 			 */
   3175 			bv->bv_len = len - 2;
   3176 			bv->bv_val[ bv->bv_len ] = '\0';
   3177 #ifdef DC_IN_UFN
   3178 		} else {
   3179 			last_iRDN = iRDN - 1;
   3180 
   3181 			for ( l = 0, iRDN = 0; iRDN < leftmost_dc; iRDN++ ) {
   3182 				ber_len_t	vl;
   3183 
   3184 				if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ],
   3185 						flags, &vl ) ) {
   3186 					LDAP_FREEX( bv->bv_val, ctx );
   3187 					bv->bv_val = NULL;
   3188 					goto return_results;
   3189 				}
   3190 				l += vl;
   3191 			}
   3192 
   3193 			if ( !dn2domain( dn, bv, l, &last_iRDN ) ) {
   3194 				LDAP_FREEX( bv->bv_val, ctx );
   3195 				bv->bv_val = NULL;
   3196 				goto return_results;
   3197 			}
   3198 
   3199 			/* the string is correctly terminated by dn2domain */
   3200 		}
   3201 #endif /* DC_IN_UFN */
   3202 
   3203 		rc = LDAP_SUCCESS;
   3204 
   3205 	} break;
   3206 
   3207 	case LDAP_DN_FORMAT_DCE:
   3208 		for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
   3209 			ber_len_t	rdnl;
   3210 			if ( rdn2DCEstrlen( dn[ iRDN ], flags, &rdnl ) ) {
   3211 				goto return_results;
   3212 			}
   3213 
   3214 			len += rdnl;
   3215 		}
   3216 
   3217 		if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) {
   3218 			rc = LDAP_NO_MEMORY;
   3219 			break;
   3220 		}
   3221 
   3222 		for ( l = 0; iRDN--; ) {
   3223 			ber_len_t	rdnl;
   3224 
   3225 			if ( rdn2DCEstr( dn[ iRDN ], &bv->bv_val[ l ], flags,
   3226 					&rdnl, 0 ) ) {
   3227 				LDAP_FREEX( bv->bv_val, ctx );
   3228 				bv->bv_val = NULL;
   3229 				goto return_results;
   3230 			}
   3231 			l += rdnl;
   3232 		}
   3233 
   3234 		assert( l == len );
   3235 
   3236 		bv->bv_len = len;
   3237 		bv->bv_val[ bv->bv_len ] = '\0';
   3238 
   3239 		rc = LDAP_SUCCESS;
   3240 		break;
   3241 
   3242 	case LDAP_DN_FORMAT_AD_CANONICAL: {
   3243 		int	trailing_slash = 1;
   3244 
   3245 		/*
   3246 		 * Sort of UFN for DCE DNs: a slash ('/') separated
   3247 		 * global->local DN with no types; strictly speaking,
   3248 		 * the naming context should be a domain, which is
   3249 		 * written in DNS-style, e.g. dot-separated.
   3250 		 *
   3251 		 * Example:
   3252 		 *
   3253 		 * 	"givenName=Bill+sn=Gates,ou=People,dc=microsoft,dc=com"
   3254 		 *
   3255 		 * will read
   3256 		 *
   3257 		 * 	"microsoft.com/People/Bill,Gates"
   3258 		 */
   3259 		for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) {
   3260 			ber_len_t	rdnl;
   3261 
   3262 			if ( rdn2ADstrlen( dn[ iRDN ], flags, &rdnl ) ) {
   3263 				goto return_results;
   3264 			}
   3265 
   3266 			len += rdnl;
   3267 		}
   3268 
   3269 		/* reserve room for trailing '/' in case the DN
   3270 		 * is exactly a domain */
   3271 		if ( ( bv->bv_val = LDAP_MALLOCX( len + 1 + 1, ctx ) ) == NULL )
   3272 		{
   3273 			rc = LDAP_NO_MEMORY;
   3274 			break;
   3275 		}
   3276 
   3277 		iRDN--;
   3278 		if ( iRDN && dn2domain( dn, bv, 0, &iRDN ) != 0 ) {
   3279 			for ( l = bv->bv_len; iRDN >= 0 ; iRDN-- ) {
   3280 				ber_len_t	rdnl;
   3281 
   3282 				trailing_slash = 0;
   3283 
   3284 				if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ],
   3285 						flags, &rdnl, 0 ) ) {
   3286 					LDAP_FREEX( bv->bv_val, ctx );
   3287 					bv->bv_val = NULL;
   3288 					goto return_results;
   3289 				}
   3290 				l += rdnl;
   3291 			}
   3292 
   3293 		} else {
   3294 			int		first = 1;
   3295 
   3296 			/*
   3297 			 * Strictly speaking, AD canonical requires
   3298 			 * a DN to be in the form "..., dc=smtg",
   3299 			 * i.e. terminated by a domain component
   3300 			 */
   3301 			if ( flags & LDAP_DN_PEDANTIC ) {
   3302 				LDAP_FREEX( bv->bv_val, ctx );
   3303 				bv->bv_val = NULL;
   3304 				rc = LDAP_ENCODING_ERROR;
   3305 				break;
   3306 			}
   3307 
   3308 			for ( l = 0; iRDN >= 0 ; iRDN-- ) {
   3309 				ber_len_t	rdnl;
   3310 
   3311 				if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ],
   3312 						flags, &rdnl, first ) ) {
   3313 					LDAP_FREEX( bv->bv_val, ctx );
   3314 					bv->bv_val = NULL;
   3315 					goto return_results;
   3316 				}
   3317 				if ( first ) {
   3318 					first = 0;
   3319 				}
   3320 				l += rdnl;
   3321 			}
   3322 		}
   3323 
   3324 		if ( trailing_slash ) {
   3325 			/* the DN is exactly a domain -- need a trailing
   3326 			 * slash; room was reserved in advance */
   3327 			bv->bv_val[ len ] = '/';
   3328 			len++;
   3329 		}
   3330 
   3331 		bv->bv_len = len;
   3332 		bv->bv_val[ bv->bv_len ] = '\0';
   3333 
   3334 		rc = LDAP_SUCCESS;
   3335 	} break;
   3336 
   3337 	default:
   3338 		return LDAP_PARAM_ERROR;
   3339 	}
   3340 
   3341 	Debug3( LDAP_DEBUG_ARGS, "<= ldap_dn2bv(%s)=%d %s\n",
   3342 		bv->bv_val, rc, rc ? ldap_err2string( rc ) : "" );
   3343 
   3344 return_results:;
   3345 	return( rc );
   3346 }
   3347 
   3348