3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * Copyright (c) 1994 Regents of the University of Michigan.
17 #include <ac/stdlib.h>
20 #include <ac/socket.h>
21 #include <ac/string.h>
26 #define NAME_TYPE_LDAP_RDN 0
27 #define NAME_TYPE_LDAP_DN 1
28 #define NAME_TYPE_DCE_DN 2
30 static char **explode_name( const char *name, int notypes, int is_type );
31 static char *dn2dn( const char *dnin, unsigned fin, unsigned fout );
33 /* from libraries/libldap/schema.c */
34 extern char * parse_numericoid(const char **sp, int *code, const int flags);
36 /* parsing/printing routines */
37 static int str2strval( const char *str, struct berval **val,
38 const char **next, unsigned flags, unsigned *retFlags );
39 static int DCE2strval( const char *str, struct berval **val,
40 const char **next, unsigned flags );
41 static int IA52strval( const char *str, struct berval **val,
42 const char **next, unsigned flags );
43 static int quotedIA52strval( const char *str, struct berval **val,
44 const char **next, unsigned flags );
45 static int hexstr2binval( const char *str, struct berval **val,
46 const char **next, unsigned flags );
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 ber_len_t strval2strlen( struct berval *val, unsigned flags );
51 static int strval2str( struct berval *val, char *str, unsigned flags,
53 static ber_len_t strval2IA5strlen( struct berval *val, unsigned flags );
54 static int strval2IA5str( struct berval *val, char *str, unsigned flags,
56 static ber_len_t strval2DCEstrlen( struct berval *val, unsigned flags );
57 static int strval2DCEstr( struct berval *val, char *str, unsigned flags,
59 static ber_len_t strval2ADstrlen( struct berval *val, unsigned flags );
60 static int strval2ADstr( struct berval *val, char *str, unsigned flags,
62 static int dn2domain( LDAPDN *dn, char **str, int *iRDN );
65 static LDAPAVA * ldapava_new( const char *attr, const struct berval *val,
67 static void ldapava_free( LDAPAVA *ava );
68 static LDAPRDN * ldapava_append_to_rdn( LDAPRDN *rdn, LDAPAVA *ava );
69 static void ldapava_free_rdn( LDAPRDN *rdn );
70 static LDAPDN * ldapava_append_to_dn( LDAPDN *dn, LDAPRDN *rdn );
71 static LDAPDN * ldapava_insert_into_dn( LDAPDN *dn, LDAPRDN *rdn );
72 static void ldapava_free_dn( LDAPDN *dn );
74 /* Higher level helpers */
75 static ber_len_t rdn2strlen( LDAPRDN *rdn );
76 static int rdn2str( LDAPRDN *rdn, char *str, ber_len_t *len );
77 static ber_len_t rdn2UFNstrlen( LDAPRDN *rdn );
78 static int rdn2UFNstr( LDAPRDN *rdn, char *str, ber_len_t *len );
81 int ldap_rdn2str( LDAPRDN *rdn, char **str, unsigned flags );
84 * RFC 1823 ldap_get_dn
87 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
92 Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
94 if ( entry == NULL ) {
95 ld->ld_errno = LDAP_PARAM_ERROR;
99 tmp = *entry->lm_ber; /* struct copy */
100 if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) {
101 ld->ld_errno = LDAP_DECODING_ERROR;
109 * RFC 1823 ldap_dn2ufn
112 ldap_dn2ufn( LDAP_CONST char *dn )
114 #ifndef USE_LDAP_DN_PARSING
119 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
121 /* produces completely untyped UFNs */
127 vals = ldap_explode_dn( dn , 0 );
132 for ( i = 0; vals[i]; i++ ) {
135 rvals = ldap_explode_rdn( vals[i] , 1 );
136 if ( rvals == NULL ) {
141 LDAP_FREE( vals[i] );
142 vals[i] = ldap_charray2str( rvals, " + " );
146 ufn = ldap_charray2str( vals, ", " );
150 #else /* USE_LDAP_DN_PARSING */
151 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
153 return dn2dn( dn, LDAP_DN_FORMAT_LDAPV3, LDAP_DN_FORMAT_UFN );
154 #endif /* USE_LDAP_DN_PARSING */
158 ldap_explode_dn( LDAP_CONST char *dn, int notypes )
160 #ifndef USE_LDAP_DN_PARSING
161 Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
163 return explode_name( dn, notypes, NAME_TYPE_LDAP_DN );
164 #else /* USE_LDAP_DN_PARSING */
166 char **values = NULL;
168 unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3;
170 Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
172 if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAPV3 )
177 for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) {
178 char *str, **v = NULL;
180 ldap_rdn2str( tmpDN[ iRDN ][ 0 ], &str, flag );
182 v = LDAP_REALLOC( values, sizeof( char * ) * ( 2 + iRDN ) );
184 LBER_VFREE( values );
185 ldapava_free_dn( tmpDN );
189 values[ iRDN ] = str;
191 values[ iRDN ] = NULL;
194 #endif /* USE_LDAP_DN_PARSING */
198 ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
200 #ifndef USE_LDAP_DN_PARSING
201 Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
203 return explode_name( rdn, notypes, NAME_TYPE_LDAP_RDN );
204 #else /* USE_LDAP_DN_PARSING */
206 char **values = NULL;
208 unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3;
210 Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
213 * we assume this dn is made of one rdn only
215 if ( ldap_str2dn( rdn, &tmpDN, LDAP_DN_FORMAT_LDAPV3 )
220 for ( iAVA = 0; tmpDN[ 0 ][ 0 ][ iAVA ]; iAVA++ ) {
221 ber_len_t l = 0, vl, al = 0;
222 char *str, **v = NULL;
223 LDAPAVA *ava = tmpDN[ 0 ][ 0 ][ iAVA ][ 0 ];
225 v = LDAP_REALLOC( values, sizeof( char * ) * ( 2 + iAVA ) );
227 LBER_VFREE( values );
228 ldapava_free_dn( tmpDN );
233 if ( ava->la_flags == LDAP_AVA_BINARY ) {
234 vl = 1 + 2 * ava->la_value->bv_len;
236 vl = strval2strlen( ava->la_value, ava->la_flags );
240 al = strlen( ava->la_attr );
244 str = LDAP_MALLOC( l + 1 );
245 AC_MEMCPY( str, ava->la_attr, al );
249 str = LDAP_MALLOC( l + 1 );
252 if ( ava->la_flags == LDAP_AVA_BINARY ) {
254 binval2hexstr( ava->la_value, &str[ al ] );
256 strval2str( ava->la_value, &str[ al ],
257 ava->la_flags, &vl );
261 values[ iAVA ] = str;
263 values[ iAVA ] = NULL;
266 #endif /* USE_LDAP_DN_PARSING */
270 ldap_dn2ad_canonical( LDAP_CONST char *dn )
272 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n", 0, 0, 0 );
274 return dn2dn( dn, LDAP_DN_FORMAT_LDAPV3, LDAP_DN_FORMAT_AD_CANONICAL );
278 dn2dn( const char *dnin, unsigned fin, unsigned fout )
281 LDAPDN *tmpDN = NULL;
287 if ( ldap_str2dn( dnin , &tmpDN, fin ) != LDAP_SUCCESS ) {
291 /* don't care about the result ... */
292 ldap_dn2str( tmpDN, &dnout, fout );
294 ldapava_free_dn( tmpDN );
301 ldap_dn2dcedn( LDAP_CONST char *dn )
303 #ifndef USE_LDAP_DN_PARSING
304 char *dce, *q, **rdns, **p;
307 Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
309 rdns = explode_name( dn, 0, NAME_TYPE_LDAP_DN );
310 if ( rdns == NULL ) {
314 for ( p = rdns; *p != NULL; p++ ) {
315 len += strlen( *p ) + 1;
318 q = dce = LDAP_MALLOC( len + 1 );
323 p--; /* get back past NULL */
325 for ( ; p != rdns; p-- ) {
337 #else /* USE_LDAP_DN_PARSING */
338 Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
340 return dn2dn( dn, LDAP_DN_FORMAT_LDAPV3, LDAP_DN_FORMAT_DCE );
341 #endif /* USE_LDAP_DN_PARSING */
345 ldap_dcedn2dn( LDAP_CONST char *dce )
347 #ifndef USE_LDAP_DN_PARSING
348 char *dn, *q, **rdns, **p;
351 Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
353 rdns = explode_name( dce, 0, NAME_TYPE_DCE_DN );
354 if ( rdns == NULL ) {
360 for ( p = rdns; *p != NULL; p++ ) {
361 len += strlen( *p ) + 1;
364 q = dn = LDAP_MALLOC( len );
371 for ( ; p != rdns; p-- ) {
379 /* the name was fully qualified, thus the most-significant
380 * RDN was empty. trash the last comma */
384 /* the name was relative. copy the most significant RDN */
389 #else /* USE_LDAP_DN_PARSING */
390 Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
392 return dn2dn( dce, LDAP_DN_FORMAT_DCE, LDAP_DN_FORMAT_LDAPV3 );
393 #endif /* USE_LDAP_DN_PARSING */
400 explode_name( const char *name, int notypes, int is_type )
402 const char *p, *q, *rdn;
404 int offset, state, have_equals, count = 0, endquote, len;
407 if(name == NULL) name = "";
409 /* skip leading whitespace */
410 while( ldap_utf8_isspace( name )) {
411 LDAP_UTF8_INCR( name );
426 if ( p[1] != '\0' ) {
427 offset = LDAP_UTF8_OFFSET(++p);
431 if ( state == INQUOTE )
437 if( state == OUTQUOTE ) have_equals++;
440 if (is_type == NAME_TYPE_LDAP_RDN)
444 if (is_type == NAME_TYPE_DCE_DN)
449 if (is_type == NAME_TYPE_LDAP_DN)
454 if ( state == OUTQUOTE ) {
458 if ( parts == NULL ) {
459 if (( parts = (char **)LDAP_MALLOC( 8
460 * sizeof( char *))) == NULL )
462 } else if ( count >= 8 ) {
463 if (( parts = (char **)LDAP_REALLOC( parts,
464 (count+1) * sizeof( char *)))
469 parts[ count ] = NULL;
473 for ( q = rdn; q < p && *q != '='; ++q ) {
485 if ( p[-1] == '"' ) {
493 if (( parts[ count-1 ] = (char *)LDAP_CALLOC( 1,
496 AC_MEMCPY( parts[ count-1 ], rdn, len );
499 /* skip trailing spaces */
500 while( len > 0 && ldap_utf8_isspace(
501 &parts[count-1][len-1] ) )
507 parts[ count-1 ][ len ] = '\0';
511 * Don't forget to increment 'p' back to where
512 * it should be. If we don't, then we will
513 * never get past an "end quote."
518 rdn = *p ? &p[1] : p;
519 while ( ldap_utf8_isspace( rdn ) )
531 #define B4ATTRTYPE 0x0001
532 #define B4OIDATTRTYPE 0x0002
533 #define B4STRINGATTRTYPE 0x0003
535 #define B4AVAEQUALS 0x0100
536 #define B4AVASEP 0x0200
537 #define B4RDNSEP 0x0300
538 #define GOTAVA 0x0400
540 #define B4ATTRVALUE 0x0010
541 #define B4STRINGVALUE 0x0020
542 #define B4IA5VALUEQUOTED 0x0030
543 #define B4IA5VALUE 0x0040
544 #define B4BINARYVALUE 0x0050
546 /* Helpers (mostly from slapd.h; maybe it should be rewritten from this) */
547 #define LDAP_DN_ASCII_SPACE(c) \
548 ( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' )
549 #define LDAP_DN_ASCII_LOWER(c) ( (c) >= 'a' && (c) <= 'z' )
550 #define LDAP_DN_ASCII_UPPER(c) ( (c) >= 'A' && (c) <= 'Z' )
551 #define LDAP_DN_ASCII_ALPHA(c) \
552 ( LDAP_DN_ASCII_LOWER(c) || LDAP_DN_ASCII_UPPER(c) )
553 #define LDAP_DN_ASCII_DIGIT(c) ( (c) >= '0' && (c) <= '9' )
554 #define LDAP_DN_ASCII_LCASE_HEXALPHA(c) ( (c) >= 'a' && (c) <= 'f' )
555 #define LDAP_DN_ASCII_UCASE_HEXALPHA(c) ( (c) >= 'A' && (c) <= 'F' )
556 #define LDAP_DN_ASCII_HEXDIGIT(c) \
557 ( LDAP_DN_ASCII_DIGIT(c) \
558 || LDAP_DN_ASCII_LCASE_HEXALPHA(c) \
559 || LDAP_DN_ASCII_UCASE_HEXALPHA(c) )
560 #define LDAP_DN_ASCII_ALNUM(c) \
561 ( LDAP_DN_ASCII_ALPHA(c) || LDAP_DN_ASCII_DIGIT(c) )
562 #define LDAP_DN_ASCII_PRINTABLE(c) ( (c) >= ' ' && (c) <= '~' )
565 #define LDAP_DN_OID_LEADCHAR(c) ( LDAP_DN_ASCII_DIGIT(c) )
566 #define LDAP_DN_DESC_LEADCHAR(c) ( LDAP_DN_ASCII_ALPHA(c) )
567 #define LDAP_DN_DESC_CHAR(c) ( LDAP_DN_ASCII_ALNUM(c) || (c) == '-' )
568 #define LDAP_DN_LANG_SEP(c) ( (c) == ';' )
569 #define LDAP_DN_ATTRDESC_CHAR(c) \
570 ( LDAP_DN_DESC_CHAR(c) || LDAP_DN_LANG_SEP(c) )
572 /* special symbols */
573 #define LDAP_DN_AVA_EQUALS(c) ( (c) == '=' )
574 #define LDAP_DN_AVA_SEP(c) ( (c) == '+' )
575 #define LDAP_DN_RDN_SEP(c) ( (c) == ',' )
576 #define LDAP_DN_RDN_SEP_V2(c) ( LDAP_DN_RDN_SEP(c) || (c) == ';' )
577 #define LDAP_DN_OCTOTHORPE(c) ( (c) == '#' )
578 #define LDAP_DN_QUOTES(c) ( (c) == '\"' )
579 #define LDAP_DN_ESCAPE(c) ( (c) == '\\' )
580 #define LDAP_DN_VALUE_END(c) \
581 ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) )
582 #define LDAP_DN_NE(c) \
583 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
584 || LDAP_DN_QUOTES(c) || (c) == '<' || (c) == '>' )
585 #define LDAP_DN_NEEDESCAPE(c) \
586 ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) )
587 #define LDAP_DN_NEEDESCAPE_LEAD(c) \
588 ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) || LDAP_DN_NE(c) )
589 #define LDAP_DN_NEEDESCAPE_TRAIL(c) \
590 ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) )
593 #define LDAP_DN_VALUE_END_V2(c) \
594 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) )
596 #define LDAP_DN_V2_SPECIAL(c) \
597 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_EQUALS(c) \
598 || LDAP_DN_AVA_SEP(c) || (c) == '<' || (c) == '>' \
599 || LDAP_DN_OCTOTHORPE(c) )
600 #define LDAP_DN_V2_PAIR(c) \
601 ( LDAP_DN_V2_SPECIAL(c) || LDAP_DN_ESCAPE(c) || LDAP_DN_QUOTES(c) )
604 * DCE (mostly from Luke Howard and IBM implementation for AIX)
606 * From: "Application Development Guide - Directory Services" (FIXME: add link?)
607 * Here escapes and valid chars for GDS are considered; as soon as more
608 * specific info is found, the macros will be updated.
610 * Chars: 'a'-'z', 'A'-'Z', '0'-'9',
611 * '.', ':', ',', ''', '+', '-', '=', '(', ')', '?', '/', ' '.
613 * Metachars: '/', ',', '=', '\'.
615 * the '\' is used to escape other metachars.
617 * Attribute types must start with alphabetic chars and can contain
618 * alphabetic chars and digits (FIXME: no '-'?). OIDs are allowed.
620 #define LDAP_DN_RDN_SEP_DCE(c) ( (c) == '/' )
621 #define LDAP_DN_AVA_SEP_DCE(c) ( (c) == ',' )
622 #define LDAP_DN_ESCAPE_DCE(c) ( LDAP_DN_ESCAPE(c) )
623 #define LDAP_DN_VALUE_END_DCE(c) \
624 ( LDAP_DN_RDN_SEP_DCE(c) || LDAP_DN_AVA_SEP_DCE(c) )
625 #define LDAP_DN_NEEDESCAPE_DCE(c) \
626 ( LDAP_DN_VALUE_END_DCE(c) || LDAP_DN_AVA_EQUALS(c) )
629 #define LDAP_DN_RDN_SEP_AD(c) ( (c) == '/' )
630 #define LDAP_DN_ESCAPE_AD(c) ( LDAP_DN_ESCAPE(c) )
631 #define LDAP_DN_AVA_SEP_AD(c) ( (c) == ',' ) /* assume same as DCE */
632 #define LDAP_DN_VALUE_END_AD(c) \
633 ( LDAP_DN_RDN_SEP_AD(c) || LDAP_DN_AVA_SEP_AD(c) )
634 #define LDAP_DN_NEEDESCAPE_AD(c) \
635 ( LDAP_DN_VALUE_END_AD(c) || LDAP_DN_AVA_EQUALS(c) )
638 #define LDAP_DN_HEXPAIR(s) \
639 ( LDAP_DN_ASCII_HEXDIGIT((s)[0]) && LDAP_DN_ASCII_HEXDIGIT((s)[1]) )
640 #define LDAP_DC_ATTR "dc"
642 /* Composite rules */
643 #define LDAP_DN_ALLOW_SPACES(f) \
644 ( ( (f) & LDAP_DN_FORMAT_LDAPV2 ) || !( (f) & LDAP_DN_PEDANTIC ) )
645 #define LDAP_DN_LDAPV3(f) \
646 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV3 )
647 #define LDAP_DN_LDAPV2(f) \
648 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV2 )
649 #define LDAP_DN_DCE(f) \
650 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_DCE )
651 #define LDAP_DN_UFN(f) \
652 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_UFN )
653 #define LDAP_DN_ADC(f) \
654 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_AD_CANONICAL )
655 #define LDAP_DN_FORMAT(f) ( (f) & LDAP_DN_FORMAT_MASK )
661 ldapava_new( const char *attr, const struct berval *val, unsigned flags )
668 ava = LDAP_MALLOC( sizeof( LDAPAVA ) );
670 /* should we test it? */
675 ava->la_attr = ( char * )attr;
676 ava->la_value = ( struct berval * )val;
677 ava->la_flags = flags;
683 ldapava_free( LDAPAVA *ava )
687 LDAP_FREE( ava->la_attr );
688 ber_bvfree( ava->la_value );
694 ldapava_append_to_rdn( LDAPRDN *rdn, LDAPAVA *ava )
702 for ( i = 0U; rdn[ i ]; i++ ) {
706 newRDN = LDAP_REALLOC( rdn, ( i + 2 ) * sizeof( LDAPAVA ** ) );
707 newRDN[ i ] = LDAP_MALLOC( sizeof( LDAPAVA * ) );
708 newRDN[ i ][ 0 ] = ava;
709 newRDN[ i + 1 ] = NULL;
715 ldapava_free_rdn( LDAPRDN *rdn )
723 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
724 assert( rdn[ iAVA ][ 0 ] );
726 ldapava_free( rdn[ iAVA ][ 0 ] );
733 ldapava_append_to_dn( LDAPDN *dn, LDAPRDN *rdn )
741 for ( i = 0U; dn[ i ]; i++ ) {
745 newDN = LDAP_REALLOC( dn, ( i + 2 ) * sizeof( LDAPRDN ** ) );
746 newDN[ i ] = LDAP_MALLOC( sizeof( LDAPRDN * ) );
747 newDN[ i ][ 0 ] = rdn;
748 newDN[ i + 1 ] = NULL;
754 ldapava_insert_into_dn( LDAPDN *dn, LDAPRDN *rdn )
762 for ( i = 0U; dn[ i ]; i++ ) {
766 newDN = LDAP_MALLOC( ( i + 2 ) * sizeof( LDAPDN ) );
767 AC_MEMCPY( &newDN[ 1 ], dn, i * sizeof( LDAPDN * ) );
770 newDN[ 0 ] = LDAP_MALLOC( sizeof( LDAPRDN * ) );
771 newDN[ 0 ][ 0 ] = rdn;
772 newDN[ i + 1 ] = NULL;
778 ldapava_free_dn( LDAPDN *dn )
786 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
787 assert( dn[ iRDN ][ 0 ] );
789 ldapava_free_rdn( dn[ iRDN ][ 0 ] );
796 * Converts a string representation of a DN (in LDAPv3, LDAPv2 or DCE)
797 * into a structured representation of the DN, by separating attribute
798 * types and values encoded in the more appropriate form, which is
799 * string or OID for attribute types and binary form of the BER encoded
800 * value or Unicode string. Formats different from LDAPv3 are parsed
801 * according to their own rules and turned into the more appropriate
802 * form according to LDAPv3.
804 * NOTE: I realize the code is getting spaghettish; it is rather
805 * experimental and will hopefully turn into something more simple
806 * and readable as soon as it works as expected.
809 ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
813 int rc = LDAP_INVALID_DN_SYNTAX;
814 int attrTypeEncoding, attrValueEncoding;
816 char *attrType = NULL;
817 struct berval *attrValue = NULL;
819 LDAPDN *newDN = NULL;
820 LDAPRDN *newRDN = NULL;
825 Debug( LDAP_DEBUG_TRACE, "=> ldap_str2dn(%s,%u)\n%s", str, flags, "" );
829 switch ( LDAP_DN_FORMAT( flags ) ) {
830 case LDAP_DN_FORMAT_LDAPV3:
831 case LDAP_DN_FORMAT_LDAPV2:
832 case LDAP_DN_FORMAT_DCE:
835 /* unsupported in str2dn */
836 case LDAP_DN_FORMAT_UFN:
837 case LDAP_DN_FORMAT_AD_CANONICAL:
838 return( LDAP_INVALID_DN_SYNTAX );
841 return( LDAP_OTHER );
844 if ( str[ 0 ] == '\0' ) {
845 return( LDAP_SUCCESS );
849 if ( LDAP_DN_DCE( flags ) ) {
852 * (from Luke Howard: thnx) A RDN separator is required
853 * at the beginning of an (absolute) DN.
855 if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
861 for ( ; p[ 0 ] || state == GOTAVA; ) {
864 * The parser in principle advances one token a time,
865 * or toggles state if preferable.
870 * an AttributeType can be encoded as:
871 * - its string representation; in detail, implementations
872 * MUST recognize AttributeType string type names listed
873 * in section 2.3 of draft-ietf-ldapbis-dn-XX.txt, and
874 * MAY recognize other names.
875 * - its numeric OID (a dotted decimal string); in detail
876 * RFC 2253 asserts that ``Implementations MUST allow
877 * an oid in the attribute type to be prefixed by one
878 * of the character strings "oid." or "OID."''. As soon
879 * as draft-ietf-ldapbis-dn-XX.txt obsoletes RFC 2253
880 * I'm not sure whether this is required or not any
881 * longer; to be liberal, we still implement it.
884 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
885 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
890 /* whitespace is allowed (and trimmed) */
892 while ( p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
897 /* error: we expected an AVA */
907 if ( LDAP_DN_OID_LEADCHAR( p[ 0 ] ) ) {
908 state = B4OIDATTRTYPE;
912 /* else must be alpha */
913 if ( !LDAP_DN_DESC_LEADCHAR( p[ 0 ] ) ) {
917 /* LDAPv2 "oid." prefix */
918 if ( LDAP_DN_LDAPV2( flags ) ) {
920 * to be overly pedantic, we only accept
923 if ( flags & LDAP_DN_PEDANTIC ) {
924 if ( !strncmp( p, "oid.", 4 )
925 || !strncmp( p, "OID.", 4 ) ) {
927 state = B4OIDATTRTYPE;
931 if ( !strncasecmp( p, "oid.", 4 ) ) {
933 state = B4OIDATTRTYPE;
939 state = B4STRINGATTRTYPE;
942 case B4OIDATTRTYPE: {
943 int err = LDAP_SUCCESS;
945 attrType = parse_numericoid( &p, &err, 0 );
946 if ( attrType == NULL ) {
949 attrTypeEncoding = LDAP_AVA_BINARY;
955 case B4STRINGATTRTYPE: {
956 const char *startPos, *endPos = NULL;
960 * the starting char has been found to be
961 * a LDAP_DN_DESC_LEADCHAR so we don't re-check it
962 * FIXME: DCE attr types seem to have a more
965 for ( startPos = p++; p[ 0 ]; p++ ) {
966 if ( LDAP_DN_DESC_CHAR( p[ 0 ] ) ) {
970 if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) {
973 * RFC 2253 does not explicitly
974 * allow lang extensions to attribute
977 if ( flags & LDAP_DN_PEDANTIC ) {
982 * we trim ';' and following lang
983 * and so from attribute types
986 for ( ; LDAP_DN_ATTRDESC_CHAR( p[ 0 ] )
987 || LDAP_DN_LANG_SEP( p[ 0 ] ); p++ ) {
995 len = ( endPos ? endPos : p ) - startPos;
1000 assert( attrType == NULL );
1001 attrType = LDAP_STRNDUP( startPos, len );
1002 attrTypeEncoding = LDAP_AVA_STRING;
1005 * here we need to decide whether to use it as is
1006 * or turn it in OID form; as a consequence, we
1007 * need to decide whether to binary encode the value
1010 state = B4AVAEQUALS;
1015 /* spaces may not be allowed */
1016 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1017 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1022 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1027 /* need equal sign */
1028 if ( !LDAP_DN_AVA_EQUALS( p[ 0 ] ) ) {
1033 /* spaces may not be allowed */
1034 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1035 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1040 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1046 * octothorpe means a BER encoded value will follow
1047 * FIXME: I don't think DCE will allow it
1049 if ( LDAP_DN_OCTOTHORPE( p[ 0 ] ) ) {
1051 attrValueEncoding = LDAP_AVA_BINARY;
1052 state = B4BINARYVALUE;
1056 /* STRING value expected */
1059 * if we're pedantic, an attribute type in OID form
1060 * SHOULD imply a BER encoded attribute value; we
1061 * should at least issue a warning
1063 if ( ( flags & LDAP_DN_PEDANTIC )
1064 && ( attrTypeEncoding == LDAP_AVA_BINARY ) ) {
1065 /* OID attrType SHOULD use binary encoding */
1069 attrValueEncoding = LDAP_AVA_STRING;
1072 * LDAPv2 allows the attribute value to be quoted;
1073 * also, IA5 values are expected, in principle
1075 if ( LDAP_DN_LDAPV2( flags ) ) {
1076 if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
1078 state = B4IA5VALUEQUOTED;
1087 * here STRING means RFC 2253 string
1088 * FIXME: what about DCE strings?
1090 state = B4STRINGVALUE;
1094 if ( hexstr2binval( p, &attrValue, &p, flags ) ) {
1102 switch ( LDAP_DN_FORMAT( flags ) ) {
1103 case LDAP_DN_FORMAT_LDAPV3:
1104 if ( str2strval( p, &attrValue,
1106 &attrValueEncoding ) ) {
1111 case LDAP_DN_FORMAT_DCE:
1112 /* FIXME: does DCE use UTF-8? */
1113 if ( DCE2strval( p, &attrValue,
1127 if ( IA52strval( p, &attrValue, &p, flags ) ) {
1134 case B4IA5VALUEQUOTED:
1136 /* lead quote already stripped */
1137 if ( quotedIA52strval( p, &attrValue,
1151 * we accept empty values
1153 ava = ldapava_new( attrType, attrValue,
1154 attrValueEncoding );
1155 if ( ava == NULL ) {
1156 rc = LDAP_NO_MEMORY;
1160 rdn = ldapava_append_to_rdn( newRDN, ava );
1161 if ( rdn == NULL ) {
1162 rc = LDAP_NO_MEMORY;
1168 * if we got an AVA separator ('+', | ',' * for DCE )
1169 * we expect a new AVA for this RDN; otherwise
1170 * we add the RDN to the DN
1172 switch ( LDAP_DN_FORMAT( flags ) ) {
1173 case LDAP_DN_FORMAT_LDAPV3:
1174 case LDAP_DN_FORMAT_LDAPV2:
1175 if ( !LDAP_DN_AVA_SEP( p[ 0 ] ) ) {
1180 case LDAP_DN_FORMAT_DCE:
1181 if ( !LDAP_DN_AVA_SEP_DCE( p[ 0 ] ) ) {
1190 if ( LDAP_DN_DCE( flags ) ) {
1191 /* add in reversed order */
1192 dn = ldapava_insert_into_dn( newDN,
1195 dn = ldapava_append_to_dn( newDN,
1200 rc = LDAP_NO_MEMORY;
1205 if ( p[ 0 ] == '\0' ) {
1208 * the DN is over, phew
1214 /* expect AVA for a new RDN */
1218 /* they should have been used in an AVA */
1234 /* They are set to NULL after they're used in an AVA */
1236 LDAP_FREE( attrType );
1240 ber_bvfree( attrValue );
1244 ldapava_free_rdn( newRDN );
1248 ldapava_free_dn( newDN );
1254 Debug( LDAP_DEBUG_TRACE, "<= ldap_str2dn(%s,%u)=%d\n", str, flags, rc );
1261 * reads in a UTF-8 string value, unescaping stuff:
1262 * '\' + LDAP_DN_NEEDESCAPE(c) -> 'c'
1263 * '\' + HEXPAIR(p) -> unhex(p)
1266 str2strval( const char *str, struct berval **val, const char **next, unsigned flags, unsigned *retFlags )
1268 const char *p, *startPos, *endPos = NULL;
1269 ber_len_t len, escapes, unescapes;
1278 for ( startPos = p = str, escapes = 0, unescapes = 0; p[ 0 ]; p++ ) {
1279 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1281 if ( p[ 0 ] == '\0' ) {
1284 if ( ( p == startPos + 1 && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
1285 || ( LDAP_DN_VALUE_END( p[ 1 ] ) && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) )
1286 || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
1291 if ( LDAP_DN_HEXPAIR( p ) ) {
1297 * here I guess I need to decode
1298 * the byte; let's also check
1299 * the resulting encoding is a legal
1303 #endif /* PARSE_UTF8 */
1304 hexstr2bin( p, &c );
1306 cl = ldap_utf8_charlen( &c );
1308 for ( escapes += 2; --cl; escapes += 2 ) {
1312 * there must be another escaped
1315 if ( !LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1319 if ( !LDAP_DN_HEXPAIR( p ) ) {
1324 * that must be 10xxxxxx
1326 hexstr2bin( p, &c );
1327 if ( ( c & 0xc0 ) != 0x80 ) {
1331 #else /* !PARSE_UTF8 */
1333 #endif /* !PARSE_UTF8 */
1335 if ( !LDAP_DN_ASCII_PRINTABLE( c ) ) {
1338 * we assume the string is UTF-8
1340 *retFlags = LDAP_AVA_PRINTABLE;
1347 if ( LDAP_DN_PEDANTIC & flags ) {
1351 * FIXME: we allow escaping
1352 * of chars that don't need
1353 * to and do not belong to
1354 * HEXDIGITS (we also allow
1355 * single hexdigit; maybe we
1360 } else if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1363 } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
1365 * FIXME: maybe we can add
1366 * escapes if not pedantic?
1373 * we do allow unescaped spaces at the end
1374 * of the value only in non-pedantic mode
1376 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
1377 !LDAP_DN_ESCAPE( p[ -2 ] ) ) {
1378 if ( flags & LDAP_DN_PEDANTIC ) {
1382 /* strip trailing (unescaped) spaces */
1383 for ( endPos = p - 1;
1384 endPos > startPos + 1 &&
1385 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1386 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1393 * FIXME: test memory?
1395 len = ( endPos ? endPos : p ) - startPos - escapes - unescapes;
1396 *val = LDAP_MALLOC( sizeof( struct berval ) );
1397 ( *val )->bv_len = len;
1399 if ( escapes == 0 && unescapes == 0 ) {
1400 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1404 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1405 for ( s = 0, d = 0; d < len; ) {
1406 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
1408 if ( ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( startPos[ s ] ) )
1409 || ( s == len - 1 && LDAP_DN_NEEDESCAPE_TRAIL( startPos[ s ] ) )
1410 || LDAP_DN_NEEDESCAPE( startPos[ s ] ) ) {
1411 ( *val )->bv_val[ d++ ] =
1413 } else if ( LDAP_DN_HEXPAIR( &startPos[ s ] ) ) {
1416 hexstr2bin( &startPos[ s ], &c );
1417 ( *val )->bv_val[ d++ ] = c;
1421 * we allow escaping of chars
1422 * that do not need to
1424 ( *val )->bv_val[ d++ ] =
1429 ( *val )->bv_val[ d++ ] = startPos[ s++ ];
1433 ( *val )->bv_val[ d ] = '\0';
1434 assert( strlen( ( *val )->bv_val ) == len );
1444 DCE2strval( const char *str, struct berval **val, const char **next, unsigned flags )
1446 const char *p, *startPos, *endPos = NULL;
1447 ber_len_t len, escapes;
1456 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
1457 if ( LDAP_DN_ESCAPE_DCE( p[ 0 ] ) ) {
1459 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
1464 } else if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1469 * FIXME: can we accept anything else? I guess we need
1470 * to stop if a value is not legal
1475 * (unescaped) trailing spaces are trimmed must be silently ignored;
1478 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
1479 !LDAP_DN_ESCAPE( p[ -2 ] ) ) {
1480 if ( flags & LDAP_DN_PEDANTIC ) {
1484 /* strip trailing (unescaped) spaces */
1485 for ( endPos = p - 1;
1486 endPos > startPos + 1 &&
1487 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1488 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1495 len = ( endPos ? endPos : p ) - startPos - escapes;
1496 *val = LDAP_MALLOC( sizeof( struct berval ) );
1497 ( *val )->bv_len = len;
1498 if ( escapes == 0 ){
1499 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1503 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1504 for ( s = 0, d = 0; d < len; ) {
1506 * This point is reached only if escapes
1507 * are properly used, so all we need to
1510 if ( LDAP_DN_ESCAPE_DCE( startPos[ s ] ) ) {
1514 ( *val )->bv_val[ d++ ] = startPos[ s++ ];
1516 ( *val )->bv_val[ d ] = '\0';
1517 assert( strlen( ( *val )->bv_val ) == len );
1526 IA52strval( const char *str, struct berval **val, const char **next, unsigned flags )
1528 const char *p, *startPos, *endPos = NULL;
1529 ber_len_t len, escapes;
1542 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
1543 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1545 if ( p[ 0 ] == '\0' ) {
1549 if ( !LDAP_DN_NEEDESCAPE( p[ 0 ] )
1550 && ( LDAP_DN_PEDANTIC & flags ) ) {
1555 } else if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
1560 * FIXME: can we accept anything else? I guess we need
1561 * to stop if a value is not legal
1565 /* strip trailing (unescaped) spaces */
1567 endPos > startPos + 1 &&
1568 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1569 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1574 *val = LDAP_MALLOC( sizeof( struct berval ) );
1575 len = ( endPos ? endPos : p ) - startPos - escapes;
1576 ( *val )->bv_len = len;
1577 if ( escapes == 0 ) {
1578 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1582 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1583 for ( s = 0, d = 0; d < len; ) {
1584 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
1587 ( *val )->bv_val[ d++ ] = startPos[ s++ ];
1589 ( *val )->bv_val[ d ] = '\0';
1590 assert( strlen( ( *val )->bv_val ) == len );
1598 quotedIA52strval( const char *str, struct berval **val, const char **next, unsigned flags )
1600 const char *p, *startPos, *endPos = NULL;
1602 unsigned escapes = 0;
1611 /* initial quote already eaten */
1612 for ( startPos = p = str; p[ 0 ]; p++ ) {
1614 * According to RFC 1779, the quoted value can
1615 * contain escaped as well as unescaped special values;
1616 * as a consequence we tolerate escaped values
1617 * (e.g. '"\,"' -> '\,') and escape unescaped specials
1618 * (e.g. '","' -> '\,').
1620 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1621 if ( p[ 1 ] == '\0' ) {
1626 if ( !LDAP_DN_V2_PAIR( p[ 0 ] )
1627 && ( LDAP_DN_PEDANTIC & flags ) ) {
1629 * do we allow to escape normal chars?
1630 * LDAPv2 does not allow any mechanism
1631 * for escaping chars with '\' and hex
1638 } else if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
1640 /* eat closing quotes */
1646 * FIXME: can we accept anything else? I guess we need
1647 * to stop if a value is not legal
1651 if ( endPos == NULL ) {
1655 /* Strip trailing (unescaped) spaces */
1656 for ( ; p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1660 len = endPos - startPos - escapes;
1662 *val = LDAP_MALLOC( sizeof( struct berval ) );
1663 ( *val )->bv_len = len;
1664 if ( escapes == 0 ) {
1665 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1669 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1670 ( *val )->bv_len = len;
1672 for ( s = d = 0; d < len; ) {
1673 if ( LDAP_DN_ESCAPE( str[ s ] ) ) {
1676 ( *val )->bv_val[ d++ ] = str[ s++ ];
1678 ( *val )->bv_val[ d ] = '\0';
1679 assert( strlen( ( *val )->bv_val ) == len );
1688 hexstr2bin( const char *str, char *c )
1698 if ( LDAP_DN_ASCII_DIGIT( c1 ) ) {
1703 if ( LDAP_DN_ASCII_LCASE_HEXALPHA( c1 ) ) {
1710 if ( LDAP_DN_ASCII_DIGIT( c2 ) ) {
1715 if ( LDAP_DN_ASCII_LCASE_HEXALPHA( c2 ) ) {
1716 *c += c2 - 'a' + 10;
1724 hexstr2binval( const char *str, struct berval **val, const char **next, unsigned flags )
1726 const char *p, *startPos, *endPos = NULL;
1737 for ( startPos = p = str; p[ 0 ]; p += 2 ) {
1738 switch ( LDAP_DN_FORMAT( flags ) ) {
1739 case LDAP_DN_FORMAT_LDAPV3:
1740 case LDAP_DN_FORMAT_LDAPV2:
1741 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1746 case LDAP_DN_FORMAT_DCE:
1747 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1753 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1754 if ( flags & LDAP_DN_PEDANTIC ) {
1759 for ( ; p[ 0 ]; p++ ) {
1760 switch ( LDAP_DN_FORMAT( flags ) ) {
1761 case LDAP_DN_FORMAT_LDAPV3:
1762 case LDAP_DN_FORMAT_LDAPV2:
1763 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1768 case LDAP_DN_FORMAT_DCE:
1769 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1778 if ( !LDAP_DN_HEXPAIR( p ) ) {
1785 len = ( ( endPos ? endPos : p ) - startPos ) / 2;
1787 assert( 2 * len == ( endPos ? endPos : p ) - startPos );
1789 *val = LDAP_MALLOC( sizeof( struct berval ) );
1790 if ( *val == NULL ) {
1791 return( LDAP_NO_MEMORY );
1794 ( *val )->bv_len = len;
1795 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1796 if ( ( *val )->bv_val == NULL ) {
1798 return( LDAP_NO_MEMORY );
1801 for ( s = 0, d = 0; d < len; s += 2, d++ ) {
1804 hexstr2bin( &startPos[ s ], &c );
1806 ( *val )->bv_val[ d ] = c;
1809 ( *val )->bv_val[ d ] = '\0';
1816 * convert a byte in a hexadecimal pair
1819 byte2hexpair( const char *val, char *pair )
1821 static const char hexdig[] = "0123456789abcdef";
1827 * we assume the string has enough room for the hex encoding
1831 pair[ 0 ] = hexdig[ 0x0f & ( val[ 0 ] >> 4 ) ];
1832 pair[ 1 ] = hexdig[ 0x0f & val[ 0 ] ];
1838 * convert a binary value in hexadecimal pairs
1841 binval2hexstr( struct berval *val, char *str )
1848 if ( val->bv_len == 0 ) {
1853 * we assume the string has enough room for the hex encoding
1857 for ( s = 0, d = 0; s < val->bv_len; s++, d += 2 ) {
1858 byte2hexpair( &val->bv_val[ s ], &str[ d ] );
1865 * Length of the string representation, accounting for escaped hex
1869 strval2strlen( struct berval *val, unsigned flags )
1871 ber_len_t l, cl = 1;
1876 if ( val->bv_len == 0 ) {
1880 for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) {
1882 cl = ldap_utf8_charlen( p );
1884 /* need to escape it */
1886 #else /* !PARSE_UTF8 */
1887 if ( ( p[ 0 ] & 0x80 ) != 0x00 ) {
1888 /* need to escape it */
1890 #endif /* !PARSE_UTF8 */
1891 } else if ( ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
1892 || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) )
1893 || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
1904 * convert to string representation, escaping with hex the UTF-8 stuff;
1905 * assume the destination has enough room for escaping
1908 strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
1910 ber_len_t s, d, end;
1916 if ( val->bv_len == 0 ) {
1922 * we assume the string has enough room for the hex encoding
1925 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
1927 ber_len_t cl = ldap_utf8_charlen( &val->bv_val[ s ] );
1931 #else /* !PARSE_UTF8 */
1932 if ( ( val->bv_val[ s ] & 0x80 ) != 0x00 ) {
1933 #endif /* !PARSE_UTF8 */
1935 byte2hexpair( &val->bv_val[ s ], &str[ d ] );
1940 #endif /* !PARSE_UTF8 */
1942 if ( ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
1943 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
1944 || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) ) {
1947 str[ d++ ] = val->bv_val[ s++ ];
1957 * Length of the IA5 string representation (no UTF-8 allowed)
1960 strval2IA5strlen( struct berval *val, unsigned flags )
1967 if ( val->bv_len == 0 ) {
1971 if ( flags & LDAP_AVA_PRINTABLE ) {
1973 * Turn value into a binary encoded BER
1978 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
1979 if ( ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
1980 || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) )
1981 || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
1993 * convert to string representation (np UTF-8)
1994 * assume the destination has enough room for escaping
1997 strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
1999 ber_len_t s, d, end;
2005 if ( val->bv_len == 0 ) {
2010 if ( flags & LDAP_AVA_PRINTABLE ) {
2012 * Turn value into a binary encoded BER
2019 * we assume the string has enough room for the hex encoding
2023 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
2024 if ( ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
2025 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
2026 || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) ) {
2029 str[ d++ ] = val->bv_val[ s++ ];
2039 * Length of the (supposedly) DCE string representation,
2040 * accounting for escaped hex of UTF-8 chars
2043 strval2DCEstrlen( struct berval *val, unsigned flags )
2050 if ( val->bv_len == 0 ) {
2054 if ( flags & LDAP_AVA_PRINTABLE ) {
2056 * FIXME: Turn the value into a binary encoded BER?
2061 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2062 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
2074 * convert to (supposedly) DCE string representation,
2075 * escaping with hex the UTF-8 stuff;
2076 * assume the destination has enough room for escaping
2079 strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2087 if ( val->bv_len == 0 ) {
2092 if ( flags & LDAP_AVA_PRINTABLE ) {
2094 * FIXME: Turn the value into a binary encoded BER?
2102 * we assume the string has enough room for the hex encoding
2106 for ( s = 0, d = 0; s < val->bv_len; ) {
2107 if ( LDAP_DN_NEEDESCAPE_DCE( val->bv_val[ s ] ) ) {
2110 str[ d++ ] = val->bv_val[ s++ ];
2120 * Length of the (supposedly) AD canonical string representation,
2121 * accounting for escaped hex of UTF-8 chars
2124 strval2ADstrlen( struct berval *val, unsigned flags )
2131 if ( val->bv_len == 0 ) {
2135 if ( flags & LDAP_AVA_PRINTABLE ) {
2137 * FIXME: Turn the value into a binary encoded BER?
2142 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2143 if ( LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
2155 * convert to (supposedly) AD string representation,
2156 * escaping with hex the UTF-8 stuff;
2157 * assume the destination has enough room for escaping
2160 strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2168 if ( val->bv_len == 0 ) {
2173 if ( flags & LDAP_AVA_PRINTABLE ) {
2175 * FIXME: Turn the value into a binary encoded BER?
2183 * we assume the string has enough room for the hex encoding
2187 for ( s = 0, d = 0; s < val->bv_len; ) {
2188 if ( LDAP_DN_NEEDESCAPE_AD( val->bv_val[ s ] ) ) {
2191 str[ d++ ] = val->bv_val[ s++ ];
2201 * If the DN is terminated by single-AVA RDNs with attribute type of "dc",
2202 * the forst part of the AD representation of the DN is written in DNS
2203 * form, i.e. dot separated domain name components (as suggested
2204 * by Luke Howard, http://www.padl.com/~lukeh)
2207 dn2domain( LDAPDN *dn, char **str, int *iRDN )
2210 int domain = 0, first = 1;
2211 ber_len_t l = 1; /* we move the null also */
2213 /* we are guaranteed there's enough memory in str */
2220 assert( *iRDN > 0 );
2222 for ( i = *iRDN; i >= 0; i-- ) {
2226 assert( dn[ i ][ 0 ] );
2229 assert( rdn[ 0 ][ 0 ] );
2230 ava = rdn[ 0 ][ 0 ];
2232 /* FIXME: no composite rdn or non-"dc" types, right? */
2233 /* FIXME: we do not allow binary values in domain, right? */
2234 if ( rdn[ 1 ] || strcasecmp( ava->la_attr, LDAP_DC_ATTR )
2235 || ava->la_flags != LDAP_AVA_STRING ) {
2243 AC_MEMCPY( *str, ava->la_value->bv_val,
2244 ava->la_value->bv_len + 1);
2245 l += ava->la_value->bv_len;
2247 AC_MEMCPY( *str + ava->la_value->bv_len + 1, *str, l);
2248 AC_MEMCPY( *str, ava->la_value->bv_val,
2249 ava->la_value->bv_len );
2250 ( *str )[ ava->la_value->bv_len ] = '.';
2251 l += ava->la_value->bv_len + 1;
2261 rdn2strlen( LDAPRDN *rdn )
2266 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2267 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2269 /* len(type) + '=' + '+' | ',' */
2270 len += strlen( ava->la_attr ) + 2;
2272 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2273 /* octothorpe + twice the length */
2274 len += 1 + 2 * ava->la_value->bv_len;
2276 len += strval2strlen( ava->la_value, ava->la_flags );
2284 rdn2str( LDAPRDN *rdn, char *str, ber_len_t *len )
2289 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2290 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2291 ber_len_t al = strlen( ava->la_attr );
2293 AC_MEMCPY( &str[ l ], ava->la_attr, al );
2298 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2300 binval2hexstr( ava->la_value, &str[ l ] );
2301 l += 2 * ava->la_value->bv_len;
2304 strval2str( ava->la_value, &str[ l ],
2305 ava->la_flags, &vl );
2308 str[ l++ ] = ( rdn[ iAVA + 1 ] ? '+' : ',' );
2317 rdn2UFNstrlen( LDAPRDN *rdn )
2322 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2323 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2326 len += ( rdn[ iAVA + 1 ] ? 3 : 2 );
2328 /* FIXME: are binary values allowed in UFN? */
2329 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2330 /* octothorpe + twice the value */
2331 len += 1 + 2 * ava->la_value->bv_len;
2333 len += strval2strlen( ava->la_value, ava->la_flags );
2341 rdn2UFNstr( LDAPRDN *rdn, char *str, ber_len_t *len )
2346 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2347 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2349 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2351 binval2hexstr( ava->la_value, &str[ l ] );
2352 l += 2 * ava->la_value->bv_len;
2355 strval2str( ava->la_value, &str[ l ],
2356 ava->la_flags, &vl );
2360 if ( rdn[ iAVA + 1 ]) {
2361 AC_MEMCPY( &str[ l ], " + ", 3 );
2364 AC_MEMCPY( &str[ l ], ", ", 2 );
2375 ldap_rdn2str( LDAPRDN *rdn, char **str, unsigned flags )
2382 if ( rdn == NULL ) {
2383 *str = LDAP_STRDUP( "" );
2384 return( LDAP_SUCCESS );
2387 switch ( LDAP_DN_FORMAT( flags ) ) {
2388 case LDAP_DN_FORMAT_LDAPV3:
2389 l = rdn2strlen( rdn );
2392 case LDAP_DN_FORMAT_UFN:
2393 l = rdn2UFNstrlen( rdn );
2397 return( LDAP_OTHER );
2400 *str = LDAP_MALLOC( l + 1 );
2402 switch ( LDAP_DN_FORMAT( flags ) ) {
2403 case LDAP_DN_FORMAT_LDAPV3:
2404 rc = rdn2str( rdn, *str, &l );
2408 case LDAP_DN_FORMAT_UFN:
2409 rc = rdn2UFNstr( rdn, *str, &l );
2415 ldap_memfree( *str );
2416 return( LDAP_OTHER );
2419 ( *str )[ l - back ] = '\0';
2421 return( LDAP_SUCCESS );
2425 * Very bulk implementation; many optimizations can be performed
2426 * - a NULL dn results in an empty string ""
2429 * a) what do we do if a UTF-8 string must be converted in LDAPv2?
2430 * we must encode it in binary form ('#' + HEXPAIRs)
2431 * b) does DCE/AD support UTF-8?
2432 * no clue; don't think so.
2433 * c) what do we do when binary values must be converted in UTF/DCE/AD?
2434 * use binary encoded BER
2436 int ldap_dn2str( LDAPDN *dn, char **str, unsigned flags )
2439 int rc = LDAP_OTHER;
2442 ber_len_t ( *s2l )( struct berval *, unsigned );
2443 int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * );
2447 Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2str(%u)\n%s%s", flags, "", "" );
2452 *str = LDAP_STRDUP( "" );
2453 return( LDAP_SUCCESS );
2456 switch ( LDAP_DN_FORMAT( flags ) ) {
2457 case LDAP_DN_FORMAT_LDAPV3:
2458 s2l = strval2strlen;
2462 * LDAPv3 uses helpers
2464 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
2465 len += rdn2strlen( dn[ iRDN ][ 0 ] );
2468 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2469 rc = LDAP_NO_MEMORY;
2473 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
2475 rdn2str( dn[ iRDN ][ 0 ], &( *str )[ l ], &vl );
2482 * trim the last ',' (the allocated memory
2483 * is one byte longer than required)
2485 ( *str )[ len - 1 ] = '\0';
2490 case LDAP_DN_FORMAT_LDAPV2:
2491 s2l = strval2IA5strlen;
2492 s2s = strval2IA5str;
2495 * LDAPv2 follows the regular path
2497 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
2498 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2500 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2501 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2503 /* len(type) + '=' + '+' | ',' */
2504 len += strlen( ava->la_attr ) + 2;
2506 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2507 /* octothorpe + twice the length */
2508 len += 1 + 2 * ava->la_value->bv_len;
2510 len += ( *s2l )( ava->la_value,
2516 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2517 rc = LDAP_NO_MEMORY;
2521 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
2522 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2524 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2525 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2526 ber_len_t al = strlen( ava->la_attr );
2528 AC_MEMCPY( &( *str )[ l ], ava->la_attr, al );
2531 ( *str )[ l++ ] = '=';
2533 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2534 ( *str )[ l++ ] = '#';
2535 binval2hexstr( ava->la_value,
2537 l += 2 * ava->la_value->bv_len;
2540 ( *s2s )( ava->la_value,
2542 ava->la_flags, &vl );
2546 ( rdn[ iAVA + 1 ] ? '+' : ',' );
2551 * trim the last ',' (the allocated memory
2552 * is one byte longer than required)
2554 ( *str )[ len - 1 ] = '\0';
2559 case LDAP_DN_FORMAT_UFN:
2562 * FIXME: quoting from RFC 1781:
2564 To take a distinguished name, and generate a name of this format with
2565 attribute types omitted, the following steps are followed.
2567 1. If the first attribute is of type CommonName, the type may be
2570 2. If the last attribute is of type Country, the type may be
2573 3. If the last attribute is of type Country, the last
2574 Organisation attribute may have the type omitted.
2576 4. All attributes of type OrganisationalUnit may have the type
2577 omitted, unless they are after an Organisation attribute or
2578 the first attribute is of type OrganisationalUnit.
2580 * this should be the pedantic implementation.
2581 * A non-standard but nice implementation could
2582 * be to turn the final "dc" attributes into a
2583 * dot-separated domain.
2584 * Other improvements could involve the use of
2585 * friendly country names and so.
2588 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
2589 len += rdn2UFNstrlen( dn[ iRDN ][ 0 ] );
2592 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2593 rc = LDAP_NO_MEMORY;
2597 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
2599 rdn2UFNstr( dn[ iRDN ][ 0 ], &( *str )[ l ], &vl );
2604 * trim the last ', ' (the allocated memory
2605 * is two bytes longer than required)
2607 ( *str )[ len - 2 ] = '\0';
2612 case LDAP_DN_FORMAT_DCE:
2613 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
2614 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2616 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2617 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2619 /* len(type) + '=' + ( ',' || '/' ) */
2620 len += strlen( ava->la_attr ) + 2;
2622 /* FIXME: are binary values allowed in DCE? */
2623 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2624 /* octothorpe + twice the value */
2625 len += 1 + 2 * ava->la_value->bv_len;
2627 len += strval2DCEstrlen( ava->la_value,
2633 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2634 rc = LDAP_NO_MEMORY;
2638 for ( l = 0; iRDN--; ) {
2639 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2642 * DCE uses ',' for composite RDNs
2644 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2645 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2646 ber_len_t al = strlen( ava->la_attr );
2648 ( *str )[ l++ ] = ( iAVA ? ',' : '/' );
2649 AC_MEMCPY( &( *str )[ l ], ava->la_attr, al );
2651 ( *str )[ l++ ] = '=';
2652 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2653 ( *str )[ l++ ]= '#';
2654 binval2hexstr( ava->la_value,
2656 l += 2 * ava->la_value->bv_len;
2659 strval2DCEstr( ava->la_value,
2661 ava->la_flags, &vl );
2667 ( *str )[ len ] = '\0';
2672 case LDAP_DN_FORMAT_AD_CANONICAL: {
2673 for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) {
2674 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2676 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2677 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2679 /* ',' || '/' || '.' */
2682 /* FIXME: are binary values allowed in AD? */
2683 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2684 /* octothorpe + twice the value */
2685 len += 1 + 2 * ava->la_value->bv_len;
2687 len += strval2ADstrlen( ava->la_value,
2693 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2694 rc = LDAP_NO_MEMORY;
2699 if ( iRDN && dn2domain( dn, str, &iRDN ) ) {
2700 for ( l = strlen( *str ); iRDN >= 0 ; iRDN-- ) {
2701 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2703 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2704 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2706 ( *str)[ l++ ] = ( iAVA ? ',' : '/' );
2707 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2708 ( *str )[ l++ ] = '#';
2709 binval2hexstr( ava->la_value,
2711 l += 2 * ava->la_value->bv_len;
2714 strval2ADstr( ava->la_value,
2726 * Strictly speaking, AD canonical requires
2727 * a DN to be in the form "..., dc=smtg",
2728 * i.e. terminated by a domain component
2730 if ( flags & LDAP_DN_PEDANTIC ) {
2733 rc = LDAP_INVALID_DN_SYNTAX;
2737 for ( l = 0; iRDN >= 0 ; iRDN-- ) {
2738 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2740 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2741 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2747 ( iAVA ? ',' : '/' );
2749 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2750 ( *str )[ l++ ] = '#';
2751 binval2hexstr( ava->la_value,
2753 l += 2 * ava->la_value->bv_len;
2756 strval2ADstr( ava->la_value,
2766 ( *str )[ len ] = '\0';
2777 Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2str(%s,%u)=%d\n", *str, flags, rc );