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