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