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 /* forces the use of new dn parsing routines */
27 /* #define USE_LDAP_DN_PARSING */
28 /* extension to UFN that turns trailing "dc=value" rdns in DNS style,
29 * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */
32 static char *dn2dn( const char *dnin, unsigned fin, unsigned fout );
34 /* from libraries/libldap/schema.c */
35 extern char * parse_numericoid(const char **sp, int *code, const int flags);
37 /* parsing/printing routines */
38 static int str2strval( const char *str, struct berval **val,
39 const char **next, unsigned flags, unsigned *retFlags );
40 static int DCE2strval( const char *str, struct berval **val,
41 const char **next, unsigned flags );
42 static int IA52strval( const char *str, struct berval **val,
43 const char **next, unsigned flags );
44 static int quotedIA52strval( const char *str, struct berval **val,
45 const char **next, unsigned flags );
46 static int hexstr2binval( const char *str, struct berval **val,
47 const char **next, unsigned flags );
48 static int hexstr2bin( const char *str, char *c );
49 static int byte2hexpair( const char *val, char *pair );
50 static int binval2hexstr( struct berval *val, char *str );
51 static int strval2strlen( struct berval *val, unsigned flags,
53 static int strval2str( struct berval *val, char *str, unsigned flags,
55 static int strval2IA5strlen( struct berval *val, unsigned flags,
57 static int strval2IA5str( struct berval *val, char *str, unsigned flags,
59 static int strval2DCEstrlen( struct berval *val, unsigned flags,
61 static int strval2DCEstr( struct berval *val, char *str, unsigned flags,
63 static int strval2ADstrlen( struct berval *val, unsigned flags,
65 static int strval2ADstr( struct berval *val, char *str, unsigned flags,
67 static int dn2domain( LDAPDN *dn, char *str, int *iRDN );
70 LDAPAVA * ldapava_new( const char *attr, const struct berval *val,
72 void ldapava_free( LDAPAVA *ava );
73 LDAPRDN * ldapava_append_to_rdn( LDAPRDN *rdn, LDAPAVA *ava );
74 LDAPRDN * ldapava_insert_into_rdn( LDAPRDN *rdn, LDAPAVA *ava, unsigned where );
75 void ldapava_free_rdn( LDAPRDN *rdn );
76 LDAPDN * ldapava_append_to_dn( LDAPDN *dn, LDAPRDN *rdn );
77 LDAPDN * ldapava_insert_into_dn( LDAPDN *dn, LDAPRDN *rdn, unsigned where );
78 void ldapava_free_dn( LDAPDN *dn );
80 /* Higher level helpers */
81 static int rdn2strlen( LDAPRDN *rdn, ber_len_t *len,
82 int ( *s2l )( struct berval *, unsigned, ber_len_t * ) );
83 static int rdn2str( LDAPRDN *rdn, char *str, ber_len_t *len,
84 int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * ));
85 static int rdn2UFNstrlen( LDAPRDN *rdn, ber_len_t *len );
86 static int rdn2UFNstr( LDAPRDN *rdn, char *str, ber_len_t *len );
89 int ldap_rdn2str( LDAPRDN *rdn, char **str, unsigned flags );
91 #ifndef USE_LDAP_DN_PARSING /* deprecated */
92 #define NAME_TYPE_LDAP_RDN 0
93 #define NAME_TYPE_LDAP_DN 1
94 #define NAME_TYPE_DCE_DN 2
96 static char **explode_name( const char *name, int notypes, int is_type );
97 #endif /* !USE_LDAP_DN_PARSING */
100 * RFC 1823 ldap_get_dn
103 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
108 Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
110 if ( entry == NULL ) {
111 ld->ld_errno = LDAP_PARAM_ERROR;
115 tmp = *entry->lm_ber; /* struct copy */
116 if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) {
117 ld->ld_errno = LDAP_DECODING_ERROR;
125 * RFC 1823 ldap_dn2ufn
128 ldap_dn2ufn( LDAP_CONST char *dn )
130 #ifndef USE_LDAP_DN_PARSING /* deprecated */
135 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
137 /* produces completely untyped UFNs */
143 vals = ldap_explode_dn( dn , 0 );
148 for ( i = 0; vals[i]; i++ ) {
151 rvals = ldap_explode_rdn( vals[i] , 1 );
152 if ( rvals == NULL ) {
157 LDAP_FREE( vals[i] );
158 vals[i] = ldap_charray2str( rvals, " + " );
162 ufn = ldap_charray2str( vals, ", " );
166 #else /* USE_LDAP_DN_PARSING */
167 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
169 return dn2dn( dn, LDAP_DN_FORMAT_LDAPV3, LDAP_DN_FORMAT_UFN );
170 #endif /* USE_LDAP_DN_PARSING */
174 * RFC 1823 ldap_explode_dn
177 ldap_explode_dn( LDAP_CONST char *dn, int notypes )
179 #ifndef USE_LDAP_DN_PARSING /* deprecated */
180 Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
182 return explode_name( dn, notypes, NAME_TYPE_LDAP_DN );
183 #else /* USE_LDAP_DN_PARSING */
185 char **values = NULL;
187 unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3;
189 Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
191 if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAPV3 )
196 for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) {
197 char *str, **v = NULL;
199 ldap_rdn2str( tmpDN[ iRDN ][ 0 ], &str, flag );
201 v = LDAP_REALLOC( values, sizeof( char * ) * ( 2 + iRDN ) );
203 LBER_VFREE( values );
204 ldapava_free_dn( tmpDN );
208 values[ iRDN ] = str;
210 values[ iRDN ] = NULL;
213 #endif /* USE_LDAP_DN_PARSING */
217 ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
219 #ifndef USE_LDAP_DN_PARSING /* deprecated */
220 Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
222 return explode_name( rdn, notypes, NAME_TYPE_LDAP_RDN );
223 #else /* USE_LDAP_DN_PARSING */
225 char **values = NULL;
227 unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3;
229 Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
232 * we assume this dn is made of one rdn only
234 if ( ldap_str2dn( rdn, &tmpDN, LDAP_DN_FORMAT_LDAPV3 )
239 for ( iAVA = 0; tmpDN[ 0 ][ 0 ][ iAVA ]; iAVA++ ) {
240 ber_len_t l = 0, vl, al = 0;
241 char *str, **v = NULL;
242 LDAPAVA *ava = tmpDN[ 0 ][ 0 ][ iAVA ][ 0 ];
244 v = LDAP_REALLOC( values, sizeof( char * ) * ( 2 + iAVA ) );
250 if ( ava->la_flags == LDAP_AVA_BINARY ) {
251 vl = 1 + 2 * ava->la_value->bv_len;
256 if ( strval2strlen( ava->la_value,
257 ava->la_flags, &vl ) ) {
263 al = strlen( ava->la_attr );
267 str = LDAP_MALLOC( l + 1 );
268 AC_MEMCPY( str, ava->la_attr, al );
273 str = LDAP_MALLOC( l + 1 );
276 if ( ava->la_flags == LDAP_AVA_BINARY ) {
278 if ( binval2hexstr( ava->la_value, &str[ al ] ) ) {
283 if ( strval2str( ava->la_value, &str[ al ],
284 ava->la_flags, &vl ) ) {
290 values[ iAVA ] = str;
292 values[ iAVA ] = NULL;
294 ldapava_free_dn( tmpDN );
299 LBER_VFREE( values );
300 ldapava_free_dn( tmpDN );
302 #endif /* USE_LDAP_DN_PARSING */
306 ldap_dn2dcedn( LDAP_CONST char *dn )
308 #ifndef USE_LDAP_DN_PARSING /* deprecated */
309 char *dce, *q, **rdns, **p;
312 Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
314 rdns = explode_name( dn, 0, NAME_TYPE_LDAP_DN );
315 if ( rdns == NULL ) {
319 for ( p = rdns; *p != NULL; p++ ) {
320 len += strlen( *p ) + 1;
323 q = dce = LDAP_MALLOC( len + 1 );
328 p--; /* get back past NULL */
330 for ( ; p != rdns; p-- ) {
342 #else /* USE_LDAP_DN_PARSING */
343 Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
345 return dn2dn( dn, LDAP_DN_FORMAT_LDAPV3, LDAP_DN_FORMAT_DCE );
346 #endif /* USE_LDAP_DN_PARSING */
350 ldap_dcedn2dn( LDAP_CONST char *dce )
352 #ifndef USE_LDAP_DN_PARSING
353 char *dn, *q, **rdns, **p;
356 Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
358 rdns = explode_name( dce, 0, NAME_TYPE_DCE_DN );
359 if ( rdns == NULL ) {
365 for ( p = rdns; *p != NULL; p++ ) {
366 len += strlen( *p ) + 1;
369 q = dn = LDAP_MALLOC( len );
376 for ( ; p != rdns; p-- ) {
384 /* the name was fully qualified, thus the most-significant
385 * RDN was empty. trash the last comma */
389 /* the name was relative. copy the most significant RDN */
394 #else /* USE_LDAP_DN_PARSING */
395 Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
397 return dn2dn( dce, LDAP_DN_FORMAT_DCE, LDAP_DN_FORMAT_LDAPV3 );
398 #endif /* USE_LDAP_DN_PARSING */
402 ldap_dn2ad_canonical( LDAP_CONST char *dn )
404 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n", 0, 0, 0 );
406 return dn2dn( dn, LDAP_DN_FORMAT_LDAPV3, LDAP_DN_FORMAT_AD_CANONICAL );
409 #ifndef USE_LDAP_DN_PARSING /* deprecated */
414 explode_name( const char *name, int notypes, int is_type )
416 const char *p, *q, *rdn;
418 int offset, state, have_equals, count = 0, endquote, len;
421 if(name == NULL) name = "";
423 /* skip leading whitespace */
424 while( ldap_utf8_isspace( name )) {
425 LDAP_UTF8_INCR( name );
440 if ( p[1] != '\0' ) {
441 offset = LDAP_UTF8_OFFSET(++p);
445 if ( state == INQUOTE )
451 if( state == OUTQUOTE ) have_equals++;
454 if (is_type == NAME_TYPE_LDAP_RDN)
458 if (is_type == NAME_TYPE_DCE_DN)
463 if (is_type == NAME_TYPE_LDAP_DN)
468 if ( state == OUTQUOTE ) {
472 if ( parts == NULL ) {
473 if (( parts = (char **)LDAP_MALLOC( 8
474 * sizeof( char *))) == NULL )
476 } else if ( count >= 8 ) {
477 if (( parts = (char **)LDAP_REALLOC( parts,
478 (count+1) * sizeof( char *)))
483 parts[ count ] = NULL;
487 for ( q = rdn; q < p && *q != '='; ++q ) {
499 if ( p[-1] == '"' ) {
507 if (( parts[ count-1 ] = (char *)LDAP_CALLOC( 1,
510 AC_MEMCPY( parts[ count-1 ], rdn, len );
513 /* skip trailing spaces */
514 while( len > 0 && ldap_utf8_isspace(
515 &parts[count-1][len-1] ) )
521 parts[ count-1 ][ len ] = '\0';
525 * Don't forget to increment 'p' back to where
526 * it should be. If we don't, then we will
527 * never get past an "end quote."
532 rdn = *p ? &p[1] : p;
533 while ( ldap_utf8_isspace( rdn ) )
541 #endif /* !USE_LDAP_DN_PARSING */
544 * helper that changes the string representation of dnin
545 * from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK )
548 * LDAP_DN_FORMAT_LDAPV3 (rfc 2253 and ldapbis)
549 * LDAP_DN_FORMAT_LDAPV2 (rfc 1779)
550 * LDAP_DN_FORMAT_DCE (?)
552 * fout can be any of the above plus:
553 * LDAP_DN_FORMAT_UFN (rfc 1781, partial and with extensions)
554 * LDAP_DN_FORMAT_AD_CANONICAL (?)
557 dn2dn( const char *dnin, unsigned fin, unsigned fout )
560 LDAPDN *tmpDN = NULL;
566 if ( ldap_str2dn( dnin , &tmpDN, fin ) != LDAP_SUCCESS ) {
570 /* don't care about the result ... */
571 ldap_dn2str( tmpDN, &dnout, fout );
573 ldapava_free_dn( tmpDN );
581 #define B4ATTRTYPE 0x0001
582 #define B4OIDATTRTYPE 0x0002
583 #define B4STRINGATTRTYPE 0x0003
585 #define B4AVAEQUALS 0x0100
586 #define B4AVASEP 0x0200
587 #define B4RDNSEP 0x0300
588 #define GOTAVA 0x0400
590 #define B4ATTRVALUE 0x0010
591 #define B4STRINGVALUE 0x0020
592 #define B4IA5VALUEQUOTED 0x0030
593 #define B4IA5VALUE 0x0040
594 #define B4BINARYVALUE 0x0050
596 /* Helpers (mostly from slapd.h; maybe it should be rewritten from this) */
597 #define LDAP_DN_ASCII_SPACE(c) \
598 ( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' )
599 #define LDAP_DN_ASCII_LOWER(c) ( (c) >= 'a' && (c) <= 'z' )
600 #define LDAP_DN_ASCII_UPPER(c) ( (c) >= 'A' && (c) <= 'Z' )
601 #define LDAP_DN_ASCII_ALPHA(c) \
602 ( LDAP_DN_ASCII_LOWER(c) || LDAP_DN_ASCII_UPPER(c) )
603 #define LDAP_DN_ASCII_DIGIT(c) ( (c) >= '0' && (c) <= '9' )
604 #define LDAP_DN_ASCII_LCASE_HEXALPHA(c) ( (c) >= 'a' && (c) <= 'f' )
605 #define LDAP_DN_ASCII_UCASE_HEXALPHA(c) ( (c) >= 'A' && (c) <= 'F' )
606 #define LDAP_DN_ASCII_HEXDIGIT(c) \
607 ( LDAP_DN_ASCII_DIGIT(c) \
608 || LDAP_DN_ASCII_LCASE_HEXALPHA(c) \
609 || LDAP_DN_ASCII_UCASE_HEXALPHA(c) )
610 #define LDAP_DN_ASCII_ALNUM(c) \
611 ( LDAP_DN_ASCII_ALPHA(c) || LDAP_DN_ASCII_DIGIT(c) )
612 #define LDAP_DN_ASCII_PRINTABLE(c) ( (c) >= ' ' && (c) <= '~' )
615 #define LDAP_DN_OID_LEADCHAR(c) ( LDAP_DN_ASCII_DIGIT(c) )
616 #define LDAP_DN_DESC_LEADCHAR(c) ( LDAP_DN_ASCII_ALPHA(c) )
617 #define LDAP_DN_DESC_CHAR(c) ( LDAP_DN_ASCII_ALNUM(c) || (c) == '-' )
618 #define LDAP_DN_LANG_SEP(c) ( (c) == ';' )
619 #define LDAP_DN_ATTRDESC_CHAR(c) \
620 ( LDAP_DN_DESC_CHAR(c) || LDAP_DN_LANG_SEP(c) )
622 /* special symbols */
623 #define LDAP_DN_AVA_EQUALS(c) ( (c) == '=' )
624 #define LDAP_DN_AVA_SEP(c) ( (c) == '+' )
625 #define LDAP_DN_RDN_SEP(c) ( (c) == ',' )
626 #define LDAP_DN_RDN_SEP_V2(c) ( LDAP_DN_RDN_SEP(c) || (c) == ';' )
627 #define LDAP_DN_OCTOTHORPE(c) ( (c) == '#' )
628 #define LDAP_DN_QUOTES(c) ( (c) == '\"' )
629 #define LDAP_DN_ESCAPE(c) ( (c) == '\\' )
630 #define LDAP_DN_VALUE_END(c) \
631 ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) )
632 #define LDAP_DN_NE(c) \
633 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
634 || LDAP_DN_QUOTES(c) || (c) == '<' || (c) == '>' )
635 #define LDAP_DN_NEEDESCAPE(c) \
636 ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) )
637 #define LDAP_DN_NEEDESCAPE_LEAD(c) \
638 ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) || LDAP_DN_NE(c) )
639 #define LDAP_DN_NEEDESCAPE_TRAIL(c) \
640 ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) )
643 #define LDAP_DN_VALUE_END_V2(c) \
644 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) )
646 #define LDAP_DN_V2_SPECIAL(c) \
647 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_EQUALS(c) \
648 || LDAP_DN_AVA_SEP(c) || (c) == '<' || (c) == '>' \
649 || LDAP_DN_OCTOTHORPE(c) )
650 #define LDAP_DN_V2_PAIR(c) \
651 ( LDAP_DN_V2_SPECIAL(c) || LDAP_DN_ESCAPE(c) || LDAP_DN_QUOTES(c) )
654 * DCE (mostly from Luke Howard and IBM implementation for AIX)
656 * From: "Application Development Guide - Directory Services" (FIXME: add link?)
657 * Here escapes and valid chars for GDS are considered; as soon as more
658 * specific info is found, the macros will be updated.
660 * Chars: 'a'-'z', 'A'-'Z', '0'-'9',
661 * '.', ':', ',', ''', '+', '-', '=', '(', ')', '?', '/', ' '.
663 * Metachars: '/', ',', '=', '\'.
665 * the '\' is used to escape other metachars.
671 * Attribute types must start with alphabetic chars and can contain
672 * alphabetic chars and digits (FIXME: no '-'?). OIDs are allowed.
674 #define LDAP_DN_RDN_SEP_DCE(c) ( (c) == '/' )
675 #define LDAP_DN_AVA_SEP_DCE(c) ( (c) == ',' )
676 #define LDAP_DN_ESCAPE_DCE(c) ( LDAP_DN_ESCAPE(c) )
677 #define LDAP_DN_VALUE_END_DCE(c) \
678 ( LDAP_DN_RDN_SEP_DCE(c) || LDAP_DN_AVA_SEP_DCE(c) )
679 #define LDAP_DN_NEEDESCAPE_DCE(c) \
680 ( LDAP_DN_VALUE_END_DCE(c) || LDAP_DN_AVA_EQUALS(c) )
683 #define LDAP_DN_RDN_SEP_AD(c) ( (c) == '/' )
684 #define LDAP_DN_ESCAPE_AD(c) ( LDAP_DN_ESCAPE(c) )
685 #define LDAP_DN_AVA_SEP_AD(c) ( (c) == ',' ) /* assume same as DCE */
686 #define LDAP_DN_VALUE_END_AD(c) \
687 ( LDAP_DN_RDN_SEP_AD(c) || LDAP_DN_AVA_SEP_AD(c) )
688 #define LDAP_DN_NEEDESCAPE_AD(c) \
689 ( LDAP_DN_VALUE_END_AD(c) || LDAP_DN_AVA_EQUALS(c) )
692 #define LDAP_DN_HEXPAIR(s) \
693 ( LDAP_DN_ASCII_HEXDIGIT((s)[0]) && LDAP_DN_ASCII_HEXDIGIT((s)[1]) )
694 #define LDAP_DC_ATTR "dc"
695 /* better look at the AttributeDescription? */
697 /* FIXME: no composite rdn or non-"dc" types, right? */
698 /* FIXME: we do not allow binary values in domain, right? */
699 #define LDAP_DN_IS_RDN_DC( rdn ) \
700 ( ( rdn ) && ( rdn )[ 0 ][ 0 ] && !( rdn )[ 1 ] \
701 && ( ( rdn )[ 0 ][ 0 ]->la_flags == LDAP_AVA_STRING ) \
702 && ! strcasecmp( ( rdn )[ 0 ][ 0 ]->la_attr, LDAP_DC_ATTR ) )
704 /* Composite rules */
705 #define LDAP_DN_ALLOW_ONE_SPACE(f) \
706 ( ( (f) & LDAP_DN_FORMAT_LDAPV2 ) \
707 || !( (f) & LDAP_DN_P_NOSPACEAFTERRDN ) )
708 #define LDAP_DN_ALLOW_SPACES(f) \
709 ( ( (f) & LDAP_DN_FORMAT_LDAPV2 ) \
710 || !( (f) & ( LDAP_DN_P_NOLEADTRAILSPACES | LDAP_DN_P_NOSPACEAFTERRDN ) ) )
711 #define LDAP_DN_LDAPV3(f) \
712 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV3 )
713 #define LDAP_DN_LDAPV2(f) \
714 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV2 )
715 #define LDAP_DN_DCE(f) \
716 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_DCE )
717 #define LDAP_DN_UFN(f) \
718 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_UFN )
719 #define LDAP_DN_ADC(f) \
720 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_AD_CANONICAL )
721 #define LDAP_DN_FORMAT(f) ( (f) & LDAP_DN_FORMAT_MASK )
724 * LDAPAVA helpers (will become part of the API for operations
725 * on structural representations of DNs).
728 ldapava_new( const char *attr, const struct berval *val, unsigned flags )
735 ava = LDAP_MALLOC( sizeof( LDAPAVA ) );
737 /* should we test it? */
742 ava->la_attr = ( char * )attr;
743 ava->la_value = ( struct berval * )val;
744 ava->la_flags = flags;
750 ldapava_free( LDAPAVA *ava )
754 LDAP_FREE( ava->la_attr );
755 ber_bvfree( ava->la_value );
761 ldapava_append_to_rdn( LDAPRDN *rdn, LDAPAVA *ava )
769 for ( i = 0U; rdn[ i ]; i++ ) {
773 newRDN = LDAP_REALLOC( rdn, ( i + 2 ) * sizeof( LDAPAVA ** ) );
774 newRDN[ i ] = LDAP_MALLOC( sizeof( LDAPAVA * ) );
775 newRDN[ i ][ 0 ] = ava;
776 newRDN[ i + 1 ] = NULL;
782 ldapava_insert_into_rdn( LDAPRDN *rdn, LDAPAVA *ava, unsigned where )
790 for ( i = 0U; rdn[ i ]; i++ ) {
796 /* assume "at end", which corresponds to
797 * ldapava_append_to_rdn */
800 newRDN = LDAP_REALLOC( rdn, ( i + 2 ) * sizeof( LDAPAVA ** ) );
802 /* data after insert point */
803 AC_MEMCPY( &newRDN[ where + 1 ], &newRDN[ where ],
804 ( i - where ) * sizeof( LDAPRDN * ) );
806 newRDN[ where ] = LDAP_MALLOC( sizeof( LDAPAVA * ) );
807 newRDN[ where ][ 0 ] = ava;
808 newRDN[ i + 1 ] = NULL;
814 ldapava_free_rdn( LDAPRDN *rdn )
822 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
823 assert( rdn[ iAVA ][ 0 ] );
825 ldapava_free( rdn[ iAVA ][ 0 ] );
832 ldapava_append_to_dn( LDAPDN *dn, LDAPRDN *rdn )
840 for ( i = 0U; dn[ i ]; i++ ) {
844 newDN = LDAP_REALLOC( dn, ( i + 2 ) * sizeof( LDAPRDN ** ) );
845 newDN[ i ] = LDAP_MALLOC( sizeof( LDAPRDN * ) );
846 newDN[ i ][ 0 ] = rdn;
847 newDN[ i + 1 ] = NULL;
853 ldapava_insert_into_dn( LDAPDN *dn, LDAPRDN *rdn, unsigned where )
861 for ( i = 0U; dn[ i ]; i++ ) {
867 /* assume "at end", which corresponds to
868 * ldapava_append_to_dn */
871 newDN = LDAP_REALLOC( dn, ( i + 2 ) * sizeof( LDAPRDN ** ) );
873 /* data after insert point */
874 AC_MEMCPY( &newDN[ where + 1 ], &newDN[ where ],
875 ( i - where ) * sizeof( LDAPDN * ) );
877 newDN[ where ] = LDAP_MALLOC( sizeof( LDAPRDN * ) );
878 newDN[ where ][ 0 ] = rdn;
879 newDN[ i + 1 ] = NULL;
885 ldapava_free_dn( LDAPDN *dn )
893 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
894 assert( dn[ iRDN ][ 0 ] );
896 ldapava_free_rdn( dn[ iRDN ][ 0 ] );
903 * Converts a string representation of a DN (in LDAPv3, LDAPv2 or DCE)
904 * into a structured representation of the DN, by separating attribute
905 * types and values encoded in the more appropriate form, which is
906 * string or OID for attribute types and binary form of the BER encoded
907 * value or Unicode string. Formats different from LDAPv3 are parsed
908 * according to their own rules and turned into the more appropriate
909 * form according to LDAPv3.
911 * NOTE: I realize the code is getting spaghettish; it is rather
912 * experimental and will hopefully turn into something more simple
913 * and readable as soon as it works as expected.
916 * TODO: move parsing code to function
919 ldap_str2rdn( const char *str, LDAPRDN **rdn, const char **n, unsigned flags );
921 * and make ldap_str2dn call it repeatedly
924 ldap_str2dn( const char *str, LDAPDN **dn, unsigned flags )
928 int rc = LDAP_INVALID_DN_SYNTAX;
929 int attrTypeEncoding, attrValueEncoding;
931 char *attrType = NULL;
932 struct berval *attrValue = NULL;
934 LDAPDN *newDN = NULL;
935 LDAPRDN *newRDN = NULL;
940 Debug( LDAP_DEBUG_TRACE, "=> ldap_str2dn(%s,%u)\n%s", str, flags, "" );
944 switch ( LDAP_DN_FORMAT( flags ) ) {
945 case LDAP_DN_FORMAT_LDAPV3:
946 case LDAP_DN_FORMAT_LDAPV2:
947 case LDAP_DN_FORMAT_DCE:
950 /* unsupported in str2dn */
951 case LDAP_DN_FORMAT_UFN:
952 case LDAP_DN_FORMAT_AD_CANONICAL:
953 return( LDAP_INVALID_DN_SYNTAX );
956 return( LDAP_OTHER );
959 if ( str[ 0 ] == '\0' ) {
960 return( LDAP_SUCCESS );
964 if ( LDAP_DN_DCE( flags ) ) {
967 * (from Luke Howard: thnx) A RDN separator is required
968 * at the beginning of an (absolute) DN.
970 if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
976 for ( ; p[ 0 ] || state == GOTAVA; ) {
979 * The parser in principle advances one token a time,
980 * or toggles state if preferable.
985 * an AttributeType can be encoded as:
986 * - its string representation; in detail, implementations
987 * MUST recognize AttributeType string type names listed
988 * in section 2.3 of draft-ietf-ldapbis-dn-XX.txt, and
989 * MAY recognize other names.
990 * - its numeric OID (a dotted decimal string); in detail
991 * RFC 2253 asserts that ``Implementations MUST allow
992 * an oid in the attribute type to be prefixed by one
993 * of the character strings "oid." or "OID."''. As soon
994 * as draft-ietf-ldapbis-dn-XX.txt obsoletes RFC 2253
995 * I'm not sure whether this is required or not any
996 * longer; to be liberal, we still implement it.
999 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1000 if ( !LDAP_DN_ALLOW_ONE_SPACE( flags ) ) {
1007 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1008 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1013 /* whitespace is allowed (and trimmed) */
1015 while ( p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1020 /* error: we expected an AVA */
1030 if ( LDAP_DN_OID_LEADCHAR( p[ 0 ] ) ) {
1031 state = B4OIDATTRTYPE;
1035 /* else must be alpha */
1036 if ( !LDAP_DN_DESC_LEADCHAR( p[ 0 ] ) ) {
1040 /* LDAPv2 "oid." prefix */
1041 if ( LDAP_DN_LDAPV2( flags ) ) {
1043 * to be overly pedantic, we only accept
1046 if ( flags & LDAP_DN_PEDANTIC ) {
1047 if ( !strncmp( p, "oid.", 4 )
1048 || !strncmp( p, "OID.", 4 ) ) {
1050 state = B4OIDATTRTYPE;
1054 if ( !strncasecmp( p, "oid.", 4 ) ) {
1056 state = B4OIDATTRTYPE;
1062 state = B4STRINGATTRTYPE;
1065 case B4OIDATTRTYPE: {
1066 int err = LDAP_SUCCESS;
1068 attrType = parse_numericoid( &p, &err, 0 );
1069 if ( attrType == NULL ) {
1072 attrTypeEncoding = LDAP_AVA_BINARY;
1074 state = B4AVAEQUALS;
1078 case B4STRINGATTRTYPE: {
1079 const char *startPos, *endPos = NULL;
1083 * the starting char has been found to be
1084 * a LDAP_DN_DESC_LEADCHAR so we don't re-check it
1085 * FIXME: DCE attr types seem to have a more
1086 * restrictive syntax
1088 for ( startPos = p++; p[ 0 ]; p++ ) {
1089 if ( LDAP_DN_DESC_CHAR( p[ 0 ] ) ) {
1093 if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) {
1096 * RFC 2253 does not explicitly
1097 * allow lang extensions to attribute
1100 if ( flags & LDAP_DN_PEDANTIC ) {
1105 * we trim ';' and following lang
1106 * and so from attribute types
1109 for ( ; LDAP_DN_ATTRDESC_CHAR( p[ 0 ] )
1110 || LDAP_DN_LANG_SEP( p[ 0 ] ); p++ ) {
1118 len = ( endPos ? endPos : p ) - startPos;
1123 assert( attrType == NULL );
1124 attrType = LDAP_STRNDUP( startPos, len );
1125 attrTypeEncoding = LDAP_AVA_STRING;
1128 * here we need to decide whether to use it as is
1129 * or turn it in OID form; as a consequence, we
1130 * need to decide whether to binary encode the value
1133 state = B4AVAEQUALS;
1138 /* spaces may not be allowed */
1139 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1140 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1145 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1150 /* need equal sign */
1151 if ( !LDAP_DN_AVA_EQUALS( p[ 0 ] ) ) {
1156 /* spaces may not be allowed */
1157 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1158 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1163 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1169 * octothorpe means a BER encoded value will follow
1170 * FIXME: I don't think DCE will allow it
1172 if ( LDAP_DN_OCTOTHORPE( p[ 0 ] ) ) {
1174 attrValueEncoding = LDAP_AVA_BINARY;
1175 state = B4BINARYVALUE;
1179 /* STRING value expected */
1182 * if we're pedantic, an attribute type in OID form
1183 * SHOULD imply a BER encoded attribute value; we
1184 * should at least issue a warning
1186 if ( ( flags & LDAP_DN_PEDANTIC )
1187 && ( attrTypeEncoding == LDAP_AVA_BINARY ) ) {
1188 /* OID attrType SHOULD use binary encoding */
1192 attrValueEncoding = LDAP_AVA_STRING;
1195 * LDAPv2 allows the attribute value to be quoted;
1196 * also, IA5 values are expected, in principle
1198 if ( LDAP_DN_LDAPV2( flags ) ) {
1199 if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
1201 state = B4IA5VALUEQUOTED;
1210 * here STRING means RFC 2253 string
1211 * FIXME: what about DCE strings?
1213 state = B4STRINGVALUE;
1217 if ( hexstr2binval( p, &attrValue, &p, flags ) ) {
1225 switch ( LDAP_DN_FORMAT( flags ) ) {
1226 case LDAP_DN_FORMAT_LDAPV3:
1227 if ( str2strval( p, &attrValue,
1229 &attrValueEncoding ) ) {
1234 case LDAP_DN_FORMAT_DCE:
1235 /* FIXME: does DCE use UTF-8? */
1236 if ( DCE2strval( p, &attrValue,
1250 if ( IA52strval( p, &attrValue, &p, flags ) ) {
1257 case B4IA5VALUEQUOTED:
1259 /* lead quote already stripped */
1260 if ( quotedIA52strval( p, &attrValue,
1274 * we accept empty values
1276 ava = ldapava_new( attrType, attrValue,
1277 attrValueEncoding );
1278 if ( ava == NULL ) {
1279 rc = LDAP_NO_MEMORY;
1283 rdn = ldapava_append_to_rdn( newRDN, ava );
1284 if ( rdn == NULL ) {
1285 rc = LDAP_NO_MEMORY;
1291 * if we got an AVA separator ('+', | ',' * for DCE )
1292 * we expect a new AVA for this RDN; otherwise
1293 * we add the RDN to the DN
1295 switch ( LDAP_DN_FORMAT( flags ) ) {
1296 case LDAP_DN_FORMAT_LDAPV3:
1297 case LDAP_DN_FORMAT_LDAPV2:
1298 if ( !LDAP_DN_AVA_SEP( p[ 0 ] ) ) {
1303 case LDAP_DN_FORMAT_DCE:
1304 if ( !LDAP_DN_AVA_SEP_DCE( p[ 0 ] ) ) {
1313 if ( LDAP_DN_DCE( flags ) ) {
1314 /* add in reversed order */
1315 dn = ldapava_insert_into_dn( newDN,
1318 dn = ldapava_append_to_dn( newDN,
1323 rc = LDAP_NO_MEMORY;
1328 if ( p[ 0 ] == '\0' ) {
1331 * the DN is over, phew
1337 /* expect AVA for a new RDN */
1341 /* they should have been used in an AVA */
1357 /* They are set to NULL after they're used in an AVA */
1359 LDAP_FREE( attrType );
1363 ber_bvfree( attrValue );
1367 ldapava_free_rdn( newRDN );
1371 ldapava_free_dn( newDN );
1377 Debug( LDAP_DEBUG_TRACE, "<= ldap_str2dn(%s,%u)=%d\n", str, flags, rc );
1384 * reads in a UTF-8 string value, unescaping stuff:
1385 * '\' + LDAP_DN_NEEDESCAPE(c) -> 'c'
1386 * '\' + HEXPAIR(p) -> unhex(p)
1389 str2strval( const char *str, struct berval **val, const char **next, unsigned flags, unsigned *retFlags )
1391 const char *p, *startPos, *endPos = NULL;
1392 ber_len_t len, escapes, unescapes;
1401 for ( startPos = p = str, escapes = 0, unescapes = 0; p[ 0 ]; p++ ) {
1402 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1404 if ( p[ 0 ] == '\0' ) {
1407 if ( ( p == startPos + 1 && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
1408 || ( LDAP_DN_VALUE_END( p[ 1 ] ) && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) )
1409 || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
1414 if ( LDAP_DN_HEXPAIR( p ) ) {
1417 hexstr2bin( p, &c );
1420 if ( !LDAP_DN_ASCII_PRINTABLE( c ) ) {
1423 * we assume the string is UTF-8
1425 *retFlags = LDAP_AVA_NONPRINTABLE;
1432 if ( LDAP_DN_PEDANTIC & flags ) {
1436 * FIXME: we allow escaping
1437 * of chars that don't need
1438 * to and do not belong to
1439 * HEXDIGITS (we also allow
1440 * single hexdigit; maybe we
1445 } else if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1448 } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
1450 * FIXME: maybe we can add
1451 * escapes if not pedantic?
1458 * we do allow unescaped spaces at the end
1459 * of the value only in non-pedantic mode
1461 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
1462 !LDAP_DN_ESCAPE( p[ -2 ] ) ) {
1463 if ( flags & LDAP_DN_PEDANTIC ) {
1467 /* strip trailing (unescaped) spaces */
1468 for ( endPos = p - 1;
1469 endPos > startPos + 1 &&
1470 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1471 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1478 * FIXME: test memory?
1480 len = ( endPos ? endPos : p ) - startPos - escapes - unescapes;
1481 *val = LDAP_MALLOC( sizeof( struct berval ) );
1482 ( *val )->bv_len = len;
1484 if ( escapes == 0 && unescapes == 0 ) {
1485 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1490 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1491 for ( s = 0, d = 0; d < len; ) {
1492 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
1494 if ( ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( startPos[ s ] ) )
1495 || ( s == len - 1 && LDAP_DN_NEEDESCAPE_TRAIL( startPos[ s ] ) )
1496 || LDAP_DN_NEEDESCAPE( startPos[ s ] ) ) {
1497 ( *val )->bv_val[ d++ ] =
1500 } else if ( LDAP_DN_HEXPAIR( &startPos[ s ] ) ) {
1503 hexstr2bin( &startPos[ s ], &c );
1504 ( *val )->bv_val[ d++ ] = c;
1509 * we allow escaping of chars
1510 * that do not need to
1512 ( *val )->bv_val[ d++ ] =
1517 ( *val )->bv_val[ d++ ] = startPos[ s++ ];
1521 ( *val )->bv_val[ d ] = '\0';
1522 assert( strlen( ( *val )->bv_val ) == len );
1532 DCE2strval( const char *str, struct berval **val, const char **next, unsigned flags )
1534 const char *p, *startPos, *endPos = NULL;
1535 ber_len_t len, escapes;
1544 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
1545 if ( LDAP_DN_ESCAPE_DCE( p[ 0 ] ) ) {
1547 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
1554 } else if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1559 * FIXME: can we accept anything else? I guess we need
1560 * to stop if a value is not legal
1565 * (unescaped) trailing spaces are trimmed must be silently ignored;
1568 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
1569 !LDAP_DN_ESCAPE( p[ -2 ] ) ) {
1570 if ( flags & LDAP_DN_PEDANTIC ) {
1574 /* strip trailing (unescaped) spaces */
1575 for ( endPos = p - 1;
1576 endPos > startPos + 1 &&
1577 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1578 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1585 len = ( endPos ? endPos : p ) - startPos - escapes;
1586 *val = LDAP_MALLOC( sizeof( struct berval ) );
1587 ( *val )->bv_len = len;
1588 if ( escapes == 0 ){
1589 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1594 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1595 for ( s = 0, d = 0; d < len; ) {
1597 * This point is reached only if escapes
1598 * are properly used, so all we need to
1601 if ( LDAP_DN_ESCAPE_DCE( startPos[ s ] ) ) {
1605 ( *val )->bv_val[ d++ ] = startPos[ s++ ];
1607 ( *val )->bv_val[ d ] = '\0';
1608 assert( strlen( ( *val )->bv_val ) == len );
1617 IA52strval( const char *str, struct berval **val, const char **next, unsigned flags )
1619 const char *p, *startPos, *endPos = NULL;
1620 ber_len_t len, escapes;
1633 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
1634 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1636 if ( p[ 0 ] == '\0' ) {
1640 if ( !LDAP_DN_NEEDESCAPE( p[ 0 ] )
1641 && ( LDAP_DN_PEDANTIC & flags ) ) {
1646 } else if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
1651 * FIXME: can we accept anything else? I guess we need
1652 * to stop if a value is not legal
1656 /* strip trailing (unescaped) spaces */
1658 endPos > startPos + 1 &&
1659 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1660 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1665 *val = LDAP_MALLOC( sizeof( struct berval ) );
1666 len = ( endPos ? endPos : p ) - startPos - escapes;
1667 ( *val )->bv_len = len;
1668 if ( escapes == 0 ) {
1669 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1674 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1675 for ( s = 0, d = 0; d < len; ) {
1676 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
1679 ( *val )->bv_val[ d++ ] = startPos[ s++ ];
1681 ( *val )->bv_val[ d ] = '\0';
1682 assert( strlen( ( *val )->bv_val ) == len );
1690 quotedIA52strval( const char *str, struct berval **val, const char **next, unsigned flags )
1692 const char *p, *startPos, *endPos = NULL;
1694 unsigned escapes = 0;
1703 /* initial quote already eaten */
1704 for ( startPos = p = str; p[ 0 ]; p++ ) {
1706 * According to RFC 1779, the quoted value can
1707 * contain escaped as well as unescaped special values;
1708 * as a consequence we tolerate escaped values
1709 * (e.g. '"\,"' -> '\,') and escape unescaped specials
1710 * (e.g. '","' -> '\,').
1712 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1713 if ( p[ 1 ] == '\0' ) {
1718 if ( !LDAP_DN_V2_PAIR( p[ 0 ] )
1719 && ( LDAP_DN_PEDANTIC & flags ) ) {
1721 * do we allow to escape normal chars?
1722 * LDAPv2 does not allow any mechanism
1723 * for escaping chars with '\' and hex
1730 } else if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
1732 /* eat closing quotes */
1738 * FIXME: can we accept anything else? I guess we need
1739 * to stop if a value is not legal
1743 if ( endPos == NULL ) {
1747 /* Strip trailing (unescaped) spaces */
1748 for ( ; p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1752 len = endPos - startPos - escapes;
1754 *val = LDAP_MALLOC( sizeof( struct berval ) );
1755 ( *val )->bv_len = len;
1756 if ( escapes == 0 ) {
1757 ( *val )->bv_val = LDAP_STRNDUP( startPos, len );
1762 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1763 ( *val )->bv_len = len;
1765 for ( s = d = 0; d < len; ) {
1766 if ( LDAP_DN_ESCAPE( str[ s ] ) ) {
1769 ( *val )->bv_val[ d++ ] = str[ s++ ];
1771 ( *val )->bv_val[ d ] = '\0';
1772 assert( strlen( ( *val )->bv_val ) == len );
1781 hexstr2bin( const char *str, char *c )
1791 if ( LDAP_DN_ASCII_DIGIT( c1 ) ) {
1797 if ( LDAP_DN_ASCII_LCASE_HEXALPHA( c1 ) ) {
1804 if ( LDAP_DN_ASCII_DIGIT( c2 ) ) {
1810 if ( LDAP_DN_ASCII_LCASE_HEXALPHA( c2 ) ) {
1811 *c += c2 - 'a' + 10;
1819 hexstr2binval( const char *str, struct berval **val, const char **next, unsigned flags )
1821 const char *p, *startPos, *endPos = NULL;
1832 for ( startPos = p = str; p[ 0 ]; p += 2 ) {
1833 switch ( LDAP_DN_FORMAT( flags ) ) {
1834 case LDAP_DN_FORMAT_LDAPV3:
1835 case LDAP_DN_FORMAT_LDAPV2:
1836 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1841 case LDAP_DN_FORMAT_DCE:
1842 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1848 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1849 if ( flags & LDAP_DN_PEDANTIC ) {
1854 for ( ; p[ 0 ]; p++ ) {
1855 switch ( LDAP_DN_FORMAT( flags ) ) {
1856 case LDAP_DN_FORMAT_LDAPV3:
1857 case LDAP_DN_FORMAT_LDAPV2:
1858 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1863 case LDAP_DN_FORMAT_DCE:
1864 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1873 if ( !LDAP_DN_HEXPAIR( p ) ) {
1880 len = ( ( endPos ? endPos : p ) - startPos ) / 2;
1882 assert( 2 * len == ( endPos ? endPos : p ) - startPos );
1884 *val = LDAP_MALLOC( sizeof( struct berval ) );
1885 if ( *val == NULL ) {
1886 return( LDAP_NO_MEMORY );
1889 ( *val )->bv_len = len;
1890 ( *val )->bv_val = LDAP_MALLOC( len + 1 );
1891 if ( ( *val )->bv_val == NULL ) {
1893 return( LDAP_NO_MEMORY );
1896 for ( s = 0, d = 0; d < len; s += 2, d++ ) {
1899 hexstr2bin( &startPos[ s ], &c );
1901 ( *val )->bv_val[ d ] = c;
1904 ( *val )->bv_val[ d ] = '\0';
1911 * convert a byte in a hexadecimal pair
1914 byte2hexpair( const char *val, char *pair )
1916 static const char hexdig[] = "0123456789abcdef";
1922 * we assume the string has enough room for the hex encoding
1926 pair[ 0 ] = hexdig[ 0x0f & ( val[ 0 ] >> 4 ) ];
1927 pair[ 1 ] = hexdig[ 0x0f & val[ 0 ] ];
1933 * convert a binary value in hexadecimal pairs
1936 binval2hexstr( struct berval *val, char *str )
1943 if ( val->bv_len == 0 ) {
1948 * we assume the string has enough room for the hex encoding
1952 for ( s = 0, d = 0; s < val->bv_len; s++, d += 2 ) {
1953 byte2hexpair( &val->bv_val[ s ], &str[ d ] );
1960 * Length of the string representation, accounting for escaped hex
1964 strval2strlen( struct berval *val, unsigned flags, ber_len_t *len )
1966 ber_len_t l, cl = 1;
1973 if ( val->bv_len == 0 ) {
1977 for ( l = 0, p = val->bv_val; p[ 0 ]; p += cl ) {
1978 cl = ldap_utf8_charlen( p );
1980 /* illegal utf-8 char! */
1983 } else if ( cl > 1 ) {
1986 for ( cnt = 1; cnt < cl; cnt++ ) {
1987 if ( ( p[ cnt ] & 0x80 ) == 0x00 ) {
1991 /* need to escape it */
1994 } else if ( ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
1995 || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) )
1996 || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
2010 * convert to string representation, escaping with hex the UTF-8 stuff;
2011 * assume the destination has enough room for escaping
2014 strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2016 ber_len_t s, d, end;
2022 if ( val->bv_len == 0 ) {
2028 * we assume the string has enough room for the hex encoding
2031 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
2032 ber_len_t cl = ldap_utf8_charlen( &val->bv_val[ s ] );
2037 byte2hexpair( &val->bv_val[ s ], &str[ d ] );
2043 if ( ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
2044 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
2045 || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) ) {
2048 str[ d++ ] = val->bv_val[ s++ ];
2058 * Length of the IA5 string representation (no UTF-8 allowed)
2061 strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len )
2070 if ( val->bv_len == 0 ) {
2074 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2076 * Turn value into a binary encoded BER
2081 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2082 if ( ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
2083 || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) )
2084 || LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
2099 * convert to string representation (np UTF-8)
2100 * assume the destination has enough room for escaping
2103 strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2105 ber_len_t s, d, end;
2111 if ( val->bv_len == 0 ) {
2116 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2118 * Turn value into a binary encoded BER
2125 * we assume the string has enough room for the hex encoding
2129 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
2130 if ( ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
2131 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
2132 || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] ) ) {
2135 str[ d++ ] = val->bv_val[ s++ ];
2145 * Length of the (supposedly) DCE string representation,
2146 * accounting for escaped hex of UTF-8 chars
2149 strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len )
2158 if ( val->bv_len == 0 ) {
2162 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2164 * FIXME: Turn the value into a binary encoded BER?
2169 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2170 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
2185 * convert to (supposedly) DCE string representation,
2186 * escaping with hex the UTF-8 stuff;
2187 * assume the destination has enough room for escaping
2190 strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2198 if ( val->bv_len == 0 ) {
2203 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2205 * FIXME: Turn the value into a binary encoded BER?
2213 * we assume the string has enough room for the hex encoding
2217 for ( s = 0, d = 0; s < val->bv_len; ) {
2218 if ( LDAP_DN_NEEDESCAPE_DCE( val->bv_val[ s ] ) ) {
2221 str[ d++ ] = val->bv_val[ s++ ];
2231 * Length of the (supposedly) AD canonical string representation,
2232 * accounting for escaped hex of UTF-8 chars
2235 strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len )
2244 if ( val->bv_len == 0 ) {
2248 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2250 * FIXME: Turn the value into a binary encoded BER?
2255 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2256 if ( LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
2271 * convert to (supposedly) AD string representation,
2272 * escaping with hex the UTF-8 stuff;
2273 * assume the destination has enough room for escaping
2276 strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2284 if ( val->bv_len == 0 ) {
2289 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2291 * FIXME: Turn the value into a binary encoded BER?
2299 * we assume the string has enough room for the hex encoding
2303 for ( s = 0, d = 0; s < val->bv_len; ) {
2304 if ( LDAP_DN_NEEDESCAPE_AD( val->bv_val[ s ] ) ) {
2307 str[ d++ ] = val->bv_val[ s++ ];
2317 * If the DN is terminated by single-AVA RDNs with attribute type of "dc",
2318 * the forst part of the AD representation of the DN is written in DNS
2319 * form, i.e. dot separated domain name components (as suggested
2320 * by Luke Howard, http://www.padl.com/~lukeh)
2323 dn2domain( LDAPDN *dn, char *str, int *iRDN )
2326 int domain = 0, first = 1;
2327 ber_len_t l = 1; /* we move the null also */
2329 /* we are guaranteed there's enough memory in str */
2335 assert( *iRDN > 0 );
2337 for ( i = *iRDN; i >= 0; i-- ) {
2341 assert( dn[ i ][ 0 ] );
2344 assert( rdn[ 0 ][ 0 ] );
2345 ava = rdn[ 0 ][ 0 ];
2347 if ( !LDAP_DN_IS_RDN_DC( rdn ) ) {
2355 AC_MEMCPY( str, ava->la_value->bv_val,
2356 ava->la_value->bv_len + 1);
2357 l += ava->la_value->bv_len;
2360 AC_MEMCPY( str + ava->la_value->bv_len + 1, str, l);
2361 AC_MEMCPY( str, ava->la_value->bv_val,
2362 ava->la_value->bv_len );
2363 str[ ava->la_value->bv_len ] = '.';
2364 l += ava->la_value->bv_len + 1;
2374 rdn2strlen( LDAPRDN *rdn, ber_len_t *len,
2375 int ( *s2l )( struct berval *v, unsigned f, ber_len_t *l ) )
2382 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2383 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2385 /* len(type) + '=' + '+' | ',' */
2386 l += strlen( ava->la_attr ) + 2;
2388 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2389 /* octothorpe + twice the length */
2390 l += 1 + 2 * ava->la_value->bv_len;
2395 if ( ( *s2l )( ava->la_value, ava->la_flags, &vl ) ) {
2408 rdn2str( LDAPRDN *rdn, char *str, ber_len_t *len,
2409 int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) )
2414 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2415 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2416 ber_len_t al = strlen( ava->la_attr );
2418 AC_MEMCPY( &str[ l ], ava->la_attr, al );
2423 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2425 if ( binval2hexstr( ava->la_value, &str[ l ] ) ) {
2428 l += 2 * ava->la_value->bv_len;
2433 if ( ( *s2s )( ava->la_value, &str[ l ],
2434 ava->la_flags, &vl ) ) {
2439 str[ l++ ] = ( rdn[ iAVA + 1 ] ? '+' : ',' );
2448 rdn2UFNstrlen( LDAPRDN *rdn, ber_len_t *len )
2458 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2459 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2462 l += ( rdn[ iAVA + 1 ] ? 3 : 2 );
2464 /* FIXME: are binary values allowed in UFN? */
2465 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2466 /* octothorpe + twice the value */
2467 l += 1 + 2 * ava->la_value->bv_len;
2472 if ( strval2strlen( ava->la_value, ava->la_flags,
2486 rdn2UFNstr( LDAPRDN *rdn, char *str, ber_len_t *len )
2491 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2492 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2494 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2496 if ( binval2hexstr( ava->la_value, &str[ l ] ) ) {
2499 l += 2 * ava->la_value->bv_len;
2504 if ( strval2str( ava->la_value, &str[ l ],
2505 ava->la_flags, &vl ) ) {
2511 if ( rdn[ iAVA + 1 ]) {
2512 AC_MEMCPY( &str[ l ], " + ", 3 );
2516 AC_MEMCPY( &str[ l ], ", ", 2 );
2527 ldap_rdn2str( LDAPRDN *rdn, char **str, unsigned flags )
2534 if ( rdn == NULL ) {
2535 *str = LDAP_STRDUP( "" );
2536 return( LDAP_SUCCESS );
2540 switch ( LDAP_DN_FORMAT( flags ) ) {
2541 case LDAP_DN_FORMAT_LDAPV3:
2542 if ( rdn2strlen( rdn, &l, strval2strlen ) ) {
2543 return( LDAP_OTHER );
2547 case LDAP_DN_FORMAT_LDAPV2:
2548 if ( rdn2strlen( rdn, &l, strval2IA5strlen ) ) {
2549 return( LDAP_OTHER );
2553 case LDAP_DN_FORMAT_UFN:
2554 if ( rdn2UFNstrlen( rdn, &l ) ) {
2555 return( LDAP_OTHER );
2560 return( LDAP_OTHER );
2563 *str = LDAP_MALLOC( l + 1 );
2565 switch ( LDAP_DN_FORMAT( flags ) ) {
2566 case LDAP_DN_FORMAT_LDAPV3:
2567 rc = rdn2str( rdn, *str, &l, strval2str );
2571 case LDAP_DN_FORMAT_LDAPV2:
2572 rc = rdn2str( rdn, *str, &l, strval2IA5str );
2576 case LDAP_DN_FORMAT_UFN:
2577 rc = rdn2UFNstr( rdn, *str, &l );
2583 ldap_memfree( *str );
2584 return( LDAP_OTHER );
2587 ( *str )[ l - back ] = '\0';
2589 return( LDAP_SUCCESS );
2593 * Very bulk implementation; many optimizations can be performed
2594 * - a NULL dn results in an empty string ""
2597 * a) what do we do if a UTF-8 string must be converted in LDAPv2?
2598 * we must encode it in binary form ('#' + HEXPAIRs)
2599 * b) does DCE/AD support UTF-8?
2600 * no clue; don't think so.
2601 * c) what do we do when binary values must be converted in UTF/DCE/AD?
2602 * use binary encoded BER
2604 int ldap_dn2str( LDAPDN *dn, char **str, unsigned flags )
2607 int rc = LDAP_OTHER;
2610 /* stringifying helpers for LDAPv3/LDAPv2 */
2611 int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l );
2612 int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l );
2616 Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2str(%u)\n%s%s", flags, "", "" );
2621 * a null dn means an empty dn string
2622 * FIXME: better raise an error?
2625 *str = LDAP_STRDUP( "" );
2626 return( LDAP_SUCCESS );
2629 switch ( LDAP_DN_FORMAT( flags ) ) {
2630 case LDAP_DN_FORMAT_LDAPV3:
2631 sv2l = strval2strlen;
2635 case LDAP_DN_FORMAT_LDAPV2:
2636 sv2l = strval2IA5strlen;
2637 sv2s = strval2IA5str;
2640 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
2642 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2644 if ( rdn2strlen( rdn, &rdnl, sv2l ) ) {
2645 goto return_results;
2651 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2652 rc = LDAP_NO_MEMORY;
2656 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
2658 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2660 if ( rdn2str( rdn, &( *str )[ l ], &rdnl, sv2s ) ) {
2663 goto return_results;
2671 * trim the last ',' (the allocated memory
2672 * is one byte longer than required)
2674 ( *str )[ len - 1 ] = '\0';
2679 case LDAP_DN_FORMAT_UFN: {
2682 * FIXME: quoting from RFC 1781:
2684 To take a distinguished name, and generate a name of this format with
2685 attribute types omitted, the following steps are followed.
2687 1. If the first attribute is of type CommonName, the type may be
2690 2. If the last attribute is of type Country, the type may be
2693 3. If the last attribute is of type Country, the last
2694 Organisation attribute may have the type omitted.
2696 4. All attributes of type OrganisationalUnit may have the type
2697 omitted, unless they are after an Organisation attribute or
2698 the first attribute is of type OrganisationalUnit.
2700 * this should be the pedantic implementation.
2702 * Here the standard implementation reflects
2703 * the one historically provided by OpenLDAP
2704 * (and UMIch, I presume), with the variant
2705 * of spaces and plusses (' + ') separating
2708 * A non-standard but nice implementation could
2709 * be to turn the final "dc" attributes into a
2710 * dot-separated domain.
2712 * Other improvements could involve the use of
2713 * friendly country names and so.
2716 int leftmost_dc = -1;
2718 #endif /* DC_IN_UFN */
2720 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
2722 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2724 if ( rdn2UFNstrlen( rdn, &rdnl ) ) {
2725 goto return_results;
2730 if ( LDAP_DN_IS_RDN_DC( rdn ) ) {
2731 if ( leftmost_dc == -1 ) {
2737 #endif /* DC_IN_UFN */
2740 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2741 rc = LDAP_NO_MEMORY;
2746 if ( leftmost_dc == -1 ) {
2747 #endif /* DC_IN_UFN */
2748 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
2750 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2752 if ( rdn2UFNstr( rdn, &( *str )[ l ], &vl ) ) {
2755 goto return_results;
2761 * trim the last ', ' (the allocated memory
2762 * is two bytes longer than required)
2764 ( *str )[ len - 2 ] = '\0';
2767 last_iRDN = iRDN - 1;
2769 for ( l = 0, iRDN = 0; iRDN < leftmost_dc; iRDN++ ) {
2771 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2773 if ( rdn2UFNstr( rdn, &( *str )[ l ], &vl ) ) {
2776 goto return_results;
2781 if ( !dn2domain( dn, &( *str )[ l ], &last_iRDN ) ) {
2784 goto return_results;
2787 /* the string is correctly terminated by dn2domain */
2789 #endif /* DC_IN_UFN */
2795 case LDAP_DN_FORMAT_DCE:
2796 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
2797 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2799 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2800 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2802 /* len(type) + '=' + ( ',' || '/' ) */
2803 len += strlen( ava->la_attr ) + 2;
2805 /* FIXME: are binary values allowed in DCE? */
2806 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2807 /* octothorpe + twice the value */
2808 len += 1 + 2 * ava->la_value->bv_len;
2813 if ( strval2DCEstrlen( ava->la_value,
2814 ava->la_flags, &vl ) ) {
2815 goto return_results;
2822 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2823 rc = LDAP_NO_MEMORY;
2827 for ( l = 0; iRDN--; ) {
2828 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2831 * DCE uses ',' for composite RDNs
2833 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2834 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2835 ber_len_t al = strlen( ava->la_attr );
2837 ( *str )[ l++ ] = ( iAVA ? ',' : '/' );
2838 AC_MEMCPY( &( *str )[ l ], ava->la_attr, al );
2840 ( *str )[ l++ ] = '=';
2841 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2842 ( *str )[ l++ ]= '#';
2843 if ( binval2hexstr( ava->la_value,
2844 &( *str )[ l ] ) ) {
2847 goto return_results;
2849 l += 2 * ava->la_value->bv_len;
2854 if ( strval2DCEstr( ava->la_value,
2856 ava->la_flags, &vl ) ) {
2859 goto return_results;
2866 ( *str )[ len ] = '\0';
2871 case LDAP_DN_FORMAT_AD_CANONICAL: {
2874 * Sort of UFN for DCE DNs: a slash ('/') separated
2875 * global->local DN with no types; strictly speaking,
2876 * the naming context should be a domain, which is
2877 * written in DNS-style, e.g. dot-deparated.
2881 * "cn=Bill+sn=Gates,ou=People,dc=microsoft,dc=com"
2885 * "microsoft.com/People/Bill,Gates"
2887 for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) {
2888 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2890 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2891 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2893 /* ',' || '/' || '.' */
2896 /* FIXME: are binary values allowed in AD? */
2897 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2898 /* octothorpe + twice the value */
2899 len += 1 + 2 * ava->la_value->bv_len;
2904 if ( strval2ADstrlen( ava->la_value,
2905 ava->la_flags, &vl ) ) {
2906 goto return_results;
2913 if ( ( *str = LDAP_MALLOC( len + 1 ) ) == NULL ) {
2914 rc = LDAP_NO_MEMORY;
2919 if ( iRDN && dn2domain( dn, *str, &iRDN ) ) {
2920 for ( l = strlen( *str ); iRDN >= 0 ; iRDN-- ) {
2921 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2923 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2924 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2926 ( *str)[ l++ ] = ( iAVA ? ',' : '/' );
2927 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2928 ( *str )[ l++ ] = '#';
2929 if ( binval2hexstr( ava->la_value,
2930 &( *str )[ l ] ) ) {
2933 goto return_results;
2935 l += 2 * ava->la_value->bv_len;
2940 if ( strval2ADstr( ava->la_value,
2946 goto return_results;
2957 * Strictly speaking, AD canonical requires
2958 * a DN to be in the form "..., dc=smtg",
2959 * i.e. terminated by a domain component
2961 if ( flags & LDAP_DN_PEDANTIC ) {
2964 rc = LDAP_INVALID_DN_SYNTAX;
2968 for ( l = 0; iRDN >= 0 ; iRDN-- ) {
2969 LDAPRDN *rdn = dn[ iRDN ][ 0 ];
2971 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2972 LDAPAVA *ava = rdn[ iAVA ][ 0 ];
2979 ( iAVA ? ',' : '/' );
2981 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2982 ( *str )[ l++ ] = '#';
2983 if ( binval2hexstr( ava->la_value,
2984 &( *str )[ l ] ) ) {
2987 goto return_results;
2989 l += 2 * ava->la_value->bv_len;
2994 if ( strval2ADstr( ava->la_value,
3000 goto return_results;
3008 ( *str )[ len ] = '\0';
3019 Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2str(%s,%u)=%d\n", *str, flags, rc );