2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2004 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
15 /* Portions Copyright (c) 1994 Regents of the University of Michigan.
16 * All rights reserved.
23 #include <ac/stdlib.h>
24 #include <ac/socket.h>
25 #include <ac/string.h>
29 #include "ldap_schema.h"
31 /* extension to UFN that turns trailing "dc=value" rdns in DNS style,
32 * e.g. "ou=People,dc=openldap,dc=org" => "People, openldap.org" */
36 /* parsing/printing routines */
37 static int str2strval( const char *str, ber_len_t stoplen, struct berval *val,
38 const char **next, unsigned flags, int *retFlags, void *ctx );
39 static int DCE2strval( const char *str, struct berval *val,
40 const char **next, unsigned flags, void *ctx );
41 static int IA52strval( const char *str, struct berval *val,
42 const char **next, unsigned flags, void *ctx );
43 static int quotedIA52strval( const char *str, struct berval *val,
44 const char **next, unsigned flags, void *ctx );
45 static int hexstr2binval( const char *str, struct berval *val,
46 const char **next, unsigned flags, void *ctx );
47 static int hexstr2bin( const char *str, char *c );
48 static int byte2hexpair( const char *val, char *pair );
49 static int binval2hexstr( struct berval *val, char *str );
50 static int strval2strlen( struct berval *val, unsigned flags,
52 static int strval2str( struct berval *val, char *str, unsigned flags,
54 static int strval2IA5strlen( struct berval *val, unsigned flags,
56 static int strval2IA5str( struct berval *val, char *str, unsigned flags,
58 static int strval2DCEstrlen( struct berval *val, unsigned flags,
60 static int strval2DCEstr( struct berval *val, char *str, unsigned flags,
62 static int strval2ADstrlen( struct berval *val, unsigned flags,
64 static int strval2ADstr( struct berval *val, char *str, unsigned flags,
66 static int dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN );
69 static LDAPAVA * ldapava_new(
70 const struct berval *attr, const struct berval *val, unsigned flags, void *ctx );
72 /* Higher level helpers */
73 static int rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len,
74 int ( *s2l )( struct berval *, unsigned, ber_len_t * ) );
75 static int rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len,
76 int ( *s2s )( struct berval *, char *, unsigned, ber_len_t * ));
77 static int rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len );
78 static int rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len );
79 static int rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len );
80 static int rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flag, ber_len_t *len, int first );
81 static int rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len );
82 static int rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first );
85 * RFC 1823 ldap_get_dn
88 ldap_get_dn( LDAP *ld, LDAPMessage *entry )
94 LDAP_LOG ( OPERATION, ENTRY, "ldap_get_dn\n", 0, 0, 0 );
96 Debug( LDAP_DEBUG_TRACE, "ldap_get_dn\n", 0, 0, 0 );
100 assert( LDAP_VALID(ld) );
101 assert( entry != NULL );
103 tmp = *entry->lm_ber; /* struct copy */
104 if ( ber_scanf( &tmp, "{a" /*}*/, &dn ) == LBER_ERROR ) {
105 ld->ld_errno = LDAP_DECODING_ERROR;
113 ldap_get_dn_ber( LDAP *ld, LDAPMessage *entry, BerElement **berout,
116 BerElement tmp, *ber;
118 int rc = LDAP_SUCCESS;
121 LDAP_LOG ( OPERATION, ENTRY, "ldap_get_dn_ber\n", 0, 0, 0 );
123 Debug( LDAP_DEBUG_TRACE, "ldap_get_dn_ber\n", 0, 0, 0 );
126 assert( ld != NULL );
127 assert( LDAP_VALID(ld) );
128 assert( entry != NULL );
129 assert( dn != NULL );
136 ber = ldap_alloc_ber_with_options( ld );
138 return LDAP_NO_MEMORY;
145 *ber = *entry->lm_ber; /* struct copy */
146 if ( ber_scanf( ber, "{ml{" /*}*/, dn, &len ) == LBER_ERROR ) {
147 rc = ld->ld_errno = LDAP_DECODING_ERROR;
149 if ( rc == LDAP_SUCCESS ) {
150 /* set the length to avoid overrun */
151 rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len );
152 if( rc != LBER_OPT_SUCCESS ) {
153 rc = ld->ld_errno = LDAP_LOCAL_ERROR;
156 if ( rc != LDAP_SUCCESS && berout ) {
164 * RFC 1823 ldap_dn2ufn
167 ldap_dn2ufn( LDAP_CONST char *dn )
172 LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2ufn\n", 0, 0, 0 );
174 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ufn\n", 0, 0, 0 );
177 ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
178 &out, LDAP_DN_FORMAT_UFN );
184 * RFC 1823 ldap_explode_dn
187 ldap_explode_dn( LDAP_CONST char *dn, int notypes )
190 char **values = NULL;
192 unsigned flag = notypes ? LDAP_DN_FORMAT_UFN : LDAP_DN_FORMAT_LDAPV3;
195 LDAP_LOG ( OPERATION, ENTRY, "ldap_explode_dn\n", 0, 0, 0 );
197 Debug( LDAP_DEBUG_TRACE, "ldap_explode_dn\n", 0, 0, 0 );
200 if ( ldap_str2dn( dn, &tmpDN, LDAP_DN_FORMAT_LDAP )
205 if( tmpDN == NULL ) {
206 values = LDAP_MALLOC( sizeof( char * ) );
207 if( values == NULL ) return NULL;
213 for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ );
215 values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iRDN ) );
216 if ( values == NULL ) {
217 ldap_dnfree( tmpDN );
221 for ( iRDN = 0; tmpDN[ iRDN ]; iRDN++ ) {
222 ldap_rdn2str( tmpDN[ iRDN ], &values[ iRDN ], flag );
224 ldap_dnfree( tmpDN );
225 values[ iRDN ] = NULL;
231 ldap_explode_rdn( LDAP_CONST char *rdn, int notypes )
234 char **values = NULL;
239 LDAP_LOG ( OPERATION, ENTRY, "ldap_explode_rdn\n", 0, 0, 0 );
241 Debug( LDAP_DEBUG_TRACE, "ldap_explode_rdn\n", 0, 0, 0 );
245 * we only parse the first rdn
246 * FIXME: we prefer efficiency over checking if the _ENTIRE_
249 if ( ldap_str2rdn( rdn, &tmpRDN, (char **) &p, LDAP_DN_FORMAT_LDAP )
254 for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) ;
255 values = LDAP_MALLOC( sizeof( char * ) * ( 1 + iAVA ) );
256 if ( values == NULL ) {
257 ldap_rdnfree( tmpRDN );
261 for ( iAVA = 0; tmpRDN[ iAVA ]; iAVA++ ) {
262 ber_len_t l = 0, vl, al = 0;
264 LDAPAVA *ava = tmpRDN[ iAVA ];
266 if ( ava->la_flags & LDAP_AVA_BINARY ) {
267 vl = 1 + 2 * ava->la_value.bv_len;
270 if ( strval2strlen( &ava->la_value,
271 ava->la_flags, &vl ) ) {
277 al = ava->la_attr.bv_len;
278 l = vl + ava->la_attr.bv_len + 1;
280 str = LDAP_MALLOC( l + 1 );
281 AC_MEMCPY( str, ava->la_attr.bv_val,
282 ava->la_attr.bv_len );
287 str = LDAP_MALLOC( l + 1 );
290 if ( ava->la_flags & LDAP_AVA_BINARY ) {
292 if ( binval2hexstr( &ava->la_value, &str[ al ] ) ) {
297 if ( strval2str( &ava->la_value, &str[ al ],
298 ava->la_flags, &vl ) ) {
304 values[ iAVA ] = str;
306 values[ iAVA ] = NULL;
308 ldap_rdnfree( tmpRDN );
313 LBER_VFREE( values );
314 ldap_rdnfree( tmpRDN );
319 ldap_dn2dcedn( LDAP_CONST char *dn )
324 LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2dcedn\n", 0, 0, 0 );
326 Debug( LDAP_DEBUG_TRACE, "ldap_dn2dcedn\n", 0, 0, 0 );
329 ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
330 &out, LDAP_DN_FORMAT_DCE );
336 ldap_dcedn2dn( LDAP_CONST char *dce )
341 LDAP_LOG ( OPERATION, ENTRY, "ldap_dcedn2dn\n", 0, 0, 0 );
343 Debug( LDAP_DEBUG_TRACE, "ldap_dcedn2dn\n", 0, 0, 0 );
346 ( void )ldap_dn_normalize( dce, LDAP_DN_FORMAT_DCE, &out, LDAP_DN_FORMAT_LDAPV3 );
352 ldap_dn2ad_canonical( LDAP_CONST char *dn )
357 LDAP_LOG ( OPERATION, ENTRY, "ldap_dn2ad_canonical\n", 0, 0, 0 );
359 Debug( LDAP_DEBUG_TRACE, "ldap_dn2ad_canonical\n", 0, 0, 0 );
362 ( void )ldap_dn_normalize( dn, LDAP_DN_FORMAT_LDAP,
363 &out, LDAP_DN_FORMAT_AD_CANONICAL );
369 * function that changes the string representation of dnin
370 * from ( fin & LDAP_DN_FORMAT_MASK ) to ( fout & LDAP_DN_FORMAT_MASK )
373 * LDAP_DN_FORMAT_LDAP (rfc 2253 and ldapbis liberal,
374 * plus some rfc 1779)
375 * LDAP_DN_FORMAT_LDAPV3 (rfc 2253 and ldapbis)
376 * LDAP_DN_FORMAT_LDAPV2 (rfc 1779)
377 * LDAP_DN_FORMAT_DCE (?)
379 * fout can be any of the above except
380 * LDAP_DN_FORMAT_LDAP
382 * LDAP_DN_FORMAT_UFN (rfc 1781, partial and with extensions)
383 * LDAP_DN_FORMAT_AD_CANONICAL (?)
386 ldap_dn_normalize( LDAP_CONST char *dnin,
387 unsigned fin, char **dnout, unsigned fout )
393 LDAP_LOG ( OPERATION, ENTRY, "ldap_dn_normalize\n", 0, 0, 0 );
395 Debug( LDAP_DEBUG_TRACE, "ldap_dn_normalize\n", 0, 0, 0 );
402 if ( dnin == NULL ) {
403 return( LDAP_SUCCESS );
406 rc = ldap_str2dn( dnin , &tmpDN, fin );
407 if ( rc != LDAP_SUCCESS ) {
411 rc = ldap_dn2str( tmpDN, dnout, fout );
413 ldap_dnfree( tmpDN );
421 /* #define B4ATTRTYPE 0x0001 */
422 #define B4OIDATTRTYPE 0x0002
423 #define B4STRINGATTRTYPE 0x0003
425 #define B4AVAEQUALS 0x0100
426 #define B4AVASEP 0x0200
427 #define B4RDNSEP 0x0300
428 #define GOTAVA 0x0400
430 #define B4ATTRVALUE 0x0010
431 #define B4STRINGVALUE 0x0020
432 #define B4IA5VALUEQUOTED 0x0030
433 #define B4IA5VALUE 0x0040
434 #define B4BINARYVALUE 0x0050
437 * Helpers (mostly from slap.h)
438 * c is assumed to Unicode in an ASCII compatible format (UTF-8)
439 * Macros assume "C" Locale (ASCII)
441 #define LDAP_DN_ASCII_SPACE(c) \
442 ( (c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' )
443 #define LDAP_DN_ASCII_LOWER(c) LDAP_LOWER(c)
444 #define LDAP_DN_ASCII_UPPER(c) LDAP_UPPER(c)
445 #define LDAP_DN_ASCII_ALPHA(c) LDAP_ALPHA(c)
447 #define LDAP_DN_ASCII_DIGIT(c) LDAP_DIGIT(c)
448 #define LDAP_DN_ASCII_LCASE_HEXALPHA(c) LDAP_HEXLOWER(c)
449 #define LDAP_DN_ASCII_UCASE_HEXALPHA(c) LDAP_HEXUPPER(c)
450 #define LDAP_DN_ASCII_HEXDIGIT(c) LDAP_HEX(c)
451 #define LDAP_DN_ASCII_ALNUM(c) LDAP_ALNUM(c)
452 #define LDAP_DN_ASCII_PRINTABLE(c) ( (c) >= ' ' && (c) <= '~' )
455 #define LDAP_DN_OID_LEADCHAR(c) LDAP_DIGIT(c)
456 #define LDAP_DN_DESC_LEADCHAR(c) LDAP_ALPHA(c)
457 #define LDAP_DN_DESC_CHAR(c) LDAP_LDH(c)
458 #define LDAP_DN_LANG_SEP(c) ( (c) == ';' )
459 #define LDAP_DN_ATTRDESC_CHAR(c) \
460 ( LDAP_DN_DESC_CHAR(c) || LDAP_DN_LANG_SEP(c) )
462 /* special symbols */
463 #define LDAP_DN_AVA_EQUALS(c) ( (c) == '=' )
464 #define LDAP_DN_AVA_SEP(c) ( (c) == '+' )
465 #define LDAP_DN_RDN_SEP(c) ( (c) == ',' )
466 #define LDAP_DN_RDN_SEP_V2(c) ( LDAP_DN_RDN_SEP(c) || (c) == ';' )
467 #define LDAP_DN_OCTOTHORPE(c) ( (c) == '#' )
468 #define LDAP_DN_QUOTES(c) ( (c) == '\"' )
469 #define LDAP_DN_ESCAPE(c) ( (c) == '\\' )
470 #define LDAP_DN_VALUE_END(c) \
471 ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) )
472 #define LDAP_DN_NE(c) \
473 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) \
474 || LDAP_DN_QUOTES(c) || (c) == '<' || (c) == '>' )
475 #define LDAP_DN_MAYESCAPE(c) \
476 ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) \
477 || LDAP_DN_ASCII_SPACE(c) || LDAP_DN_OCTOTHORPE(c) )
478 #define LDAP_DN_NEEDESCAPE(c) \
479 ( LDAP_DN_ESCAPE(c) || LDAP_DN_NE(c) )
480 #define LDAP_DN_NEEDESCAPE_LEAD(c) LDAP_DN_MAYESCAPE(c)
481 #define LDAP_DN_NEEDESCAPE_TRAIL(c) \
482 ( LDAP_DN_ASCII_SPACE(c) || LDAP_DN_NEEDESCAPE(c) )
483 #define LDAP_DN_WILLESCAPE_CHAR(c) \
484 ( LDAP_DN_RDN_SEP(c) || LDAP_DN_AVA_SEP(c) || LDAP_DN_ESCAPE(c) )
485 #define LDAP_DN_IS_PRETTY(f) ( (f) & LDAP_DN_PRETTY )
486 #define LDAP_DN_WILLESCAPE_HEX(f, c) \
487 ( ( !LDAP_DN_IS_PRETTY( f ) ) && LDAP_DN_WILLESCAPE_CHAR(c) )
490 #define LDAP_DN_VALUE_END_V2(c) \
491 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_SEP(c) )
493 #define LDAP_DN_V2_SPECIAL(c) \
494 ( LDAP_DN_RDN_SEP_V2(c) || LDAP_DN_AVA_EQUALS(c) \
495 || LDAP_DN_AVA_SEP(c) || (c) == '<' || (c) == '>' \
496 || LDAP_DN_OCTOTHORPE(c) )
497 #define LDAP_DN_V2_PAIR(c) \
498 ( LDAP_DN_V2_SPECIAL(c) || LDAP_DN_ESCAPE(c) || LDAP_DN_QUOTES(c) )
501 * DCE (mostly from Luke Howard and IBM implementation for AIX)
503 * From: "Application Development Guide - Directory Services" (FIXME: add link?)
504 * Here escapes and valid chars for GDS are considered; as soon as more
505 * specific info is found, the macros will be updated.
507 * Chars: 'a'-'z', 'A'-'Z', '0'-'9',
508 * '.', ':', ',', ''', '+', '-', '=', '(', ')', '?', '/', ' '.
510 * Metachars: '/', ',', '=', '\'.
512 * the '\' is used to escape other metachars.
518 * Attribute types must start with alphabetic chars and can contain
519 * alphabetic chars and digits (FIXME: no '-'?). OIDs are allowed.
521 #define LDAP_DN_RDN_SEP_DCE(c) ( (c) == '/' )
522 #define LDAP_DN_AVA_SEP_DCE(c) ( (c) == ',' )
523 #define LDAP_DN_ESCAPE_DCE(c) ( LDAP_DN_ESCAPE(c) )
524 #define LDAP_DN_VALUE_END_DCE(c) \
525 ( LDAP_DN_RDN_SEP_DCE(c) || LDAP_DN_AVA_SEP_DCE(c) )
526 #define LDAP_DN_NEEDESCAPE_DCE(c) \
527 ( LDAP_DN_VALUE_END_DCE(c) || LDAP_DN_AVA_EQUALS(c) )
530 #define LDAP_DN_RDN_SEP_AD(c) ( (c) == '/' )
531 #define LDAP_DN_ESCAPE_AD(c) ( LDAP_DN_ESCAPE(c) )
532 #define LDAP_DN_AVA_SEP_AD(c) ( (c) == ',' ) /* assume same as DCE */
533 #define LDAP_DN_VALUE_END_AD(c) \
534 ( LDAP_DN_RDN_SEP_AD(c) || LDAP_DN_AVA_SEP_AD(c) )
535 #define LDAP_DN_NEEDESCAPE_AD(c) \
536 ( LDAP_DN_VALUE_END_AD(c) || LDAP_DN_AVA_EQUALS(c) )
539 #define LDAP_DN_HEXPAIR(s) \
540 ( LDAP_DN_ASCII_HEXDIGIT((s)[0]) && LDAP_DN_ASCII_HEXDIGIT((s)[1]) )
541 /* better look at the AttributeDescription? */
543 /* FIXME: no composite rdn or non-"dc" types, right?
544 * (what about "dc" in OID form?) */
545 /* FIXME: we do not allow binary values in domain, right? */
546 /* NOTE: use this macro only when ABSOLUTELY SURE rdn IS VALID! */
547 /* NOTE: don't use strcasecmp() as it is locale specific! */
548 #define LDAP_DC_ATTR "dc"
549 #define LDAP_DC_ATTRU "DC"
550 #define LDAP_DN_IS_RDN_DC( r ) \
551 ( (r) && (r)[0] && !(r)[1] \
552 && ((r)[0]->la_flags & LDAP_AVA_STRING) \
553 && ((r)[0]->la_attr.bv_len == 2) \
554 && (((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTR[0]) \
555 || ((r)[0]->la_attr.bv_val[0] == LDAP_DC_ATTRU[0])) \
556 && (((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTR[1]) \
557 || ((r)[0]->la_attr.bv_val[1] == LDAP_DC_ATTRU[1])))
559 /* Composite rules */
560 #define LDAP_DN_ALLOW_ONE_SPACE(f) \
561 ( LDAP_DN_LDAPV2(f) \
562 || !( (f) & LDAP_DN_P_NOSPACEAFTERRDN ) )
563 #define LDAP_DN_ALLOW_SPACES(f) \
564 ( LDAP_DN_LDAPV2(f) \
565 || !( (f) & ( LDAP_DN_P_NOLEADTRAILSPACES | LDAP_DN_P_NOSPACEAFTERRDN ) ) )
566 #define LDAP_DN_LDAP(f) \
567 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAP )
568 #define LDAP_DN_LDAPV3(f) \
569 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV3 )
570 #define LDAP_DN_LDAPV2(f) \
571 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_LDAPV2 )
572 #define LDAP_DN_DCE(f) \
573 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_DCE )
574 #define LDAP_DN_UFN(f) \
575 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_UFN )
576 #define LDAP_DN_ADC(f) \
577 ( ( (f) & LDAP_DN_FORMAT_MASK ) == LDAP_DN_FORMAT_AD_CANONICAL )
578 #define LDAP_DN_FORMAT(f) ( (f) & LDAP_DN_FORMAT_MASK )
581 * LDAPAVA helpers (will become part of the API for operations
582 * on structural representations of DNs).
585 ldapava_new( const struct berval *attr, const struct berval *val,
586 unsigned flags, void *ctx )
593 ava = LDAP_MALLOCX( sizeof( LDAPAVA ) + attr->bv_len + 1, ctx );
596 ava->la_attr.bv_len = attr->bv_len;
597 ava->la_attr.bv_val = (char *)(ava+1);
598 AC_MEMCPY( ava->la_attr.bv_val, attr->bv_val, attr->bv_len );
599 ava->la_attr.bv_val[attr->bv_len] = '\0';
601 ava->la_value = *val;
602 ava->la_flags = flags | LDAP_AVA_FREE_VALUE;
604 ava->la_private = NULL;
611 ldapava_free( LDAPAVA *ava, void *ctx )
616 /* ava's private must be freed by caller
617 * (at present let's skip this check because la_private
618 * basically holds static data) */
619 assert( ava->la_private == NULL );
622 if (ava->la_flags & LDAP_AVA_FREE_VALUE)
623 LDAP_FREEX( ava->la_value.bv_val, ctx );
625 LDAP_FREEX( ava, ctx );
629 ldap_rdnfree( LDAPRDN rdn )
631 ldap_rdnfree_x( rdn, NULL );
635 ldap_rdnfree_x( LDAPRDN rdn, void *ctx )
643 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
644 ldapava_free( rdn[ iAVA ], ctx );
647 LDAP_FREEX( rdn, ctx );
651 ldap_dnfree( LDAPDN dn )
653 ldap_dnfree_x( dn, NULL );
657 ldap_dnfree_x( LDAPDN dn, void *ctx )
665 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
666 ldap_rdnfree_x( dn[ iRDN ], ctx );
669 LDAP_FREEX( dn, ctx );
673 * Converts a string representation of a DN (in LDAPv3, LDAPv2 or DCE)
674 * into a structural representation of the DN, by separating attribute
675 * types and values encoded in the more appropriate form, which is
676 * string or OID for attribute types and binary form of the BER encoded
677 * value or Unicode string. Formats different from LDAPv3 are parsed
678 * according to their own rules and turned into the more appropriate
679 * form according to LDAPv3.
681 * NOTE: I realize the code is getting spaghettish; it is rather
682 * experimental and will hopefully turn into something more simple
683 * and readable as soon as it works as expected.
687 * Default sizes of AVA and RDN static working arrays; if required
688 * the are dynamically resized. The values can be tuned in case
689 * of special requirements (e.g. very deep DN trees or high number
692 #define TMP_AVA_SLOTS 8
693 #define TMP_RDN_SLOTS 32
696 ldap_str2dn( LDAP_CONST char *str, LDAPDN *dn, unsigned flags )
702 bv.bv_len = strlen( str );
703 bv.bv_val = (char *) str;
705 return ldap_bv2dn_x( &bv, dn, flags, NULL );
709 ldap_bv2dn( struct berval *bv, LDAPDN *dn, unsigned flags )
711 return ldap_bv2dn_x( bv, dn, flags, NULL );
715 ldap_bv2dn_x( struct berval *bv, LDAPDN *dn, unsigned flags, void *ctx )
718 int rc = LDAP_DECODING_ERROR;
722 LDAPRDN newRDN = NULL, tmpDN_[TMP_RDN_SLOTS], *tmpDN = tmpDN_;
723 int num_slots = TMP_RDN_SLOTS;
724 char *str = bv->bv_val;
725 char *end = str + bv->bv_len;
728 assert( bv->bv_val );
732 LDAP_LOG ( OPERATION, ARGS, "ldap_bv2dn(%s,%u)\n%s", str, flags, "" );
734 Debug( LDAP_DEBUG_TRACE, "=> ldap_bv2dn(%s,%u)\n%s", str, flags, "" );
739 switch ( LDAP_DN_FORMAT( flags ) ) {
740 case LDAP_DN_FORMAT_LDAP:
741 case LDAP_DN_FORMAT_LDAPV3:
742 case LDAP_DN_FORMAT_LDAPV2:
743 case LDAP_DN_FORMAT_DCE:
746 /* unsupported in str2dn */
747 case LDAP_DN_FORMAT_UFN:
748 case LDAP_DN_FORMAT_AD_CANONICAL:
749 return LDAP_PARAM_ERROR;
751 case LDAP_DN_FORMAT_LBER:
753 return LDAP_PARAM_ERROR;
756 if ( bv->bv_len == 0 ) {
760 if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) {
761 /* value must have embedded NULs */
762 return LDAP_DECODING_ERROR;
766 if ( LDAP_DN_DCE( flags ) ) {
769 * (from Luke Howard: thnx) A RDN separator is required
770 * at the beginning of an (absolute) DN.
772 if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
778 * actually we do not want to accept by default the DCE form,
779 * we do not want to auto-detect it
782 } else if ( LDAP_DN_LDAP( flags ) ) {
784 * if dn starts with '/' let's make it a DCE dn
786 if ( LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
787 flags |= LDAP_DN_FORMAT_DCE;
793 for ( ; p < end; p++ ) {
796 tmpbv.bv_len = bv->bv_len - ( p - str );
797 tmpbv.bv_val = (char *)p;
799 err = ldap_bv2rdn_x( &tmpbv, &newRDN, (char **) &p, flags,ctx);
800 if ( err != LDAP_SUCCESS ) {
805 * We expect a rdn separator
807 if ( p < end && p[ 0 ] ) {
808 switch ( LDAP_DN_FORMAT( flags ) ) {
809 case LDAP_DN_FORMAT_LDAPV3:
810 if ( !LDAP_DN_RDN_SEP( p[ 0 ] ) ) {
811 rc = LDAP_DECODING_ERROR;
816 case LDAP_DN_FORMAT_LDAP:
817 case LDAP_DN_FORMAT_LDAPV2:
818 if ( !LDAP_DN_RDN_SEP_V2( p[ 0 ] ) ) {
819 rc = LDAP_DECODING_ERROR;
824 case LDAP_DN_FORMAT_DCE:
825 if ( !LDAP_DN_RDN_SEP_DCE( p[ 0 ] ) ) {
826 rc = LDAP_DECODING_ERROR;
834 tmpDN[nrdns++] = newRDN;
838 * make the static RDN array dynamically rescalable
840 if ( nrdns == num_slots ) {
843 if ( tmpDN == tmpDN_ ) {
844 tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPRDN * ), ctx );
849 AC_MEMCPY( tmp, tmpDN, num_slots * sizeof( LDAPRDN * ) );
852 tmp = LDAP_REALLOCX( tmpDN, num_slots * 2 * sizeof( LDAPRDN * ), ctx );
863 if ( p >= end || p[ 0 ] == '\0' ) {
865 * the DN is over, phew
867 newDN = (LDAPDN)LDAP_MALLOCX( sizeof(LDAPRDN *) * (nrdns+1), ctx );
868 if ( newDN == NULL ) {
874 if ( LDAP_DN_DCE( flags ) ) {
875 /* add in reversed order */
876 for ( i=0; i<nrdns; i++ )
877 newDN[i] = tmpDN[nrdns-1-i];
879 for ( i=0; i<nrdns; i++ )
891 ldap_rdnfree_x( newRDN, ctx );
894 for ( nrdns-- ;nrdns >= 0; nrdns-- ) {
895 ldap_rdnfree_x( tmpDN[nrdns], ctx );
900 if ( tmpDN != tmpDN_ ) {
901 LDAP_FREEX( tmpDN, ctx );
905 LDAP_LOG ( OPERATION, RESULTS, "<= ldap_bv2dn(%s,%u)=%d\n",
908 Debug( LDAP_DEBUG_TRACE, "<= ldap_bv2dn(%s,%u)=%d\n", str, flags, rc );
918 * Parses a relative DN according to flags up to a rdn separator
919 * or to the end of str.
920 * Returns the rdn and a pointer to the string continuation, which
921 * corresponds to the rdn separator or to '\0' in case the string is over.
924 ldap_str2rdn( LDAP_CONST char *str, LDAPRDN *rdn,
925 char **n_in, unsigned flags )
930 assert( str[ 0 ] != '\0' ); /* FIXME: is this required? */
932 bv.bv_len = strlen( str );
933 bv.bv_val = (char *) str;
935 return ldap_bv2rdn_x( &bv, rdn, n_in, flags, NULL );
939 ldap_bv2rdn( struct berval *bv, LDAPRDN *rdn,
940 char **n_in, unsigned flags )
942 return ldap_bv2rdn_x( bv, rdn, n_in, flags, NULL );
946 ldap_bv2rdn_x( struct berval *bv, LDAPRDN *rdn,
947 char **n_in, unsigned flags, void *ctx )
949 const char **n = (const char **) n_in;
953 int rc = LDAP_DECODING_ERROR;
954 int attrTypeEncoding = LDAP_AVA_STRING,
955 attrValueEncoding = LDAP_AVA_STRING;
957 struct berval attrType = { 0, NULL };
958 struct berval attrValue = { 0, NULL };
960 LDAPRDN newRDN = NULL;
961 LDAPAVA *tmpRDN_[TMP_AVA_SLOTS], **tmpRDN = tmpRDN_;
962 int num_slots = TMP_AVA_SLOTS;
968 assert( bv->bv_len );
969 assert( bv->bv_val );
970 assert( rdn || flags & LDAP_DN_SKIP );
974 stoplen = bv->bv_len;
981 switch ( LDAP_DN_FORMAT( flags ) ) {
982 case LDAP_DN_FORMAT_LDAP:
983 case LDAP_DN_FORMAT_LDAPV3:
984 case LDAP_DN_FORMAT_LDAPV2:
985 case LDAP_DN_FORMAT_DCE:
988 /* unsupported in str2dn */
989 case LDAP_DN_FORMAT_UFN:
990 case LDAP_DN_FORMAT_AD_CANONICAL:
991 return LDAP_PARAM_ERROR;
993 case LDAP_DN_FORMAT_LBER:
995 return LDAP_PARAM_ERROR;
998 if ( bv->bv_len == 0 ) {
1003 if( memchr( bv->bv_val, '\0', bv->bv_len ) != NULL ) {
1004 /* value must have embedded NULs */
1005 return LDAP_DECODING_ERROR;
1009 for ( ; p[ 0 ] || state == GOTAVA; ) {
1012 * The parser in principle advances one token a time,
1013 * or toggles state if preferable.
1018 * an AttributeType can be encoded as:
1019 * - its string representation; in detail, implementations
1020 * MUST recognize AttributeType string type names listed
1021 * in section 2.3 of draft-ietf-ldapbis-dn-XX.txt, and
1022 * MAY recognize other names.
1023 * - its numeric OID (a dotted decimal string); in detail
1024 * RFC 2253 asserts that ``Implementations MUST allow
1025 * an oid in the attribute type to be prefixed by one
1026 * of the character strings "oid." or "OID."''. As soon
1027 * as draft-ietf-ldapbis-dn-XX.txt obsoletes RFC 2253
1028 * I'm not sure whether this is required or not any
1029 * longer; to be liberal, we still implement it.
1032 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1033 if ( !LDAP_DN_ALLOW_ONE_SPACE( flags ) ) {
1040 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1041 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1046 /* whitespace is allowed (and trimmed) */
1048 while ( p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1053 /* error: we expected an AVA */
1059 if ( LDAP_DN_OID_LEADCHAR( p[ 0 ] ) ) {
1060 state = B4OIDATTRTYPE;
1064 /* else must be alpha */
1065 if ( !LDAP_DN_DESC_LEADCHAR( p[ 0 ] ) ) {
1069 /* LDAPv2 "oid." prefix */
1070 if ( LDAP_DN_LDAPV2( flags ) ) {
1072 * to be overly pedantic, we only accept
1075 if ( flags & LDAP_DN_PEDANTIC ) {
1076 if ( !strncmp( p, "OID.", 4 )
1077 || !strncmp( p, "oid.", 4 ) ) {
1079 state = B4OIDATTRTYPE;
1083 if ( !strncasecmp( p, "oid.", 4 ) ) {
1085 state = B4OIDATTRTYPE;
1091 state = B4STRINGATTRTYPE;
1094 case B4OIDATTRTYPE: {
1095 int err = LDAP_SUCCESS;
1097 attrType.bv_val = ldap_int_parse_numericoid( &p, &err,
1100 if ( err != LDAP_SUCCESS ) {
1103 attrType.bv_len = p - attrType.bv_val;
1105 attrTypeEncoding = LDAP_AVA_BINARY;
1107 state = B4AVAEQUALS;
1111 case B4STRINGATTRTYPE: {
1112 const char *startPos, *endPos = NULL;
1116 * the starting char has been found to be
1117 * a LDAP_DN_DESC_LEADCHAR so we don't re-check it
1118 * FIXME: DCE attr types seem to have a more
1119 * restrictive syntax (no '-' ...)
1121 for ( startPos = p++; p[ 0 ]; p++ ) {
1122 if ( LDAP_DN_DESC_CHAR( p[ 0 ] ) ) {
1126 if ( LDAP_DN_LANG_SEP( p[ 0 ] ) ) {
1129 * RFC 2253 does not explicitly
1130 * allow lang extensions to attribute
1133 if ( flags & LDAP_DN_PEDANTIC ) {
1138 * we trim ';' and following lang
1139 * and so from attribute types
1142 for ( ; LDAP_DN_ATTRDESC_CHAR( p[ 0 ] )
1143 || LDAP_DN_LANG_SEP( p[ 0 ] ); p++ ) {
1151 len = ( endPos ? endPos : p ) - startPos;
1156 attrTypeEncoding = LDAP_AVA_STRING;
1159 * here we need to decide whether to use it as is
1160 * or turn it in OID form; as a consequence, we
1161 * need to decide whether to binary encode the value
1164 state = B4AVAEQUALS;
1166 if ( flags & LDAP_DN_SKIP ) {
1170 attrType.bv_val = (char *)startPos;
1171 attrType.bv_len = len;
1177 /* spaces may not be allowed */
1178 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1179 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1184 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1189 /* need equal sign */
1190 if ( !LDAP_DN_AVA_EQUALS( p[ 0 ] ) ) {
1195 /* spaces may not be allowed */
1196 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1197 if ( !LDAP_DN_ALLOW_SPACES( flags ) ) {
1202 for ( p++; LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1208 * octothorpe means a BER encoded value will follow
1209 * FIXME: I don't think DCE will allow it
1211 if ( LDAP_DN_OCTOTHORPE( p[ 0 ] ) ) {
1213 attrValueEncoding = LDAP_AVA_BINARY;
1214 state = B4BINARYVALUE;
1218 /* STRING value expected */
1221 * if we're pedantic, an attribute type in OID form
1222 * SHOULD imply a BER encoded attribute value; we
1223 * should at least issue a warning
1225 if ( ( flags & LDAP_DN_PEDANTIC )
1226 && ( attrTypeEncoding == LDAP_AVA_BINARY ) ) {
1227 /* OID attrType SHOULD use binary encoding */
1231 attrValueEncoding = LDAP_AVA_STRING;
1234 * LDAPv2 allows the attribute value to be quoted;
1235 * also, IA5 values are expected, in principle
1237 if ( LDAP_DN_LDAPV2( flags ) || LDAP_DN_LDAP( flags ) ) {
1238 if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
1240 state = B4IA5VALUEQUOTED;
1244 if ( LDAP_DN_LDAPV2( flags ) ) {
1251 * here STRING means RFC 2253 string
1252 * FIXME: what about DCE strings?
1258 state = B4STRINGVALUE;
1263 if ( hexstr2binval( p, &attrValue, &p, flags, ctx ) ) {
1271 switch ( LDAP_DN_FORMAT( flags ) ) {
1272 case LDAP_DN_FORMAT_LDAP:
1273 case LDAP_DN_FORMAT_LDAPV3:
1274 if ( str2strval( p, stoplen - ( p - str ),
1275 &attrValue, &p, flags,
1276 &attrValueEncoding, ctx ) ) {
1281 case LDAP_DN_FORMAT_DCE:
1282 if ( DCE2strval( p, &attrValue, &p, flags, ctx ) ) {
1295 if ( IA52strval( p, &attrValue, &p, flags, ctx ) ) {
1302 case B4IA5VALUEQUOTED:
1304 /* lead quote already stripped */
1305 if ( quotedIA52strval( p, &attrValue,
1306 &p, flags, ctx ) ) {
1316 if ( !( flags & LDAP_DN_SKIP ) ) {
1320 * we accept empty values
1322 ava = ldapava_new( &attrType, &attrValue,
1323 attrValueEncoding, ctx );
1324 if ( ava == NULL ) {
1325 rc = LDAP_NO_MEMORY;
1328 tmpRDN[navas++] = ava;
1330 attrValue.bv_val = NULL;
1331 attrValue.bv_len = 0;
1334 * prepare room for new AVAs if needed
1336 if (navas == num_slots) {
1339 if ( tmpRDN == tmpRDN_ ) {
1340 tmp = LDAP_MALLOCX( num_slots * 2 * sizeof( LDAPAVA * ), ctx );
1341 if ( tmp == NULL ) {
1342 rc = LDAP_NO_MEMORY;
1345 AC_MEMCPY( tmp, tmpRDN, num_slots * sizeof( LDAPAVA * ) );
1348 tmp = LDAP_REALLOCX( tmpRDN, num_slots * 2 * sizeof( LDAPAVA * ), ctx );
1349 if ( tmp == NULL ) {
1350 rc = LDAP_NO_MEMORY;
1361 * if we got an AVA separator ('+', or ',' for DCE )
1362 * we expect a new AVA for this RDN; otherwise
1363 * we add the RDN to the DN
1365 switch ( LDAP_DN_FORMAT( flags ) ) {
1366 case LDAP_DN_FORMAT_LDAP:
1367 case LDAP_DN_FORMAT_LDAPV3:
1368 case LDAP_DN_FORMAT_LDAPV2:
1369 if ( !LDAP_DN_AVA_SEP( p[ 0 ] ) ) {
1374 case LDAP_DN_FORMAT_DCE:
1375 if ( !LDAP_DN_AVA_SEP_DCE( p[ 0 ] ) ) {
1383 * the RDN is over, phew
1386 if ( !( flags & LDAP_DN_SKIP ) ) {
1387 newRDN = (LDAPRDN)LDAP_MALLOCX(
1388 sizeof(LDAPAVA) * (navas+1), ctx );
1389 if ( newRDN == NULL ) {
1390 rc = LDAP_NO_MEMORY;
1393 AC_MEMCPY( newRDN, tmpRDN, sizeof(LDAPAVA *) * navas);
1394 newRDN[navas] = NULL;
1402 /* they should have been used in an AVA */
1403 attrType.bv_val = NULL;
1404 attrValue.bv_val = NULL;
1419 /* They are set to NULL after they're used in an AVA */
1421 if ( attrValue.bv_val ) {
1422 LDAP_FREEX( attrValue.bv_val, ctx );
1425 for ( navas-- ; navas >= 0; navas-- ) {
1426 ldapava_free( tmpRDN[navas], ctx );
1431 if ( tmpRDN != tmpRDN_ ) {
1432 LDAP_FREEX( tmpRDN, ctx );
1443 * reads in a UTF-8 string value, unescaping stuff:
1444 * '\' + LDAP_DN_NEEDESCAPE(c) -> 'c'
1445 * '\' + HEXPAIR(p) -> unhex(p)
1448 str2strval( const char *str, ber_len_t stoplen, struct berval *val, const char **next, unsigned flags, int *retFlags, void *ctx )
1450 const char *p, *end, *startPos, *endPos = NULL;
1451 ber_len_t len, escapes;
1458 end = str + stoplen;
1459 for ( startPos = p = str, escapes = 0; p < end; p++ ) {
1460 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1462 if ( p[ 0 ] == '\0' ) {
1465 if ( LDAP_DN_MAYESCAPE( p[ 0 ] ) ) {
1470 if ( LDAP_DN_HEXPAIR( p ) ) {
1473 hexstr2bin( p, &c );
1476 if ( !LDAP_DN_ASCII_PRINTABLE( c ) ) {
1479 * we assume the string is UTF-8
1481 *retFlags = LDAP_AVA_NONPRINTABLE;
1488 if ( LDAP_DN_PEDANTIC & flags ) {
1492 * we do not allow escaping
1493 * of chars that don't need
1494 * to and do not belong to
1499 } else if (!LDAP_DN_ASCII_PRINTABLE( p[ 0 ] ) ) {
1500 if ( p[ 0 ] == '\0' ) {
1503 *retFlags = LDAP_AVA_NONPRINTABLE;
1505 } else if ( ( LDAP_DN_LDAP( flags ) && LDAP_DN_VALUE_END_V2( p[ 0 ] ) )
1506 || ( LDAP_DN_LDAPV3( flags ) && LDAP_DN_VALUE_END( p[ 0 ] ) ) ) {
1509 } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] ) ) {
1511 * FIXME: maybe we can add
1512 * escapes if not pedantic?
1519 * we do allow unescaped spaces at the end
1520 * of the value only in non-pedantic mode
1522 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
1523 !LDAP_DN_ESCAPE( p[ -2 ] ) ) {
1524 if ( flags & LDAP_DN_PEDANTIC ) {
1528 /* strip trailing (unescaped) spaces */
1529 for ( endPos = p - 1;
1530 endPos > startPos + 1 &&
1531 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1532 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1539 if ( flags & LDAP_DN_SKIP ) {
1544 * FIXME: test memory?
1546 len = ( endPos ? endPos : p ) - startPos - escapes;
1549 if ( escapes == 0 ) {
1550 if ( *retFlags & LDAP_AVA_NONPRINTABLE ) {
1551 val->bv_val = LDAP_MALLOCX( len + 1, ctx );
1552 AC_MEMCPY( val->bv_val, startPos, len );
1553 val->bv_val[ len ] = '\0';
1555 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
1561 val->bv_val = LDAP_MALLOCX( len + 1, ctx );
1562 for ( s = 0, d = 0; d < len; ) {
1563 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
1565 if ( LDAP_DN_MAYESCAPE( startPos[ s ] ) ) {
1566 val->bv_val[ d++ ] =
1569 } else if ( LDAP_DN_HEXPAIR( &startPos[ s ] ) ) {
1572 hexstr2bin( &startPos[ s ], &c );
1573 val->bv_val[ d++ ] = c;
1577 /* we should never get here */
1582 val->bv_val[ d++ ] = startPos[ s++ ];
1586 val->bv_val[ d ] = '\0';
1594 DCE2strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
1596 const char *p, *startPos, *endPos = NULL;
1597 ber_len_t len, escapes;
1605 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
1606 if ( LDAP_DN_ESCAPE_DCE( p[ 0 ] ) ) {
1608 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
1615 } else if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1620 * FIXME: can we accept anything else? I guess we need
1621 * to stop if a value is not legal
1626 * (unescaped) trailing spaces are trimmed must be silently ignored;
1629 if ( p > startPos + 1 && LDAP_DN_ASCII_SPACE( p[ -1 ] ) &&
1630 !LDAP_DN_ESCAPE( p[ -2 ] ) ) {
1631 if ( flags & LDAP_DN_PEDANTIC ) {
1635 /* strip trailing (unescaped) spaces */
1636 for ( endPos = p - 1;
1637 endPos > startPos + 1 &&
1638 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1639 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1646 if ( flags & LDAP_DN_SKIP ) {
1650 len = ( endPos ? endPos : p ) - startPos - escapes;
1652 if ( escapes == 0 ){
1653 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
1658 val->bv_val = LDAP_MALLOCX( len + 1, ctx );
1659 for ( s = 0, d = 0; d < len; ) {
1661 * This point is reached only if escapes
1662 * are properly used, so all we need to
1665 if ( LDAP_DN_ESCAPE_DCE( startPos[ s ] ) ) {
1669 val->bv_val[ d++ ] = startPos[ s++ ];
1671 val->bv_val[ d ] = '\0';
1672 assert( strlen( val->bv_val ) == len );
1679 IA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
1681 const char *p, *startPos, *endPos = NULL;
1682 ber_len_t len, escapes;
1694 for ( startPos = p = str, escapes = 0; p[ 0 ]; p++ ) {
1695 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1697 if ( p[ 0 ] == '\0' ) {
1701 if ( !LDAP_DN_NEEDESCAPE( p[ 0 ] )
1702 && ( LDAP_DN_PEDANTIC & flags ) ) {
1707 } else if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
1712 * FIXME: can we accept anything else? I guess we need
1713 * to stop if a value is not legal
1717 /* strip trailing (unescaped) spaces */
1719 endPos > startPos + 1 &&
1720 LDAP_DN_ASCII_SPACE( endPos[ -1 ] ) &&
1721 !LDAP_DN_ESCAPE( endPos[ -2 ] );
1727 if ( flags & LDAP_DN_SKIP ) {
1731 len = ( endPos ? endPos : p ) - startPos - escapes;
1733 if ( escapes == 0 ) {
1734 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
1739 val->bv_val = LDAP_MALLOCX( len + 1, ctx );
1740 for ( s = 0, d = 0; d < len; ) {
1741 if ( LDAP_DN_ESCAPE( startPos[ s ] ) ) {
1744 val->bv_val[ d++ ] = startPos[ s++ ];
1746 val->bv_val[ d ] = '\0';
1747 assert( strlen( val->bv_val ) == len );
1754 quotedIA52strval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
1756 const char *p, *startPos, *endPos = NULL;
1758 unsigned escapes = 0;
1766 /* initial quote already eaten */
1767 for ( startPos = p = str; p[ 0 ]; p++ ) {
1769 * According to RFC 1779, the quoted value can
1770 * contain escaped as well as unescaped special values;
1771 * as a consequence we tolerate escaped values
1772 * (e.g. '"\,"' -> '\,') and escape unescaped specials
1773 * (e.g. '","' -> '\,').
1775 if ( LDAP_DN_ESCAPE( p[ 0 ] ) ) {
1776 if ( p[ 1 ] == '\0' ) {
1781 if ( !LDAP_DN_V2_PAIR( p[ 0 ] )
1782 && ( LDAP_DN_PEDANTIC & flags ) ) {
1784 * do we allow to escape normal chars?
1785 * LDAPv2 does not allow any mechanism
1786 * for escaping chars with '\' and hex
1793 } else if ( LDAP_DN_QUOTES( p[ 0 ] ) ) {
1795 /* eat closing quotes */
1801 * FIXME: can we accept anything else? I guess we need
1802 * to stop if a value is not legal
1806 if ( endPos == NULL ) {
1810 /* Strip trailing (unescaped) spaces */
1811 for ( ; p[ 0 ] && LDAP_DN_ASCII_SPACE( p[ 0 ] ); p++ ) {
1816 if ( flags & LDAP_DN_SKIP ) {
1820 len = endPos - startPos - escapes;
1821 assert( endPos >= startPos + escapes );
1823 if ( escapes == 0 ) {
1824 val->bv_val = LDAP_STRNDUPX( startPos, len, ctx );
1829 val->bv_val = LDAP_MALLOCX( len + 1, ctx );
1832 for ( s = d = 0; d < len; ) {
1833 if ( LDAP_DN_ESCAPE( str[ s ] ) ) {
1836 val->bv_val[ d++ ] = str[ s++ ];
1838 val->bv_val[ d ] = '\0';
1839 assert( strlen( val->bv_val ) == len );
1846 hexstr2bin( const char *str, char *c )
1856 if ( LDAP_DN_ASCII_DIGIT( c1 ) ) {
1860 if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c1 ) ) {
1863 assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c1 ) );
1870 if ( LDAP_DN_ASCII_DIGIT( c2 ) ) {
1874 if ( LDAP_DN_ASCII_UCASE_HEXALPHA( c2 ) ) {
1875 *c += c2 - 'A' + 10;
1877 assert( LDAP_DN_ASCII_LCASE_HEXALPHA( c2 ) );
1878 *c += c2 - 'a' + 10;
1886 hexstr2binval( const char *str, struct berval *val, const char **next, unsigned flags, void *ctx )
1888 const char *p, *startPos, *endPos = NULL;
1898 for ( startPos = p = str; p[ 0 ]; p += 2 ) {
1899 switch ( LDAP_DN_FORMAT( flags ) ) {
1900 case LDAP_DN_FORMAT_LDAPV3:
1901 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1906 case LDAP_DN_FORMAT_LDAP:
1907 case LDAP_DN_FORMAT_LDAPV2:
1908 if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
1913 case LDAP_DN_FORMAT_DCE:
1914 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1920 if ( LDAP_DN_ASCII_SPACE( p[ 0 ] ) ) {
1921 if ( flags & LDAP_DN_PEDANTIC ) {
1926 for ( ; p[ 0 ]; p++ ) {
1927 switch ( LDAP_DN_FORMAT( flags ) ) {
1928 case LDAP_DN_FORMAT_LDAPV3:
1929 if ( LDAP_DN_VALUE_END( p[ 0 ] ) ) {
1934 case LDAP_DN_FORMAT_LDAP:
1935 case LDAP_DN_FORMAT_LDAPV2:
1936 if ( LDAP_DN_VALUE_END_V2( p[ 0 ] ) ) {
1941 case LDAP_DN_FORMAT_DCE:
1942 if ( LDAP_DN_VALUE_END_DCE( p[ 0 ] ) ) {
1951 if ( !LDAP_DN_HEXPAIR( p ) ) {
1959 if ( flags & LDAP_DN_SKIP ) {
1963 len = ( ( endPos ? endPos : p ) - startPos ) / 2;
1965 assert( 2 * len == (ber_len_t) (( endPos ? endPos : p ) - startPos ));
1968 val->bv_val = LDAP_MALLOCX( len + 1, ctx );
1969 if ( val->bv_val == NULL ) {
1970 return( LDAP_NO_MEMORY );
1973 for ( s = 0, d = 0; d < len; s += 2, d++ ) {
1976 hexstr2bin( &startPos[ s ], &c );
1978 val->bv_val[ d ] = c;
1981 val->bv_val[ d ] = '\0';
1987 * convert a byte in a hexadecimal pair
1990 byte2hexpair( const char *val, char *pair )
1992 static const char hexdig[] = "0123456789ABCDEF";
1998 * we assume the string has enough room for the hex encoding
2002 pair[ 0 ] = hexdig[ 0x0f & ( val[ 0 ] >> 4 ) ];
2003 pair[ 1 ] = hexdig[ 0x0f & val[ 0 ] ];
2009 * convert a binary value in hexadecimal pairs
2012 binval2hexstr( struct berval *val, char *str )
2019 if ( val->bv_len == 0 ) {
2024 * we assume the string has enough room for the hex encoding
2028 for ( s = 0, d = 0; s < val->bv_len; s++, d += 2 ) {
2029 byte2hexpair( &val->bv_val[ s ], &str[ d ] );
2036 * Length of the string representation, accounting for escaped hex
2040 strval2strlen( struct berval *val, unsigned flags, ber_len_t *len )
2042 ber_len_t l, cl = 1;
2044 int escaped_byte_len = LDAP_DN_IS_PRETTY( flags ) ? 1 : 3;
2045 #ifdef PRETTY_ESCAPE
2046 int escaped_ascii_len = LDAP_DN_IS_PRETTY( flags ) ? 2 : 3;
2047 #endif /* PRETTY_ESCAPE */
2053 if ( val->bv_len == 0 ) {
2057 for ( l = 0, p = val->bv_val; p < val->bv_val + val->bv_len; p += cl ) {
2062 if ( p[ 0 ] == '\0' ) {
2068 cl = LDAP_UTF8_CHARLEN2( p, cl );
2070 /* illegal utf-8 char! */
2073 } else if ( cl > 1 ) {
2076 for ( cnt = 1; cnt < cl; cnt++ ) {
2077 if ( ( p[ cnt ] & 0xc0 ) != 0x80 ) {
2081 l += escaped_byte_len * cl;
2083 } else if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
2084 || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
2085 || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
2086 #ifdef PRETTY_ESCAPE
2088 if ( LDAP_DN_WILLESCAPE_HEX( flags, p[ 0 ] ) ) {
2090 if ( LDAP_DN_WILLESCAPE_CHAR( p[ 0 ] ) ) {
2094 * there might be some chars we want
2095 * to escape in form of a couple
2096 * of hexdigits for optimization purposes
2101 l += escaped_ascii_len;
2103 #else /* ! PRETTY_ESCAPE */
2105 #endif /* ! PRETTY_ESCAPE */
2118 * convert to string representation, escaping with hex the UTF-8 stuff;
2119 * assume the destination has enough room for escaping
2122 strval2str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2124 ber_len_t s, d, end;
2130 if ( val->bv_len == 0 ) {
2136 * we assume the string has enough room for the hex encoding
2139 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
2145 if ( val->bv_val[ s ] == '\0' ) {
2155 * The length was checked in strval2strlen();
2156 * LDAP_UTF8_CHARLEN() should suffice
2158 cl = LDAP_UTF8_CHARLEN2( &val->bv_val[ s ], cl );
2162 * there might be some chars we want to escape in form
2163 * of a couple of hexdigits for optimization purposes
2165 if ( ( cl > 1 && !LDAP_DN_IS_PRETTY( flags ) )
2166 #ifdef PRETTY_ESCAPE
2168 || LDAP_DN_WILLESCAPE_HEX( flags, val->bv_val[ s ] )
2170 || LDAP_DN_WILLESCAPE_CHAR( val->bv_val[ s ] )
2172 #else /* ! PRETTY_ESCAPE */
2173 || LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
2174 || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
2175 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) )
2177 #endif /* ! PRETTY_ESCAPE */
2181 byte2hexpair( &val->bv_val[ s ], &str[ d ] );
2186 } else if ( cl > 1 ) {
2188 str[ d++ ] = val->bv_val[ s++ ];
2192 #ifdef PRETTY_ESCAPE
2193 if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
2194 || ( d == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
2195 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
2197 if ( !LDAP_DN_IS_PRETTY( flags ) ) {
2198 byte2hexpair( &val->bv_val[ s ], &str[ d ] );
2204 #endif /* PRETTY_ESCAPE */
2205 str[ d++ ] = val->bv_val[ s++ ];
2215 * Length of the IA5 string representation (no UTF-8 allowed)
2218 strval2IA5strlen( struct berval *val, unsigned flags, ber_len_t *len )
2227 if ( val->bv_len == 0 ) {
2231 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2233 * Turn value into a binary encoded BER
2238 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2239 if ( LDAP_DN_NEEDESCAPE( p[ 0 ] )
2240 || ( p == val->bv_val && LDAP_DN_NEEDESCAPE_LEAD( p[ 0 ] ) )
2241 || ( !p[ 1 ] && LDAP_DN_NEEDESCAPE_TRAIL( p[ 0 ] ) ) ) {
2256 * convert to string representation (np UTF-8)
2257 * assume the destination has enough room for escaping
2260 strval2IA5str( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2262 ber_len_t s, d, end;
2268 if ( val->bv_len == 0 ) {
2273 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2275 * Turn value into a binary encoded BER
2282 * we assume the string has enough room for the hex encoding
2286 for ( s = 0, d = 0, end = val->bv_len - 1; s < val->bv_len; ) {
2287 if ( LDAP_DN_NEEDESCAPE( val->bv_val[ s ] )
2288 || ( s == 0 && LDAP_DN_NEEDESCAPE_LEAD( val->bv_val[ s ] ) )
2289 || ( s == end && LDAP_DN_NEEDESCAPE_TRAIL( val->bv_val[ s ] ) ) ) {
2292 str[ d++ ] = val->bv_val[ s++ ];
2302 * Length of the (supposedly) DCE string representation,
2303 * accounting for escaped hex of UTF-8 chars
2306 strval2DCEstrlen( struct berval *val, unsigned flags, ber_len_t *len )
2315 if ( val->bv_len == 0 ) {
2319 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2321 * FIXME: Turn the value into a binary encoded BER?
2326 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2327 if ( LDAP_DN_NEEDESCAPE_DCE( p[ 0 ] ) ) {
2342 * convert to (supposedly) DCE string representation,
2343 * escaping with hex the UTF-8 stuff;
2344 * assume the destination has enough room for escaping
2347 strval2DCEstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2355 if ( val->bv_len == 0 ) {
2360 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2362 * FIXME: Turn the value into a binary encoded BER?
2370 * we assume the string has enough room for the hex encoding
2374 for ( s = 0, d = 0; s < val->bv_len; ) {
2375 if ( LDAP_DN_NEEDESCAPE_DCE( val->bv_val[ s ] ) ) {
2378 str[ d++ ] = val->bv_val[ s++ ];
2388 * Length of the (supposedly) AD canonical string representation,
2389 * accounting for escaped hex of UTF-8 chars
2392 strval2ADstrlen( struct berval *val, unsigned flags, ber_len_t *len )
2401 if ( val->bv_len == 0 ) {
2405 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2407 * FIXME: Turn the value into a binary encoded BER?
2412 for ( l = 0, p = val->bv_val; p[ 0 ]; p++ ) {
2413 if ( LDAP_DN_NEEDESCAPE_AD( p[ 0 ] ) ) {
2428 * convert to (supposedly) AD string representation,
2429 * escaping with hex the UTF-8 stuff;
2430 * assume the destination has enough room for escaping
2433 strval2ADstr( struct berval *val, char *str, unsigned flags, ber_len_t *len )
2441 if ( val->bv_len == 0 ) {
2446 if ( flags & LDAP_AVA_NONPRINTABLE ) {
2448 * FIXME: Turn the value into a binary encoded BER?
2456 * we assume the string has enough room for the hex encoding
2460 for ( s = 0, d = 0; s < val->bv_len; ) {
2461 if ( LDAP_DN_NEEDESCAPE_AD( val->bv_val[ s ] ) ) {
2464 str[ d++ ] = val->bv_val[ s++ ];
2474 * If the DN is terminated by single-AVA RDNs with attribute type of "dc",
2475 * the first part of the AD representation of the DN is written in DNS
2476 * form, i.e. dot separated domain name components (as suggested
2477 * by Luke Howard, http://www.padl.com/~lukeh)
2480 dn2domain( LDAPDN dn, struct berval *bv, int pos, int *iRDN )
2483 int domain = 0, first = 1;
2484 ber_len_t l = 1; /* we move the null also */
2487 /* we are guaranteed there's enough memory in str */
2493 assert( *iRDN >= 0 );
2495 str = bv->bv_val + pos;
2497 for ( i = *iRDN; i >= 0; i-- ) {
2507 if ( !LDAP_DN_IS_RDN_DC( rdn ) ) {
2515 AC_MEMCPY( str, ava->la_value.bv_val,
2516 ava->la_value.bv_len + 1);
2517 l += ava->la_value.bv_len;
2520 AC_MEMCPY( str + ava->la_value.bv_len + 1, bv->bv_val + pos, l);
2521 AC_MEMCPY( str, ava->la_value.bv_val,
2522 ava->la_value.bv_len );
2523 str[ ava->la_value.bv_len ] = '.';
2524 l += ava->la_value.bv_len + 1;
2529 bv->bv_len = pos + l - 1;
2535 rdn2strlen( LDAPRDN rdn, unsigned flags, ber_len_t *len,
2536 int ( *s2l )( struct berval *v, unsigned f, ber_len_t *l ) )
2543 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2544 LDAPAVA *ava = rdn[ iAVA ];
2546 /* len(type) + '=' + '+' | ',' */
2547 l += ava->la_attr.bv_len + 2;
2549 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2550 /* octothorpe + twice the length */
2551 l += 1 + 2 * ava->la_value.bv_len;
2555 unsigned f = flags | ava->la_flags;
2557 if ( ( *s2l )( &ava->la_value, f, &vl ) ) {
2570 rdn2str( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len,
2571 int ( *s2s ) ( struct berval *v, char * s, unsigned f, ber_len_t *l ) )
2576 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2577 LDAPAVA *ava = rdn[ iAVA ];
2579 AC_MEMCPY( &str[ l ], ava->la_attr.bv_val,
2580 ava->la_attr.bv_len );
2581 l += ava->la_attr.bv_len;
2585 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2587 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
2590 l += 2 * ava->la_value.bv_len;
2594 unsigned f = flags | ava->la_flags;
2596 if ( ( *s2s )( &ava->la_value, &str[ l ], f, &vl ) ) {
2601 str[ l++ ] = ( rdn[ iAVA + 1] ? '+' : ',' );
2610 rdn2DCEstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
2617 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2618 LDAPAVA *ava = rdn[ iAVA ];
2620 /* len(type) + '=' + ',' | '/' */
2621 l += ava->la_attr.bv_len + 2;
2623 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2624 /* octothorpe + twice the length */
2625 l += 1 + 2 * ava->la_value.bv_len;
2628 unsigned f = flags | ava->la_flags;
2630 if ( strval2DCEstrlen( &ava->la_value, f, &vl ) ) {
2643 rdn2DCEstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first )
2648 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2649 LDAPAVA *ava = rdn[ iAVA ];
2654 str[ l++ ] = ( iAVA ? ',' : '/' );
2657 AC_MEMCPY( &str[ l ], ava->la_attr.bv_val,
2658 ava->la_attr.bv_len );
2659 l += ava->la_attr.bv_len;
2663 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2665 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
2668 l += 2 * ava->la_value.bv_len;
2671 unsigned f = flags | ava->la_flags;
2673 if ( strval2DCEstr( &ava->la_value, &str[ l ], f, &vl ) ) {
2686 rdn2UFNstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
2696 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2697 LDAPAVA *ava = rdn[ iAVA ];
2700 l += ( rdn[ iAVA + 1 ] ? 3 : 2 );
2702 /* FIXME: are binary values allowed in UFN? */
2703 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2704 /* octothorpe + twice the value */
2705 l += 1 + 2 * ava->la_value.bv_len;
2709 unsigned f = flags | ava->la_flags;
2711 if ( strval2strlen( &ava->la_value, f, &vl ) ) {
2724 rdn2UFNstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len )
2729 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2730 LDAPAVA *ava = rdn[ iAVA ];
2732 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2734 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
2737 l += 2 * ava->la_value.bv_len;
2741 unsigned f = flags | ava->la_flags;
2743 if ( strval2str( &ava->la_value, &str[ l ], f, &vl ) ) {
2749 if ( rdn[ iAVA + 1 ] ) {
2750 AC_MEMCPY( &str[ l ], " + ", 3 );
2754 AC_MEMCPY( &str[ l ], ", ", 2 );
2765 rdn2ADstrlen( LDAPRDN rdn, unsigned flags, ber_len_t *len )
2775 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2776 LDAPAVA *ava = rdn[ iAVA ];
2781 /* FIXME: are binary values allowed in UFN? */
2782 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2783 /* octothorpe + twice the value */
2784 l += 1 + 2 * ava->la_value.bv_len;
2787 unsigned f = flags | ava->la_flags;
2789 if ( strval2ADstrlen( &ava->la_value, f, &vl ) ) {
2802 rdn2ADstr( LDAPRDN rdn, char *str, unsigned flags, ber_len_t *len, int first )
2807 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
2808 LDAPAVA *ava = rdn[ iAVA ];
2813 str[ l++ ] = ( iAVA ? ',' : '/' );
2816 if ( ava->la_flags & LDAP_AVA_BINARY ) {
2818 if ( binval2hexstr( &ava->la_value, &str[ l ] ) ) {
2821 l += 2 * ava->la_value.bv_len;
2824 unsigned f = flags | ava->la_flags;
2826 if ( strval2ADstr( &ava->la_value, &str[ l ], f, &vl ) ) {
2841 * Returns in str a string representation of rdn based on flags.
2842 * There is some duplication of code between this and ldap_dn2str;
2843 * this is wanted to reduce the allocation of temporary buffers.
2846 ldap_rdn2str( LDAPRDN rdn, char **str, unsigned flags )
2853 if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
2854 return LDAP_PARAM_ERROR;
2857 rc = ldap_rdn2bv_x( rdn, &bv, flags, NULL );
2863 ldap_rdn2bv( LDAPRDN rdn, struct berval *bv, unsigned flags )
2865 return ldap_rdn2bv_x( rdn, bv, flags, NULL );
2869 ldap_rdn2bv_x( LDAPRDN rdn, struct berval *bv, unsigned flags, void *ctx )
2879 if ( rdn == NULL ) {
2880 bv->bv_val = LDAP_STRDUPX( "", ctx );
2881 return( LDAP_SUCCESS );
2885 * This routine wastes "back" bytes at the end of the string
2888 switch ( LDAP_DN_FORMAT( flags ) ) {
2889 case LDAP_DN_FORMAT_LDAPV3:
2890 if ( rdn2strlen( rdn, flags, &l, strval2strlen ) ) {
2891 return LDAP_DECODING_ERROR;
2895 case LDAP_DN_FORMAT_LDAPV2:
2896 if ( rdn2strlen( rdn, flags, &l, strval2IA5strlen ) ) {
2897 return LDAP_DECODING_ERROR;
2901 case LDAP_DN_FORMAT_UFN:
2902 if ( rdn2UFNstrlen( rdn, flags, &l ) ) {
2903 return LDAP_DECODING_ERROR;
2907 case LDAP_DN_FORMAT_DCE:
2908 if ( rdn2DCEstrlen( rdn, flags, &l ) ) {
2909 return LDAP_DECODING_ERROR;
2913 case LDAP_DN_FORMAT_AD_CANONICAL:
2914 if ( rdn2ADstrlen( rdn, flags, &l ) ) {
2915 return LDAP_DECODING_ERROR;
2920 return LDAP_PARAM_ERROR;
2923 bv->bv_val = LDAP_MALLOCX( l + 1, ctx );
2925 switch ( LDAP_DN_FORMAT( flags ) ) {
2926 case LDAP_DN_FORMAT_LDAPV3:
2927 rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2str );
2931 case LDAP_DN_FORMAT_LDAPV2:
2932 rc = rdn2str( rdn, bv->bv_val, flags, &l, strval2IA5str );
2936 case LDAP_DN_FORMAT_UFN:
2937 rc = rdn2UFNstr( rdn, bv->bv_val, flags, &l );
2941 case LDAP_DN_FORMAT_DCE:
2942 rc = rdn2DCEstr( rdn, bv->bv_val, flags, &l, 1 );
2946 case LDAP_DN_FORMAT_AD_CANONICAL:
2947 rc = rdn2ADstr( rdn, bv->bv_val, flags, &l, 1 );
2952 /* need at least one of the previous */
2953 return LDAP_PARAM_ERROR;
2957 LDAP_FREEX( bv->bv_val, ctx );
2961 bv->bv_len = l - back;
2962 bv->bv_val[ bv->bv_len ] = '\0';
2964 return LDAP_SUCCESS;
2968 * Very bulk implementation; many optimizations can be performed
2969 * - a NULL dn results in an empty string ""
2972 * a) what do we do if a UTF-8 string must be converted in LDAPv2?
2973 * we must encode it in binary form ('#' + HEXPAIRs)
2974 * b) does DCE/AD support UTF-8?
2975 * no clue; don't think so.
2976 * c) what do we do when binary values must be converted in UTF/DCE/AD?
2977 * use binary encoded BER
2979 int ldap_dn2str( LDAPDN dn, char **str, unsigned flags )
2986 if((flags & LDAP_DN_FORMAT_MASK) == LDAP_DN_FORMAT_LBER) {
2987 return LDAP_PARAM_ERROR;
2990 rc = ldap_dn2bv_x( dn, &bv, flags, NULL );
2995 int ldap_dn2bv( LDAPDN dn, struct berval *bv, unsigned flags )
2997 return ldap_dn2bv_x( dn, bv, flags, NULL );
3000 int ldap_dn2bv_x( LDAPDN dn, struct berval *bv, unsigned flags, void *ctx )
3003 int rc = LDAP_ENCODING_ERROR;
3006 /* stringifying helpers for LDAPv3/LDAPv2 */
3007 int ( *sv2l ) ( struct berval *v, unsigned f, ber_len_t *l );
3008 int ( *sv2s ) ( struct berval *v, char *s, unsigned f, ber_len_t *l );
3015 LDAP_LOG ( OPERATION, ARGS, "=> ldap_dn2bv(%u)\n%s%s",
3018 Debug( LDAP_DEBUG_TRACE, "=> ldap_dn2bv(%u)\n%s%s", flags, "", "" );
3022 * a null dn means an empty dn string
3023 * FIXME: better raise an error?
3026 bv->bv_val = LDAP_STRDUPX( "", ctx );
3027 return( LDAP_SUCCESS );
3030 switch ( LDAP_DN_FORMAT( flags ) ) {
3031 case LDAP_DN_FORMAT_LDAPV3:
3032 sv2l = strval2strlen;
3036 case LDAP_DN_FORMAT_LDAPV2:
3037 sv2l = strval2IA5strlen;
3038 sv2s = strval2IA5str;
3041 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
3043 if ( rdn2strlen( dn[ iRDN ], flags, &rdnl, sv2l ) ) {
3044 goto return_results;
3050 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) {
3051 rc = LDAP_NO_MEMORY;
3055 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
3058 if ( rdn2str( dn[ iRDN ], &bv->bv_val[ l ], flags,
3060 LDAP_FREEX( bv->bv_val, ctx );
3062 goto return_results;
3070 * trim the last ',' (the allocated memory
3071 * is one byte longer than required)
3073 bv->bv_len = len - 1;
3074 bv->bv_val[ bv->bv_len ] = '\0';
3079 case LDAP_DN_FORMAT_UFN: {
3081 * FIXME: quoting from RFC 1781:
3083 To take a distinguished name, and generate a name of this format with
3084 attribute types omitted, the following steps are followed.
3086 1. If the first attribute is of type CommonName, the type may be
3089 2. If the last attribute is of type Country, the type may be
3092 3. If the last attribute is of type Country, the last
3093 Organisation attribute may have the type omitted.
3095 4. All attributes of type OrganisationalUnit may have the type
3096 omitted, unless they are after an Organisation attribute or
3097 the first attribute is of type OrganisationalUnit.
3099 * this should be the pedantic implementation.
3101 * Here the standard implementation reflects
3102 * the one historically provided by OpenLDAP
3103 * (and UMIch, I presume), with the variant
3104 * of spaces and plusses (' + ') separating
3107 * A non-standard but nice implementation could
3108 * be to turn the final "dc" attributes into a
3109 * dot-separated domain.
3111 * Other improvements could involve the use of
3112 * friendly country names and so.
3115 int leftmost_dc = -1;
3117 #endif /* DC_IN_UFN */
3119 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
3122 if ( rdn2UFNstrlen( dn[ iRDN ], flags, &rdnl ) ) {
3123 goto return_results;
3128 if ( LDAP_DN_IS_RDN_DC( dn[ iRDN ] ) ) {
3129 if ( leftmost_dc == -1 ) {
3135 #endif /* DC_IN_UFN */
3138 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) {
3139 rc = LDAP_NO_MEMORY;
3144 if ( leftmost_dc == -1 ) {
3145 #endif /* DC_IN_UFN */
3146 for ( l = 0, iRDN = 0; dn[ iRDN ]; iRDN++ ) {
3149 if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ],
3151 LDAP_FREEX( bv->bv_val, ctx );
3153 goto return_results;
3159 * trim the last ', ' (the allocated memory
3160 * is two bytes longer than required)
3162 bv->bv_len = len - 2;
3163 bv->bv_val[ bv->bv_len ] = '\0';
3166 last_iRDN = iRDN - 1;
3168 for ( l = 0, iRDN = 0; iRDN < leftmost_dc; iRDN++ ) {
3171 if ( rdn2UFNstr( dn[ iRDN ], &bv->bv_val[ l ],
3173 LDAP_FREEX( bv->bv_val, ctx );
3175 goto return_results;
3180 if ( !dn2domain( dn, bv, l, &last_iRDN ) ) {
3181 LDAP_FREEX( bv->bv_val, ctx );
3183 goto return_results;
3186 /* the string is correctly terminated by dn2domain */
3188 #endif /* DC_IN_UFN */
3194 case LDAP_DN_FORMAT_DCE:
3195 for ( iRDN = 0, len = 0; dn[ iRDN ]; iRDN++ ) {
3197 if ( rdn2DCEstrlen( dn[ iRDN ], flags, &rdnl ) ) {
3198 goto return_results;
3204 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) {
3205 rc = LDAP_NO_MEMORY;
3209 for ( l = 0; iRDN--; ) {
3212 if ( rdn2DCEstr( dn[ iRDN ], &bv->bv_val[ l ], flags,
3214 LDAP_FREEX( bv->bv_val, ctx );
3216 goto return_results;
3224 bv->bv_val[ bv->bv_len ] = '\0';
3229 case LDAP_DN_FORMAT_AD_CANONICAL: {
3231 * Sort of UFN for DCE DNs: a slash ('/') separated
3232 * global->local DN with no types; strictly speaking,
3233 * the naming context should be a domain, which is
3234 * written in DNS-style, e.g. dot-deparated.
3238 * "givenName=Bill+sn=Gates,ou=People,dc=microsoft,dc=com"
3242 * "microsoft.com/People/Bill,Gates"
3244 for ( iRDN = 0, len = -1; dn[ iRDN ]; iRDN++ ) {
3247 if ( rdn2ADstrlen( dn[ iRDN ], flags, &rdnl ) ) {
3248 goto return_results;
3254 if ( ( bv->bv_val = LDAP_MALLOCX( len + 1, ctx ) ) == NULL ) {
3255 rc = LDAP_NO_MEMORY;
3260 if ( iRDN && dn2domain( dn, bv, 0, &iRDN ) != 0 ) {
3261 for ( l = bv->bv_len; iRDN >= 0 ; iRDN-- ) {
3264 if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ],
3265 flags, &rdnl, 0 ) ) {
3266 LDAP_FREEX( bv->bv_val, ctx );
3268 goto return_results;
3277 * Strictly speaking, AD canonical requires
3278 * a DN to be in the form "..., dc=smtg",
3279 * i.e. terminated by a domain component
3281 if ( flags & LDAP_DN_PEDANTIC ) {
3282 LDAP_FREEX( bv->bv_val, ctx );
3284 rc = LDAP_ENCODING_ERROR;
3288 for ( l = 0; iRDN >= 0 ; iRDN-- ) {
3291 if ( rdn2ADstr( dn[ iRDN ], &bv->bv_val[ l ],
3292 flags, &rdnl, first ) ) {
3293 LDAP_FREEX( bv->bv_val, ctx );
3295 goto return_results;
3305 bv->bv_val[ bv->bv_len ] = '\0';
3311 return LDAP_PARAM_ERROR;
3315 LDAP_LOG ( OPERATION, RESULTS, "<= ldap_dn2bv(%s,%u)=%d\n",
3316 bv->bv_val, flags, rc );
3318 Debug( LDAP_DEBUG_TRACE, "<= ldap_dn2bv(%s,%u)=%d\n",
3319 bv->bv_val, flags, rc );
3327 #include <openssl/x509.h>
3328 #include <openssl/err.h>
3330 /* Convert a structured DN from an X.509 certificate into an LDAPV3 DN.
3331 * x509_name must be an (X509_NAME *). If func is non-NULL, the
3332 * constructed DN will use numeric OIDs to identify attributeTypes,
3333 * and the func() will be invoked to rewrite the DN with the given
3336 * Otherwise the DN will use shortNames as defined in the OpenSSL
3339 * It's preferable to let slapd do the OID to attributeType mapping,
3340 * because the OpenSSL tables are known to have many typos in versions
3341 * up to (at least) 0.9.6c. However, the LDAP client has no schema tables,
3342 * so we're forced to use OpenSSL's mapping there.
3343 * -- Howard Chu 2002-04-18
3347 ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func,
3352 LDAPAVA *newAVA, *baseAVA;
3353 X509_NAME_ENTRY *ne;
3356 char oids[8192], *oidptr = oids, *oidbuf = NULL;
3358 int i, j, k = 0, navas, nrdns, rc = LDAP_SUCCESS;
3360 size_t dnsize, oidrem = sizeof(oids), oidsize = 0;
3369 /* Get the number of AVAs. This is not necessarily the same as
3370 * the number of RDNs.
3372 navas = X509_NAME_entry_count( x509_name );
3374 /* Get the last element, to see how many RDNs there are */
3375 ne = X509_NAME_get_entry( x509_name, navas - 1 );
3376 nrdns = ne->set + 1;
3378 /* Allocate the DN/RDN/AVA stuff as a single block */
3379 dnsize = sizeof(LDAPRDN) * (nrdns+1);
3380 dnsize += sizeof(LDAPAVA *) * (navas+nrdns);
3381 dnsize += sizeof(LDAPAVA) * navas;
3382 if (dnsize > sizeof(ptrs)) {
3383 newDN = (LDAPDN)LDAP_MALLOC( dnsize );
3384 if ( newDN == NULL )
3385 return LDAP_NO_MEMORY;
3387 newDN = (LDAPDN)ptrs;
3390 newDN[nrdns] = NULL;
3391 newRDN = (LDAPRDN)(newDN + nrdns+1);
3392 newAVA = (LDAPAVA *)(newRDN + navas + nrdns);
3395 /* Retrieve RDNs in reverse order; LDAP is backwards from X.500. */
3396 for ( i = nrdns - 1, j = 0; i >= 0; i-- ) {
3397 ne = X509_NAME_get_entry( x509_name, i );
3398 obj = X509_NAME_ENTRY_get_object( ne );
3399 str = X509_NAME_ENTRY_get_data( ne );
3401 /* If set changed, move to next RDN */
3402 if ( set != ne->set ) {
3403 /* If this is not the first time, end the
3404 * previous RDN and advance.
3410 newDN[j++] = newRDN;
3415 newAVA->la_private = NULL;
3416 newAVA->la_flags = LDAP_AVA_STRING;
3419 int n = OBJ_obj2nid( obj );
3423 newAVA->la_attr.bv_val = (char *)OBJ_nid2sn( n );
3424 newAVA->la_attr.bv_len = strlen( newAVA->la_attr.bv_val );
3426 newAVA->la_attr.bv_val = LDAP_STRDUP( newAVA->la_attr.bv_val );
3427 __etoa( newAVA->la_attr.bv_val );
3428 newAVA->la_flags |= LDAP_AVA_FREE_ATTR;
3431 get_oid: newAVA->la_attr.bv_val = oidptr;
3432 newAVA->la_attr.bv_len = OBJ_obj2txt( oidptr, oidrem, obj, 1 );
3434 __etoa( newAVA->la_attr.bv_val );
3436 oidptr += newAVA->la_attr.bv_len + 1;
3437 oidrem -= newAVA->la_attr.bv_len + 1;
3439 /* Running out of OID buffer space? */
3441 if ( oidsize == 0 ) {
3442 oidsize = sizeof(oids) * 2;
3444 oidbuf = LDAP_MALLOC( oidsize );
3445 if ( oidbuf == NULL ) goto nomem;
3449 oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 );
3450 if ( oidbuf == NULL ) goto nomem;
3451 /* Buffer moved! Fix AVA pointers */
3452 if ( old != oidbuf ) {
3454 long dif = oidbuf - old;
3456 for (a=baseAVA; a<=newAVA; a++){
3457 if (a->la_attr.bv_val >= old &&
3458 a->la_attr.bv_val <= (old + oidsize))
3459 a->la_attr.bv_val += dif;
3462 oidptr = oidbuf + oidsize - oidrem;
3468 Val.bv_val = (char *) str->data;
3469 Val.bv_len = str->length;
3470 switch( str->type ) {
3471 case V_ASN1_UNIVERSALSTRING:
3472 /* This uses 32-bit ISO 10646-1 */
3473 csize = 4; goto to_utf8;
3474 case V_ASN1_BMPSTRING:
3475 /* This uses 16-bit ISO 10646-1 */
3476 csize = 2; goto to_utf8;
3477 case V_ASN1_T61STRING:
3478 /* This uses 8-bit, assume ISO 8859-1 */
3480 to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value );
3481 newAVA->la_flags |= LDAP_AVA_FREE_VALUE;
3482 if (rc != LDAP_SUCCESS) goto nomem;
3483 newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
3485 case V_ASN1_UTF8STRING:
3486 newAVA->la_flags = LDAP_AVA_NONPRINTABLE;
3487 /* This is already in UTF-8 encoding */
3488 case V_ASN1_IA5STRING:
3489 case V_ASN1_PRINTABLESTRING:
3490 /* These are always 7-bit strings */
3491 newAVA->la_value = Val;
3502 rc = func( newDN, flags, NULL );
3503 if ( rc != LDAP_SUCCESS )
3507 rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL );
3510 for (;baseAVA < newAVA; baseAVA++) {
3511 if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR)
3512 LDAP_FREE( baseAVA->la_attr.bv_val );
3513 if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE)
3514 LDAP_FREE( baseAVA->la_value.bv_val );
3518 LDAP_FREE( oidbuf );
3519 if ( newDN != (LDAPDN) ptrs )
3523 #endif /* HAVE_TLS */