1 /* dn.c - routines for dealing with distinguished names */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2005 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>
40 * The DN syntax-related functions take advantage of the dn representation
41 * handling functions ldap_str2dn/ldap_dn2str. The latter are not schema-
42 * aware, so the attributes and their values need be validated (and possibly
43 * normalized). In the current implementation the required validation/nor-
44 * malization/"pretty"ing are done on newly created DN structural represen-
45 * tations; however the idea is to move towards DN handling in structural
46 * representation instead of the current string representation. To this
47 * purpose, we need to do only the required operations and keep track of
48 * what has been done to minimize their impact on performances.
50 * Developers are strongly encouraged to use this feature, to speed-up
54 #define AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )
57 LDAPRDN_validate( LDAPRDN rdn )
64 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
65 LDAPAVA *ava = rdn[ iAVA ];
66 AttributeDescription *ad;
67 slap_syntax_validate_func *validate = NULL;
71 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
72 const char *text = NULL;
74 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
75 if ( rc != LDAP_SUCCESS ) {
76 return LDAP_INVALID_SYNTAX;
79 ava->la_private = ( void * )ad;
83 * Replace attr oid/name with the canonical name
85 ava->la_attr = ad->ad_cname;
87 validate = ad->ad_type->sat_syntax->ssyn_validate;
91 * validate value by validate function
93 rc = ( *validate )( ad->ad_type->sat_syntax,
96 if ( rc != LDAP_SUCCESS ) {
97 return LDAP_INVALID_SYNTAX;
106 * In-place, schema-aware validation of the
107 * structural representation of a distinguished name.
110 LDAPDN_validate( LDAPDN dn )
117 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
118 LDAPRDN rdn = dn[ iRDN ];
123 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
124 LDAPAVA *ava = rdn[ iAVA ];
125 AttributeDescription *ad;
126 slap_syntax_validate_func *validate = NULL;
130 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
131 const char *text = NULL;
133 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
134 if ( rc != LDAP_SUCCESS ) {
135 return LDAP_INVALID_SYNTAX;
138 ava->la_private = ( void * )ad;
142 * Replace attr oid/name with the canonical name
144 ava->la_attr = ad->ad_cname;
146 validate = ad->ad_type->sat_syntax->ssyn_validate;
150 * validate value by validate function
152 rc = ( *validate )( ad->ad_type->sat_syntax,
155 if ( rc != LDAP_SUCCESS ) {
156 return LDAP_INVALID_SYNTAX;
166 * dn validate routine
178 if ( in->bv_len == 0 ) {
181 } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
182 return LDAP_INVALID_SYNTAX;
185 rc = ldap_bv2dn( in, &dn, LDAP_DN_FORMAT_LDAP );
186 if ( rc != LDAP_SUCCESS ) {
187 return LDAP_INVALID_SYNTAX;
190 assert( strlen( in->bv_val ) == in->bv_len );
193 * Schema-aware validate
195 rc = LDAPDN_validate( dn );
198 if ( rc != LDAP_SUCCESS ) {
199 return LDAP_INVALID_SYNTAX;
215 if ( in->bv_len == 0 ) {
218 } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
219 return LDAP_INVALID_SYNTAX;
222 rc = ldap_bv2rdn_x( in , &rdn, (char **) &p,
223 LDAP_DN_FORMAT_LDAP, NULL);
224 if ( rc != LDAP_SUCCESS ) {
225 return LDAP_INVALID_SYNTAX;
228 assert( strlen( in->bv_val ) == in->bv_len );
231 * Schema-aware validate
233 rc = LDAPRDN_validate( rdn );
236 if ( rc != LDAP_SUCCESS ) {
237 return LDAP_INVALID_SYNTAX;
245 * AVA sorting inside a RDN
247 * rule: sort attributeTypes in alphabetical order; in case of multiple
248 * occurrences of the same attributeType, sort values in byte order
249 * (use memcmp, which implies alphabetical order in case of IA5 value;
250 * this should guarantee the repeatability of the operation).
252 * Note: the sorting can be slightly improved by sorting first
253 * by attribute type length, then by alphabetical order.
255 * uses a linear search; should be fine since the number of AVAs in
256 * a RDN should be limited.
259 AVA_Sort( LDAPRDN rdn, int iAVA )
262 LDAPAVA *ava_in = rdn[ iAVA ];
267 for ( i = 0; i < iAVA; i++ ) {
268 LDAPAVA *ava = rdn[ i ];
273 a = strcmp( ava_in->la_attr.bv_val, ava->la_attr.bv_val );
282 d = ava_in->la_value.bv_len - ava->la_value.bv_len;
284 v = memcmp( ava_in->la_value.bv_val,
285 ava->la_value.bv_val,
286 d <= 0 ? ava_in->la_value.bv_len
287 : ava->la_value.bv_len );
289 if ( v == 0 && d != 0 ) {
308 a = strcmp( ava_in->la_attr.bv_val,
309 ava->la_attr.bv_val );
315 for ( j = iAVA; j > i; j-- ) {
316 rdn[ j ] = rdn[ j - 1 ];
325 LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
330 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
331 LDAPAVA *ava = rdn[ iAVA ];
332 AttributeDescription *ad;
333 slap_syntax_validate_func *validf = NULL;
334 slap_mr_normalize_func *normf = NULL;
335 slap_syntax_transform_func *transf = NULL;
336 MatchingRule *mr = NULL;
337 struct berval bv = BER_BVNULL;
342 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
343 const char *text = NULL;
345 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
346 if ( rc != LDAP_SUCCESS ) {
347 return LDAP_INVALID_SYNTAX;
350 ava->la_private = ( void * )ad;
355 * Replace attr oid/name with the canonical name
357 ava->la_attr = ad->ad_cname;
359 if( ava->la_flags & LDAP_AVA_BINARY ) {
360 if( ava->la_value.bv_len == 0 ) {
361 /* BER encoding is empty */
362 return LDAP_INVALID_SYNTAX;
365 /* AVA is binary encoded, don't muck with it */
366 } else if( flags & SLAP_LDAPDN_PRETTY ) {
367 transf = ad->ad_type->sat_syntax->ssyn_pretty;
369 validf = ad->ad_type->sat_syntax->ssyn_validate;
371 } else { /* normalization */
372 validf = ad->ad_type->sat_syntax->ssyn_validate;
373 mr = ad->ad_type->sat_equality;
374 if( mr ) normf = mr->smr_normalize;
378 /* validate value before normalization */
379 rc = ( *validf )( ad->ad_type->sat_syntax,
382 : (struct berval *) &slap_empty_bv );
384 if ( rc != LDAP_SUCCESS ) {
385 return LDAP_INVALID_SYNTAX;
391 * transform value by pretty function
392 * if value is empty, use empty_bv
394 rc = ( *transf )( ad->ad_type->sat_syntax,
397 : (struct berval *) &slap_empty_bv,
400 if ( rc != LDAP_SUCCESS ) {
401 return LDAP_INVALID_SYNTAX;
408 * if value is empty, use empty_bv
411 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
412 ad->ad_type->sat_syntax,
416 : (struct berval *) &slap_empty_bv,
419 if ( rc != LDAP_SUCCESS ) {
420 return LDAP_INVALID_SYNTAX;
426 if ( ava->la_flags & LDAP_AVA_FREE_VALUE )
427 ber_memfree_x( ava->la_value.bv_val, ctx );
429 ava->la_flags |= LDAP_AVA_FREE_VALUE;
432 if( do_sort ) AVA_Sort( rdn, iAVA );
438 * In-place, schema-aware normalization / "pretty"ing of the
439 * structural representation of a distinguished name.
442 LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx )
449 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
450 LDAPRDN rdn = dn[ iRDN ];
455 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
456 LDAPAVA *ava = rdn[ iAVA ];
457 AttributeDescription *ad;
458 slap_syntax_validate_func *validf = NULL;
459 slap_mr_normalize_func *normf = NULL;
460 slap_syntax_transform_func *transf = NULL;
461 MatchingRule *mr = NULL;
462 struct berval bv = BER_BVNULL;
467 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
468 const char *text = NULL;
470 rc = slap_bv2ad( &ava->la_attr, &ad, &text );
471 if ( rc != LDAP_SUCCESS ) {
472 return LDAP_INVALID_SYNTAX;
475 ava->la_private = ( void * )ad;
480 * Replace attr oid/name with the canonical name
482 ava->la_attr = ad->ad_cname;
484 if( ava->la_flags & LDAP_AVA_BINARY ) {
485 if( ava->la_value.bv_len == 0 ) {
486 /* BER encoding is empty */
487 return LDAP_INVALID_SYNTAX;
490 /* AVA is binary encoded, don't muck with it */
491 } else if( flags & SLAP_LDAPDN_PRETTY ) {
492 transf = ad->ad_type->sat_syntax->ssyn_pretty;
494 validf = ad->ad_type->sat_syntax->ssyn_validate;
496 } else { /* normalization */
497 validf = ad->ad_type->sat_syntax->ssyn_validate;
498 mr = ad->ad_type->sat_equality;
499 if( mr ) normf = mr->smr_normalize;
503 /* validate value before normalization */
504 rc = ( *validf )( ad->ad_type->sat_syntax,
507 : (struct berval *) &slap_empty_bv );
509 if ( rc != LDAP_SUCCESS ) {
510 return LDAP_INVALID_SYNTAX;
516 * transform value by pretty function
517 * if value is empty, use empty_bv
519 rc = ( *transf )( ad->ad_type->sat_syntax,
522 : (struct berval *) &slap_empty_bv,
525 if ( rc != LDAP_SUCCESS ) {
526 return LDAP_INVALID_SYNTAX;
533 * if value is empty, use empty_bv
536 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
537 ad->ad_type->sat_syntax,
541 : (struct berval *) &slap_empty_bv,
544 if ( rc != LDAP_SUCCESS ) {
545 return LDAP_INVALID_SYNTAX;
551 if ( ava->la_flags & LDAP_AVA_FREE_VALUE )
552 ber_memfree_x( ava->la_value.bv_val, ctx );
554 ava->la_flags |= LDAP_AVA_FREE_VALUE;
557 if( do_sort ) AVA_Sort( rdn, iAVA );
576 Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
578 if ( val->bv_len != 0 ) {
583 * Go to structural representation
585 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
586 if ( rc != LDAP_SUCCESS ) {
587 return LDAP_INVALID_SYNTAX;
590 assert( strlen( val->bv_val ) == val->bv_len );
593 * Schema-aware rewrite
595 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
596 ldap_dnfree_x( dn, ctx );
597 return LDAP_INVALID_SYNTAX;
601 * Back to string representation
603 rc = ldap_dn2bv_x( dn, out,
604 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
606 ldap_dnfree_x( dn, ctx );
608 if ( rc != LDAP_SUCCESS ) {
609 return LDAP_INVALID_SYNTAX;
612 ber_dupbv_x( out, val, ctx );
615 Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
632 Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
633 if ( val->bv_len != 0 ) {
639 * Go to structural representation
641 rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
642 LDAP_DN_FORMAT_LDAP, ctx);
644 if ( rc != LDAP_SUCCESS ) {
645 return LDAP_INVALID_SYNTAX;
648 assert( strlen( val->bv_val ) == val->bv_len );
651 * Schema-aware rewrite
653 if ( LDAPRDN_rewrite( rdn, 0, ctx ) != LDAP_SUCCESS ) {
654 ldap_rdnfree_x( rdn, ctx );
655 return LDAP_INVALID_SYNTAX;
659 * Back to string representation
661 rc = ldap_rdn2bv_x( rdn, out,
662 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
664 ldap_rdnfree_x( rdn, ctx );
666 if ( rc != LDAP_SUCCESS ) {
667 return LDAP_INVALID_SYNTAX;
670 ber_dupbv_x( out, val, ctx );
673 Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
688 Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
690 if ( val->bv_len == 0 ) {
691 ber_dupbv_x( out, val, ctx );
693 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
694 return LDAP_INVALID_SYNTAX;
700 /* FIXME: should be liberal in what we accept */
701 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
702 if ( rc != LDAP_SUCCESS ) {
703 return LDAP_INVALID_SYNTAX;
706 assert( strlen( val->bv_val ) == val->bv_len );
709 * Schema-aware rewrite
711 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
712 ldap_dnfree_x( dn, ctx );
713 return LDAP_INVALID_SYNTAX;
716 /* FIXME: not sure why the default isn't pretty */
717 /* RE: the default is the form that is used as
718 * an internal representation; the pretty form
720 rc = ldap_dn2bv_x( dn, out,
721 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
723 ldap_dnfree_x( dn, ctx );
725 if ( rc != LDAP_SUCCESS ) {
726 return LDAP_INVALID_SYNTAX;
730 Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
745 Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
747 if ( val->bv_len == 0 ) {
748 ber_dupbv_x( out, val, ctx );
750 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
751 return LDAP_INVALID_SYNTAX;
758 /* FIXME: should be liberal in what we accept */
759 rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
760 LDAP_DN_FORMAT_LDAP, ctx);
761 if ( rc != LDAP_SUCCESS ) {
762 return LDAP_INVALID_SYNTAX;
765 assert( strlen( val->bv_val ) == val->bv_len );
768 * Schema-aware rewrite
770 if ( LDAPRDN_rewrite( rdn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
771 ldap_rdnfree_x( rdn, ctx );
772 return LDAP_INVALID_SYNTAX;
775 /* FIXME: not sure why the default isn't pretty */
776 /* RE: the default is the form that is used as
777 * an internal representation; the pretty form
779 rc = ldap_rdn2bv_x( rdn, out,
780 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
782 ldap_rdnfree_x( rdn, ctx );
784 if ( rc != LDAP_SUCCESS ) {
785 return LDAP_INVALID_SYNTAX;
789 Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
806 Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n",
807 flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
810 if ( val->bv_len == 0 ) {
813 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
814 return LDAP_INVALID_SYNTAX;
819 /* FIXME: should be liberal in what we accept */
820 rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx );
821 if ( rc != LDAP_SUCCESS ) {
822 return LDAP_INVALID_SYNTAX;
825 assert( strlen( val->bv_val ) == val->bv_len );
828 * Schema-aware rewrite
830 if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) {
831 ldap_dnfree_x( *dn, ctx );
833 return LDAP_INVALID_SYNTAX;
837 Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n",
838 flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
845 * Combination of both dnPretty and dnNormalize
851 struct berval *pretty,
852 struct berval *normal,
855 Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val, 0, 0 );
861 if ( val->bv_len == 0 ) {
862 ber_dupbv_x( pretty, val, ctx );
863 ber_dupbv_x( normal, val, ctx );
865 } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
867 return LDAP_INVALID_SYNTAX;
873 pretty->bv_val = NULL;
874 normal->bv_val = NULL;
878 /* FIXME: should be liberal in what we accept */
879 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
880 if ( rc != LDAP_SUCCESS ) {
881 return LDAP_INVALID_SYNTAX;
884 assert( strlen( val->bv_val ) == val->bv_len );
887 * Schema-aware rewrite
889 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
890 ldap_dnfree_x( dn, ctx );
891 return LDAP_INVALID_SYNTAX;
894 rc = ldap_dn2bv_x( dn, pretty,
895 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
897 if ( rc != LDAP_SUCCESS ) {
898 ldap_dnfree_x( dn, ctx );
899 return LDAP_INVALID_SYNTAX;
902 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
903 ldap_dnfree_x( dn, ctx );
904 ber_memfree_x( pretty->bv_val, ctx );
905 pretty->bv_val = NULL;
907 return LDAP_INVALID_SYNTAX;
910 rc = ldap_dn2bv_x( dn, normal,
911 LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
913 ldap_dnfree_x( dn, ctx );
914 if ( rc != LDAP_SUCCESS ) {
915 ber_memfree_x( pretty->bv_val, ctx );
916 pretty->bv_val = NULL;
918 return LDAP_INVALID_SYNTAX;
922 Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n",
923 pretty->bv_val, normal->bv_val, 0 );
937 struct berval *value,
938 void *assertedValue )
941 struct berval *asserted = (struct berval *) assertedValue;
945 assert( assertedValue );
946 assert( !BER_BVISNULL( value ) );
947 assert( !BER_BVISNULL( asserted ) );
949 match = value->bv_len - asserted->bv_len;
952 match = memcmp( value->bv_val, asserted->bv_val,
956 Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
957 match, value->bv_val, asserted->bv_val );
964 * dnRelativeMatch routine
972 struct berval *value,
973 void *assertedValue )
976 struct berval *asserted = (struct berval *) assertedValue;
980 assert( assertedValue );
981 assert( !BER_BVISNULL( value ) );
982 assert( !BER_BVISNULL( asserted ) );
984 if( mr == slap_schema.si_mr_dnSubtreeMatch ) {
985 if( asserted->bv_len > value->bv_len ) {
987 } else if ( asserted->bv_len == value->bv_len ) {
988 match = memcmp( value->bv_val, asserted->bv_val,
992 value->bv_val[value->bv_len - asserted->bv_len - 1] ))
995 &value->bv_val[value->bv_len - asserted->bv_len],
1004 return LDAP_SUCCESS;
1007 if( mr == slap_schema.si_mr_dnSuperiorMatch ) {
1009 value = (struct berval *) assertedValue;
1010 mr = slap_schema.si_mr_dnSubordinateMatch;
1013 if( mr == slap_schema.si_mr_dnSubordinateMatch ) {
1014 if( asserted->bv_len >= value->bv_len ) {
1018 value->bv_val[value->bv_len - asserted->bv_len - 1] ))
1021 &value->bv_val[value->bv_len - asserted->bv_len],
1030 return LDAP_SUCCESS;
1033 if( mr == slap_schema.si_mr_dnOneLevelMatch ) {
1034 if( asserted->bv_len >= value->bv_len ) {
1038 value->bv_val[value->bv_len - asserted->bv_len - 1] ))
1041 &value->bv_val[value->bv_len - asserted->bv_len],
1047 rdn.bv_val = value->bv_val;
1048 rdn.bv_len = value->bv_len - asserted->bv_len - 1;
1049 match = dnIsOneLevelRDN( &rdn ) ? 0 : 1;
1057 return LDAP_SUCCESS;
1060 /* should not be reachable */
1071 struct berval *value,
1072 void *assertedValue )
1075 struct berval *asserted = (struct berval *) assertedValue;
1079 assert( assertedValue );
1081 match = value->bv_len - asserted->bv_len;
1084 match = memcmp( value->bv_val, asserted->bv_val,
1088 Debug( LDAP_DEBUG_ARGS, "rdnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
1089 match, value->bv_val, asserted->bv_val );
1092 return LDAP_SUCCESS;
1097 * dnParent - dn's parent, in-place
1098 * note: the incoming dn is assumed to be normalized/prettyfied,
1099 * so that escaped rdn/ava separators are in '\'+hexpair form
1101 * note: "dn" and "pdn" can point to the same berval;
1102 * beware that, in this case, the pointer to the original buffer
1108 struct berval *pdn )
1112 p = strchr( dn->bv_val, ',' );
1117 pdn->bv_val = dn->bv_val + dn->bv_len;
1121 assert( DN_SEPARATOR( p[ 0 ] ) );
1124 assert( ATTR_LEADCHAR( p[ 0 ] ) );
1125 pdn->bv_len = dn->bv_len - (p - dn->bv_val);
1132 * dnRdn - dn's rdn, in-place
1133 * note: the incoming dn is assumed to be normalized/prettyfied,
1134 * so that escaped rdn/ava separators are in '\'+hexpair form
1139 struct berval *rdn )
1144 p = strchr( dn->bv_val, ',' );
1151 assert( DN_SEPARATOR( p[ 0 ] ) );
1152 assert( ATTR_LEADCHAR( p[ 1 ] ) );
1153 rdn->bv_len = p - dn->bv_val;
1171 if( dn->bv_len == 0 ) {
1175 rc = ldap_bv2rdn_x( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP, ctx );
1176 if ( rc != LDAP_SUCCESS ) {
1180 rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY,
1183 ldap_rdnfree_x( tmpRDN, ctx );
1188 * We can assume the input is a prettied or normalized DN
1193 struct berval *dn_in )
1199 if ( dn_in == NULL ) {
1203 if ( !dn_in->bv_len ) {
1207 if ( be != NULL && be_issuffix( be, dn_in ) ) {
1211 p = strchr( dn_in->bv_val, ',' );
1213 return p ? p - dn_in->bv_val : dn_in->bv_len;
1219 * LDAP_SUCCESS if rdn is a legal rdn;
1220 * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns)
1223 rdn_validate( struct berval *rdn )
1227 * input is a pretty or normalized DN
1228 * hence, we can just search for ','
1230 if( rdn == NULL || rdn->bv_len == 0 ||
1231 rdn->bv_len > SLAP_LDAPDN_MAXLEN )
1233 return LDAP_INVALID_SYNTAX;
1235 return strchr( rdn->bv_val, ',' ) == NULL
1236 ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1239 LDAPRDN *RDN, **DN[ 2 ] = { &RDN, NULL };
1246 if ( rdn == NULL || rdn == '\0' ) {
1253 rc = ldap_bv2rdn( rdn, &RDN, (char **)&p, LDAP_DN_FORMAT_LDAP );
1254 if ( rc != LDAP_SUCCESS ) {
1261 if ( p[ 0 ] != '\0' ) {
1266 * Schema-aware validate
1268 if ( rc == LDAP_SUCCESS ) {
1269 rc = LDAPDN_validate( DN );
1271 ldap_rdnfree( RDN );
1274 * Must validate (there's a repeated parsing ...)
1276 return ( rc == LDAP_SUCCESS );
1283 * Used by ldbm/bdb2 back_modrdn to create the new dn of entries being
1286 * new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
1290 build_new_dn( struct berval * new_dn,
1291 struct berval * parent_dn,
1292 struct berval * newrdn,
1297 if ( parent_dn == NULL || parent_dn->bv_len == 0 ) {
1298 ber_dupbv( new_dn, newrdn );
1302 new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
1303 new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx );
1305 ptr = lutil_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len );
1307 strcpy( ptr, parent_dn->bv_val );
1312 * dnIsSuffix - tells whether suffix is a suffix of dn.
1313 * Both dn and suffix must be normalized.
1317 const struct berval *dn,
1318 const struct berval *suffix )
1320 int d = dn->bv_len - suffix->bv_len;
1325 /* empty suffix matches any dn */
1326 if ( suffix->bv_len == 0 ) {
1330 /* suffix longer than dn */
1335 /* no rdn separator or escaped rdn separator */
1336 if ( d > 1 && !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) ) {
1340 /* no possible match or malformed dn */
1346 return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
1350 dnIsOneLevelRDN( struct berval *rdn )
1352 ber_len_t len = rdn->bv_len;
1354 if ( DN_SEPARATOR( rdn->bv_val[ len ] ) ) {
1363 static SLAP_CERT_MAP_FN *DNX509PeerNormalizeCertMap = NULL;
1366 int register_certificate_map_function(SLAP_CERT_MAP_FN *fn)
1369 if ( DNX509PeerNormalizeCertMap == NULL ) {
1370 DNX509PeerNormalizeCertMap = fn;
1380 * Convert an X.509 DN into a normalized LDAP DN
1383 dnX509normalize( void *x509_name, struct berval *out )
1385 /* Invoke the LDAP library's converter with our schema-rewriter */
1386 int rc = ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 );
1388 Debug( LDAP_DEBUG_TRACE,
1389 "dnX509Normalize: <%s>\n", out->bv_val, 0, 0 );
1395 * Get the TLS session's peer's DN into a normalized LDAP DN
1398 dnX509peerNormalize( void *ssl, struct berval *dn )
1400 int rc = LDAP_INVALID_CREDENTIALS;
1402 if ( DNX509PeerNormalizeCertMap != NULL )
1403 rc = (*DNX509PeerNormalizeCertMap)( ssl, dn );
1405 if ( rc != LDAP_SUCCESS ) {
1406 rc = ldap_pvt_tls_get_peer_dn( ssl, dn,
1407 (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );