1 /* dn.c - routines for dealing with distinguished names */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the University
22 * may not be used to endorse or promote products derived from this
23 * software without specific prior written permission. This software
24 * is provided ``as is'' without express or implied warranty.
32 #include <ac/socket.h>
33 #include <ac/string.h>
37 #include "ldap_pvt.h" /* must be after slap.h, to get ldap_bv2dn_x() & co */
41 * The DN syntax-related functions take advantage of the dn representation
42 * handling functions ldap_str2dn/ldap_dn2str. The latter are not schema-
43 * aware, so the attributes and their values need be validated (and possibly
44 * normalized). In the current implementation the required validation/nor-
45 * malization/"pretty"ing are done on newly created DN structural represen-
46 * tations; however the idea is to move towards DN handling in structural
47 * representation instead of the current string representation. To this
48 * purpose, we need to do only the required operations and keep track of
49 * what has been done to minimize their impact on performances.
51 * Developers are strongly encouraged to use this feature, to speed-up
55 #define AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )
58 * In-place, schema-aware validation of the
59 * structural representation of a distinguished name.
62 LDAPDN_validate( LDAPDN dn )
69 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
70 LDAPRDN rdn = dn[ iRDN ];
75 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
76 LDAPAVA *ava = rdn[ iAVA ];
77 AttributeDescription *ad;
78 slap_syntax_validate_func *validate = NULL;
82 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
83 const char *text = NULL;
85 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
86 if ( rc != LDAP_SUCCESS ) {
87 return LDAP_INVALID_SYNTAX;
90 ava->la_private = ( void * )ad;
94 * Replace attr oid/name with the canonical name
96 ava->la_attr = ad->ad_cname;
98 validate = ad->ad_type->sat_syntax->ssyn_validate;
102 * validate value by validate function
104 rc = ( *validate )( ad->ad_type->sat_syntax,
107 if ( rc != LDAP_SUCCESS ) {
108 return LDAP_INVALID_SYNTAX;
118 * dn validate routine
130 if ( in->bv_len == 0 ) {
133 } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
134 return LDAP_INVALID_SYNTAX;
137 rc = ldap_bv2dn( in, &dn, LDAP_DN_FORMAT_LDAP );
138 if ( rc != LDAP_SUCCESS ) {
139 return LDAP_INVALID_SYNTAX;
142 assert( strlen( in->bv_val ) == in->bv_len );
145 * Schema-aware validate
147 rc = LDAPDN_validate( dn );
150 if ( rc != LDAP_SUCCESS ) {
151 return LDAP_INVALID_SYNTAX;
158 * AVA sorting inside a RDN
160 * rule: sort attributeTypes in alphabetical order; in case of multiple
161 * occurrences of the same attributeType, sort values in byte order
162 * (use memcmp, which implies alphabetical order in case of IA5 value;
163 * this should guarantee the repeatability of the operation).
165 * Note: the sorting can be slightly improved by sorting first
166 * by attribute type length, then by alphabetical order.
168 * uses a linear search; should be fine since the number of AVAs in
169 * a RDN should be limited.
172 AVA_Sort( LDAPRDN rdn, int iAVA )
175 LDAPAVA *ava_in = rdn[ iAVA ];
180 for ( i = 0; i < iAVA; i++ ) {
181 LDAPAVA *ava = rdn[ i ];
186 a = strcmp( ava_in->la_attr.bv_val, ava->la_attr.bv_val );
195 d = ava_in->la_value.bv_len - ava->la_value.bv_len;
197 v = memcmp( ava_in->la_value.bv_val,
198 ava->la_value.bv_val,
199 d <= 0 ? ava_in->la_value.bv_len
200 : ava->la_value.bv_len );
202 if ( v == 0 && d != 0 ) {
221 a = strcmp( ava_in->la_attr.bv_val,
222 ava->la_attr.bv_val );
228 for ( j = iAVA; j > i; j-- ) {
229 rdn[ j ] = rdn[ j - 1 ];
238 * In-place, schema-aware normalization / "pretty"ing of the
239 * structural representation of a distinguished name.
242 LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx )
249 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
250 LDAPRDN rdn = dn[ iRDN ];
255 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
256 LDAPAVA *ava = rdn[ iAVA ];
257 AttributeDescription *ad;
258 slap_syntax_validate_func *validf = NULL;
259 slap_mr_normalize_func *normf = NULL;
260 slap_syntax_transform_func *transf = NULL;
261 MatchingRule *mr = NULL;
262 struct berval bv = { 0, NULL };
267 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
268 const char *text = NULL;
270 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
271 if ( rc != LDAP_SUCCESS ) {
272 return LDAP_INVALID_SYNTAX;
275 ava->la_private = ( void * )ad;
280 * Replace attr oid/name with the canonical name
282 ava->la_attr = ad->ad_cname;
284 if( ava->la_flags & LDAP_AVA_BINARY ) {
285 if( ava->la_value.bv_len == 0 ) {
286 /* BER encoding is empty */
287 return LDAP_INVALID_SYNTAX;
290 /* AVA is binary encoded, don't muck with it */
291 } else if( flags & SLAP_LDAPDN_PRETTY ) {
292 transf = ad->ad_type->sat_syntax->ssyn_pretty;
294 validf = ad->ad_type->sat_syntax->ssyn_validate;
296 } else { /* normalization */
297 validf = ad->ad_type->sat_syntax->ssyn_validate;
298 mr = ad->ad_type->sat_equality;
299 if( mr ) normf = mr->smr_normalize;
303 /* validate value before normalization */
304 rc = ( *validf )( ad->ad_type->sat_syntax,
307 : (struct berval *) &slap_empty_bv );
309 if ( rc != LDAP_SUCCESS ) {
310 return LDAP_INVALID_SYNTAX;
316 * transform value by pretty function
317 * if value is empty, use empty_bv
319 rc = ( *transf )( ad->ad_type->sat_syntax,
322 : (struct berval *) &slap_empty_bv,
325 if ( rc != LDAP_SUCCESS ) {
326 return LDAP_INVALID_SYNTAX;
333 * if value is empty, use empty_bv
336 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
337 ad->ad_type->sat_syntax,
341 : (struct berval *) &slap_empty_bv,
344 if ( rc != LDAP_SUCCESS ) {
345 return LDAP_INVALID_SYNTAX;
351 if ( ava->la_flags & LDAP_AVA_FREE_VALUE )
352 ber_memfree_x( ava->la_value.bv_val, ctx );
354 ava->la_flags |= LDAP_AVA_FREE_VALUE;
357 if( do_sort ) AVA_Sort( rdn, iAVA );
376 Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
378 if ( val->bv_len != 0 ) {
383 * Go to structural representation
385 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
386 if ( rc != LDAP_SUCCESS ) {
387 return LDAP_INVALID_SYNTAX;
390 assert( strlen( val->bv_val ) == val->bv_len );
393 * Schema-aware rewrite
395 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
396 ldap_dnfree_x( dn, ctx );
397 return LDAP_INVALID_SYNTAX;
401 * Back to string representation
403 rc = ldap_dn2bv_x( dn, out,
404 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
406 ldap_dnfree_x( dn, ctx );
408 if ( rc != LDAP_SUCCESS ) {
409 return LDAP_INVALID_SYNTAX;
412 ber_dupbv_x( out, val, ctx );
415 Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
431 LDAP_LOG( OPERATION, ARGS, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
433 Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
436 if ( val->bv_len == 0 ) {
437 ber_dupbv_x( out, val, ctx );
439 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
440 return LDAP_INVALID_SYNTAX;
446 /* FIXME: should be liberal in what we accept */
447 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
448 if ( rc != LDAP_SUCCESS ) {
449 return LDAP_INVALID_SYNTAX;
452 assert( strlen( val->bv_val ) == val->bv_len );
455 * Schema-aware rewrite
457 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
458 ldap_dnfree_x( dn, ctx );
459 return LDAP_INVALID_SYNTAX;
462 /* FIXME: not sure why the default isn't pretty */
463 /* RE: the default is the form that is used as
464 * an internal representation; the pretty form
466 rc = ldap_dn2bv_x( dn, out,
467 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
469 ldap_dnfree_x( dn, ctx );
471 if ( rc != LDAP_SUCCESS ) {
472 return LDAP_INVALID_SYNTAX;
477 LDAP_LOG( OPERATION, ARGS, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
479 Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
497 LDAP_LOG( OPERATION, ARGS, ">>> dn%sDN: <%s>\n",
498 flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
501 Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n",
502 flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
506 if ( val->bv_len == 0 ) {
509 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
510 return LDAP_INVALID_SYNTAX;
515 /* FIXME: should be liberal in what we accept */
516 rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx );
517 if ( rc != LDAP_SUCCESS ) {
518 return LDAP_INVALID_SYNTAX;
521 assert( strlen( val->bv_val ) == val->bv_len );
524 * Schema-aware rewrite
526 if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) {
527 ldap_dnfree_x( *dn, ctx );
529 return LDAP_INVALID_SYNTAX;
533 Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n",
534 flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
541 * Combination of both dnPretty and dnNormalize
547 struct berval *pretty,
548 struct berval *normal,
552 LDAP_LOG ( OPERATION, ENTRY, ">>> dnPrettyNormal: <%s>\n", val->bv_val, 0, 0 );
554 Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val, 0, 0 );
561 if ( val->bv_len == 0 ) {
562 ber_dupbv_x( pretty, val, ctx );
563 ber_dupbv_x( normal, val, ctx );
565 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
567 return LDAP_INVALID_SYNTAX;
573 pretty->bv_val = NULL;
574 normal->bv_val = NULL;
578 /* FIXME: should be liberal in what we accept */
579 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
580 if ( rc != LDAP_SUCCESS ) {
581 return LDAP_INVALID_SYNTAX;
584 assert( strlen( val->bv_val ) == val->bv_len );
587 * Schema-aware rewrite
589 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
590 ldap_dnfree_x( dn, ctx );
591 return LDAP_INVALID_SYNTAX;
594 rc = ldap_dn2bv_x( dn, pretty,
595 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
597 if ( rc != LDAP_SUCCESS ) {
598 ldap_dnfree_x( dn, ctx );
599 return LDAP_INVALID_SYNTAX;
602 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
603 ldap_dnfree_x( dn, ctx );
604 ber_memfree_x( pretty->bv_val, ctx );
605 pretty->bv_val = NULL;
607 return LDAP_INVALID_SYNTAX;
610 rc = ldap_dn2bv_x( dn, normal,
611 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
613 ldap_dnfree_x( dn, ctx );
614 if ( rc != LDAP_SUCCESS ) {
615 ber_memfree_x( pretty->bv_val, ctx );
616 pretty->bv_val = NULL;
618 return LDAP_INVALID_SYNTAX;
623 LDAP_LOG (OPERATION, RESULTS, "<<< dnPrettyNormal: <%s>, <%s>\n",
624 pretty->bv_val, normal->bv_val, 0 );
626 Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n",
627 pretty->bv_val, normal->bv_val, 0 );
642 struct berval *value,
643 void *assertedValue )
646 struct berval *asserted = (struct berval *) assertedValue;
650 assert( assertedValue );
652 match = value->bv_len - asserted->bv_len;
655 match = memcmp( value->bv_val, asserted->bv_val,
660 LDAP_LOG( CONFIG, ENTRY, "dnMatch: %d\n %s\n %s\n",
661 match, value->bv_val, asserted->bv_val );
663 Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
664 match, value->bv_val, asserted->bv_val );
668 return( LDAP_SUCCESS );
672 * dnParent - dn's parent, in-place
674 * note: the incoming dn is assumed to be normalized/prettyfied,
675 * so that escaped rdn/ava separators are in '\'+hexpair form
684 p = strchr( dn->bv_val, ',' );
689 pdn->bv_val = dn->bv_val + dn->bv_len;
693 assert( DN_SEPARATOR( p[ 0 ] ) );
696 assert( ATTR_LEADCHAR( p[ 0 ] ) );
698 pdn->bv_len = dn->bv_len - (p - dn->bv_val);
716 if( dn->bv_len == 0 ) {
720 rc = ldap_bv2rdn_x( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP, ctx );
721 if ( rc != LDAP_SUCCESS ) {
725 rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
727 ldap_rdnfree_x( tmpRDN, ctx );
728 if ( rc != LDAP_SUCCESS ) {
736 * We can assume the input is a prettied or normalized DN
741 struct berval *dn_in )
747 if ( dn_in == NULL ) {
751 if ( !dn_in->bv_len ) {
755 if ( be != NULL && be_issuffix( be, dn_in ) ) {
759 p = strchr( dn_in->bv_val, ',' );
761 return p ? p - dn_in->bv_val : dn_in->bv_len;
767 * LDAP_SUCCESS if rdn is a legal rdn;
768 * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns)
771 rdnValidate( struct berval *rdn )
775 * input is a pretty or normalized DN
776 * hence, we can just search for ','
778 if( rdn == NULL || rdn->bv_len == 0 ||
779 rdn->bv_len > SLAP_LDAPDN_MAXLEN )
781 return LDAP_INVALID_SYNTAX;
784 return strchr( rdn->bv_val, ',' ) == NULL
785 ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
788 LDAPRDN *RDN, **DN[ 2 ] = { &RDN, NULL };
795 if ( rdn == NULL || rdn == '\0' ) {
802 rc = ldap_bv2rdn( rdn, &RDN, (char **)&p, LDAP_DN_FORMAT_LDAP );
803 if ( rc != LDAP_SUCCESS ) {
810 if ( p[ 0 ] != '\0' ) {
815 * Schema-aware validate
817 if ( rc == LDAP_SUCCESS ) {
818 rc = LDAPDN_validate( DN );
823 * Must validate (there's a repeated parsing ...)
825 return ( rc == LDAP_SUCCESS );
832 * Used by ldbm/bdb2 back_modrdn to create the new dn of entries being
835 * new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
839 build_new_dn( struct berval * new_dn,
840 struct berval * parent_dn,
841 struct berval * newrdn,
846 if ( parent_dn == NULL ) {
847 ber_dupbv( new_dn, newrdn );
851 new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
852 new_dn->bv_val = (char *) sl_malloc( new_dn->bv_len + 1, memctx );
854 ptr = lutil_strcopy( new_dn->bv_val, newrdn->bv_val );
856 strcpy( ptr, parent_dn->bv_val );
861 * dnIsSuffix - tells whether suffix is a suffix of dn.
862 * Both dn and suffix must be normalized.
866 const struct berval *dn,
867 const struct berval *suffix )
869 int d = dn->bv_len - suffix->bv_len;
874 /* empty suffix matches any dn */
875 if ( suffix->bv_len == 0 ) {
879 /* suffix longer than dn */
884 /* no rdn separator or escaped rdn separator */
885 if ( d > 1 && !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) ) {
889 /* no possible match or malformed dn */
895 return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
900 * Convert an X.509 DN into a normalized LDAP DN
903 dnX509normalize( void *x509_name, struct berval *out )
905 /* Invoke the LDAP library's converter with our schema-rewriter */
906 int rc = ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 );
908 Debug( LDAP_DEBUG_TRACE,
909 "dnX509Normalize: <%s>\n", out->bv_val, 0, 0 );
915 * Get the TLS session's peer's DN into a normalized LDAP DN
918 dnX509peerNormalize( void *ssl, struct berval *dn )
921 return ldap_pvt_tls_get_peer_dn( ssl, dn, (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );