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