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