]> git.sur5r.net Git - openldap/blob - servers/slapd/dn.c
8bd440dd7e86572a01f18f458004174b2625c557
[openldap] / servers / slapd / dn.c
1 /* dn.c - routines for dealing with distinguished names */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2007 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
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>.
15  */
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17  * All rights reserved.
18  *
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.
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/ctype.h>
32 #include <ac/socket.h>
33 #include <ac/string.h>
34 #include <ac/time.h>
35
36 #include "slap.h"
37 #include "lutil.h"
38
39 /*
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.
49  *
50  * Developers are strongly encouraged to use this feature, to speed-up
51  * its stabilization.
52  */
53
54 #define AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )
55
56 int slap_DN_strict = SLAP_AD_NOINSERT;
57
58 static int
59 LDAPRDN_validate( LDAPRDN rdn )
60 {
61         int             iAVA;
62         int             rc;
63
64         assert( rdn != NULL );
65
66         for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
67                 LDAPAVA                 *ava = rdn[ iAVA ];
68                 AttributeDescription    *ad;
69                 slap_syntax_validate_func *validate = NULL;
70
71                 assert( ava != NULL );
72                 
73                 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
74                         const char      *text = NULL;
75
76                         rc = slap_bv2ad( &ava->la_attr, &ad, &text );
77                         if ( rc != LDAP_SUCCESS ) {
78                                 rc = slap_bv2undef_ad( &ava->la_attr,
79                                         &ad, &text,
80                                         SLAP_AD_PROXIED|slap_DN_strict );
81                                 if ( rc != LDAP_SUCCESS ) {
82                                         return LDAP_INVALID_SYNTAX;
83                                 }
84                         }
85
86                         ava->la_private = ( void * )ad;
87                 }
88
89                 /*
90                  * Do not allow X-ORDERED 'VALUES' naming attributes
91                  */
92                 if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
93                         return LDAP_INVALID_SYNTAX;
94                 }
95
96                 /* 
97                  * Replace attr oid/name with the canonical name
98                  */
99                 ava->la_attr = ad->ad_cname;
100
101                 validate = ad->ad_type->sat_syntax->ssyn_validate;
102
103                 if ( validate ) {
104                         /*
105                          * validate value by validate function
106                          */
107                         rc = ( *validate )( ad->ad_type->sat_syntax,
108                                 &ava->la_value );
109                         
110                         if ( rc != LDAP_SUCCESS ) {
111                                 return LDAP_INVALID_SYNTAX;
112                         }
113                 }
114         }
115
116         return LDAP_SUCCESS;
117 }
118
119 /*
120  * In-place, schema-aware validation of the
121  * structural representation of a distinguished name.
122  */
123 static int
124 LDAPDN_validate( LDAPDN dn )
125 {
126         int             iRDN;
127         int             rc;
128
129         assert( dn != NULL );
130
131         for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
132                 rc = LDAPRDN_validate( dn[ iRDN ] );
133                 if ( rc != LDAP_SUCCESS ) {
134                         return rc;
135                 }
136         }
137
138         return LDAP_SUCCESS;
139 }
140
141 /*
142  * dn validate routine
143  */
144 int
145 dnValidate(
146         Syntax *syntax,
147         struct berval *in )
148 {
149         int             rc;
150         LDAPDN          dn = NULL;
151
152         assert( in != NULL );
153
154         if ( in->bv_len == 0 ) {
155                 return LDAP_SUCCESS;
156
157         } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
158                 return LDAP_INVALID_SYNTAX;
159         }
160
161         rc = ldap_bv2dn( in, &dn, LDAP_DN_FORMAT_LDAP );
162         if ( rc != LDAP_SUCCESS ) {
163                 return LDAP_INVALID_SYNTAX;
164         }
165
166         assert( strlen( in->bv_val ) == in->bv_len );
167
168         /*
169          * Schema-aware validate
170          */
171         rc = LDAPDN_validate( dn );
172         ldap_dnfree( dn );
173
174         if ( rc != LDAP_SUCCESS ) {
175                 return LDAP_INVALID_SYNTAX;
176         }
177
178         return LDAP_SUCCESS;
179 }
180
181 int
182 rdnValidate(
183         Syntax *syntax,
184         struct berval *in )
185 {
186         int             rc;
187         LDAPRDN         rdn;
188         char*           p;
189
190         assert( in != NULL );
191         if ( in->bv_len == 0 ) {
192                 return LDAP_SUCCESS;
193
194         } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
195                 return LDAP_INVALID_SYNTAX;
196         }
197
198         rc = ldap_bv2rdn_x( in , &rdn, (char **) &p,
199                                 LDAP_DN_FORMAT_LDAP, NULL);
200         if ( rc != LDAP_SUCCESS ) {
201                 return LDAP_INVALID_SYNTAX;
202         }
203
204         assert( strlen( in->bv_val ) == in->bv_len );
205
206         /*
207          * Schema-aware validate
208          */
209         rc = LDAPRDN_validate( rdn );
210         ldap_rdnfree( rdn );
211
212         if ( rc != LDAP_SUCCESS ) {
213                 return LDAP_INVALID_SYNTAX;
214         }
215
216         return LDAP_SUCCESS;
217 }
218
219
220 /*
221  * AVA sorting inside a RDN
222  *
223  * rule: sort attributeTypes in alphabetical order; in case of multiple
224  * occurrences of the same attributeType, sort values in byte order
225  * (use memcmp, which implies alphabetical order in case of IA5 value;
226  * this should guarantee the repeatability of the operation).
227  *
228  * Note: the sorting can be slightly improved by sorting first
229  * by attribute type length, then by alphabetical order.
230  *
231  * uses a linear search; should be fine since the number of AVAs in
232  * a RDN should be limited.
233  */
234 static void
235 AVA_Sort( LDAPRDN rdn, int iAVA )
236 {
237         int             i;
238         LDAPAVA         *ava_in = rdn[ iAVA ];
239
240         assert( rdn != NULL );
241         assert( ava_in != NULL );
242         
243         for ( i = 0; i < iAVA; i++ ) {
244                 LDAPAVA         *ava = rdn[ i ];
245                 int             a, j;
246
247                 assert( ava != NULL );
248
249                 a = strcmp( ava_in->la_attr.bv_val, ava->la_attr.bv_val );
250
251                 if ( a > 0 ) {
252                         continue;
253                 }
254
255                 while ( a == 0 ) {
256                         int             v, d;
257
258                         d = ava_in->la_value.bv_len - ava->la_value.bv_len;
259
260                         v = memcmp( ava_in->la_value.bv_val, 
261                                         ava->la_value.bv_val,
262                                         d <= 0 ? ava_in->la_value.bv_len 
263                                                 : ava->la_value.bv_len );
264
265                         if ( v == 0 && d != 0 ) {
266                                 v = d;
267                         }
268
269                         if ( v <= 0 ) {
270                                 /* 
271                                  * got it!
272                                  */
273                                 break;
274                         }
275
276                         if ( ++i == iAVA ) {
277                                 /*
278                                  * already sorted
279                                  */
280                                 return;
281                         }
282
283                         ava = rdn[ i ];
284                         a = strcmp( ava_in->la_attr.bv_val, 
285                                         ava->la_attr.bv_val );
286                 }
287
288                 /*
289                  * move ahead
290                  */
291                 for ( j = iAVA; j > i; j-- ) {
292                         rdn[ j ] = rdn[ j - 1 ];
293                 }
294                 rdn[ i ] = ava_in;
295         }
296 }
297
298 static int
299 LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
300 {
301
302         int rc;
303         int             iAVA;
304         for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
305                 LDAPAVA                 *ava = rdn[ iAVA ];
306                 AttributeDescription    *ad;
307                 slap_syntax_validate_func *validf = NULL;
308                 slap_mr_normalize_func *normf = NULL;
309                 slap_syntax_transform_func *transf = NULL;
310                 MatchingRule *mr = NULL;
311                 struct berval           bv = BER_BVNULL;
312                 int                     do_sort = 0;
313
314                 assert( ava != NULL );
315
316                 if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
317                         const char      *text = NULL;
318
319                         rc = slap_bv2ad( &ava->la_attr, &ad, &text );
320                         if ( rc != LDAP_SUCCESS ) {
321                                 rc = slap_bv2undef_ad( &ava->la_attr,
322                                         &ad, &text,
323                                         SLAP_AD_PROXIED|slap_DN_strict );
324                                 if ( rc != LDAP_SUCCESS ) {
325                                         return LDAP_INVALID_SYNTAX;
326                                 }
327                         }
328                         
329                         ava->la_private = ( void * )ad;
330                         do_sort = 1;
331                 }
332
333                 /* 
334                  * Replace attr oid/name with the canonical name
335                  */
336                 ava->la_attr = ad->ad_cname;
337
338                 if( ava->la_flags & LDAP_AVA_BINARY ) {
339                         if( ava->la_value.bv_len == 0 ) {
340                                 /* BER encoding is empty */
341                                 return LDAP_INVALID_SYNTAX;
342                         }
343
344                         /* Do not allow X-ORDERED 'VALUES' naming attributes */
345                 } else if( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
346                         return LDAP_INVALID_SYNTAX;
347
348                         /* AVA is binary encoded, don't muck with it */
349                 } else if( flags & SLAP_LDAPDN_PRETTY ) {
350                         transf = ad->ad_type->sat_syntax->ssyn_pretty;
351                         if( !transf ) {
352                                 validf = ad->ad_type->sat_syntax->ssyn_validate;
353                         }
354                 } else { /* normalization */
355                         validf = ad->ad_type->sat_syntax->ssyn_validate;
356                         mr = ad->ad_type->sat_equality;
357                         if( mr && (!( mr->smr_usage & SLAP_MR_MUTATION_NORMALIZER ))) {
358                                 normf = mr->smr_normalize;
359                         }
360                 }
361
362                 if ( validf ) {
363                         /* validate value before normalization */
364                         rc = ( *validf )( ad->ad_type->sat_syntax,
365                                 ava->la_value.bv_len
366                                         ? &ava->la_value
367                                         : (struct berval *) &slap_empty_bv );
368
369                         if ( rc != LDAP_SUCCESS ) {
370                                 return LDAP_INVALID_SYNTAX;
371                         }
372                 }
373
374                 if ( transf ) {
375                         /*
376                          * transform value by pretty function
377                          *      if value is empty, use empty_bv
378                          */
379                         rc = ( *transf )( ad->ad_type->sat_syntax,
380                                 ava->la_value.bv_len
381                                         ? &ava->la_value
382                                         : (struct berval *) &slap_empty_bv,
383                                 &bv, ctx );
384                 
385                         if ( rc != LDAP_SUCCESS ) {
386                                 return LDAP_INVALID_SYNTAX;
387                         }
388                 }
389
390                 if ( normf ) {
391                         /*
392                          * normalize value
393                          *      if value is empty, use empty_bv
394                          */
395                         rc = ( *normf )(
396                                 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
397                                 ad->ad_type->sat_syntax,
398                                 mr,
399                                 ava->la_value.bv_len
400                                         ? &ava->la_value
401                                         : (struct berval *) &slap_empty_bv,
402                                 &bv, ctx );
403                 
404                         if ( rc != LDAP_SUCCESS ) {
405                                 return LDAP_INVALID_SYNTAX;
406                         }
407                 }
408
409
410                 if( bv.bv_val ) {
411                         if ( ava->la_flags & LDAP_AVA_FREE_VALUE )
412                                 ber_memfree_x( ava->la_value.bv_val, ctx );
413                         ava->la_value = bv;
414                         ava->la_flags |= LDAP_AVA_FREE_VALUE;
415                 }
416
417                 if( do_sort ) AVA_Sort( rdn, iAVA );
418         }
419         return LDAP_SUCCESS;
420 }
421
422 /*
423  * In-place, schema-aware normalization / "pretty"ing of the
424  * structural representation of a distinguished name.
425  */
426 static int
427 LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx )
428 {
429         int             iRDN;
430         int             rc;
431
432         assert( dn != NULL );
433
434         for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
435                 rc = LDAPRDN_rewrite( dn[ iRDN ], flags, ctx );
436                 if ( rc != LDAP_SUCCESS ) {
437                         return rc;
438                 }
439         }
440
441         return LDAP_SUCCESS;
442 }
443
444 int
445 dnNormalize(
446     slap_mask_t use,
447     Syntax *syntax,
448     MatchingRule *mr,
449     struct berval *val,
450     struct berval *out,
451     void *ctx)
452 {
453         assert( val != NULL );
454         assert( out != NULL );
455
456         Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
457
458         if ( val->bv_len != 0 ) {
459                 LDAPDN          dn = NULL;
460                 int             rc;
461
462                 /*
463                  * Go to structural representation
464                  */
465                 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
466                 if ( rc != LDAP_SUCCESS ) {
467                         return LDAP_INVALID_SYNTAX;
468                 }
469
470                 assert( strlen( val->bv_val ) == val->bv_len );
471
472                 /*
473                  * Schema-aware rewrite
474                  */
475                 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
476                         ldap_dnfree_x( dn, ctx );
477                         return LDAP_INVALID_SYNTAX;
478                 }
479
480                 /*
481                  * Back to string representation
482                  */
483                 rc = ldap_dn2bv_x( dn, out,
484                         LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
485
486                 ldap_dnfree_x( dn, ctx );
487
488                 if ( rc != LDAP_SUCCESS ) {
489                         return LDAP_INVALID_SYNTAX;
490                 }
491         } else {
492                 ber_dupbv_x( out, val, ctx );
493         }
494
495         Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
496
497         return LDAP_SUCCESS;
498 }
499
500 int
501 rdnNormalize(
502     slap_mask_t use,
503     Syntax *syntax,
504     MatchingRule *mr,
505     struct berval *val,
506     struct berval *out,
507     void *ctx)
508 {
509         assert( val != NULL );
510         assert( out != NULL );
511
512         Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
513         if ( val->bv_len != 0 ) {
514                 LDAPRDN         rdn = NULL;
515                 int             rc;
516                 char*           p;
517
518                 /*
519                  * Go to structural representation
520                  */
521                 rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
522                                         LDAP_DN_FORMAT_LDAP, ctx);
523
524                 if ( rc != LDAP_SUCCESS ) {
525                         return LDAP_INVALID_SYNTAX;
526                 }
527
528                 assert( strlen( val->bv_val ) == val->bv_len );
529
530                 /*
531                  * Schema-aware rewrite
532                  */
533                 if ( LDAPRDN_rewrite( rdn, 0, ctx ) != LDAP_SUCCESS ) {
534                         ldap_rdnfree_x( rdn, ctx );
535                         return LDAP_INVALID_SYNTAX;
536                 }
537
538                 /*
539                  * Back to string representation
540                  */
541                 rc = ldap_rdn2bv_x( rdn, out,
542                         LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
543
544                 ldap_rdnfree_x( rdn, ctx );
545
546                 if ( rc != LDAP_SUCCESS ) {
547                         return LDAP_INVALID_SYNTAX;
548                 }
549         } else {
550                 ber_dupbv_x( out, val, ctx );
551         }
552
553         Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
554
555         return LDAP_SUCCESS;
556 }
557
558 int
559 dnPretty(
560         Syntax *syntax,
561         struct berval *val,
562         struct berval *out,
563         void *ctx)
564 {
565         assert( val != NULL );
566         assert( out != NULL );
567
568         Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
569
570         if ( val->bv_len == 0 ) {
571                 ber_dupbv_x( out, val, ctx );
572
573         } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
574                 return LDAP_INVALID_SYNTAX;
575
576         } else {
577                 LDAPDN          dn = NULL;
578                 int             rc;
579
580                 /* FIXME: should be liberal in what we accept */
581                 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
582                 if ( rc != LDAP_SUCCESS ) {
583                         return LDAP_INVALID_SYNTAX;
584                 }
585
586                 assert( strlen( val->bv_val ) == val->bv_len );
587
588                 /*
589                  * Schema-aware rewrite
590                  */
591                 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
592                         ldap_dnfree_x( dn, ctx );
593                         return LDAP_INVALID_SYNTAX;
594                 }
595
596                 /* FIXME: not sure why the default isn't pretty */
597                 /* RE: the default is the form that is used as
598                  * an internal representation; the pretty form
599                  * is a variant */
600                 rc = ldap_dn2bv_x( dn, out,
601                         LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
602
603                 ldap_dnfree_x( dn, ctx );
604
605                 if ( rc != LDAP_SUCCESS ) {
606                         return LDAP_INVALID_SYNTAX;
607                 }
608         }
609
610         Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
611
612         return LDAP_SUCCESS;
613 }
614
615 int
616 rdnPretty(
617         Syntax *syntax,
618         struct berval *val,
619         struct berval *out,
620         void *ctx)
621 {
622         assert( val != NULL );
623         assert( out != NULL );
624
625         Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
626
627         if ( val->bv_len == 0 ) {
628                 ber_dupbv_x( out, val, ctx );
629
630         } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
631                 return LDAP_INVALID_SYNTAX;
632
633         } else {
634                 LDAPRDN         rdn = NULL;
635                 int             rc;
636                 char*           p;
637
638                 /* FIXME: should be liberal in what we accept */
639                 rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
640                                         LDAP_DN_FORMAT_LDAP, ctx);
641                 if ( rc != LDAP_SUCCESS ) {
642                         return LDAP_INVALID_SYNTAX;
643                 }
644
645                 assert( strlen( val->bv_val ) == val->bv_len );
646
647                 /*
648                  * Schema-aware rewrite
649                  */
650                 if ( LDAPRDN_rewrite( rdn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
651                         ldap_rdnfree_x( rdn, ctx );
652                         return LDAP_INVALID_SYNTAX;
653                 }
654
655                 /* FIXME: not sure why the default isn't pretty */
656                 /* RE: the default is the form that is used as
657                  * an internal representation; the pretty form
658                  * is a variant */
659                 rc = ldap_rdn2bv_x( rdn, out,
660                         LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
661
662                 ldap_rdnfree_x( rdn, ctx );
663
664                 if ( rc != LDAP_SUCCESS ) {
665                         return LDAP_INVALID_SYNTAX;
666                 }
667         }
668
669         Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
670
671         return LDAP_SUCCESS;
672 }
673
674
675 int
676 dnPrettyNormalDN(
677         Syntax *syntax,
678         struct berval *val,
679         LDAPDN *dn,
680         int flags,
681         void *ctx )
682 {
683         assert( val != NULL );
684         assert( dn != NULL );
685
686         Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n", 
687                         flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal", 
688                         val->bv_val, 0 );
689
690         if ( val->bv_len == 0 ) {
691                 return LDAP_SUCCESS;
692
693         } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
694                 return LDAP_INVALID_SYNTAX;
695
696         } else {
697                 int             rc;
698
699                 /* FIXME: should be liberal in what we accept */
700                 rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx );
701                 if ( rc != LDAP_SUCCESS ) {
702                         return LDAP_INVALID_SYNTAX;
703                 }
704
705                 assert( strlen( val->bv_val ) == val->bv_len );
706
707                 /*
708                  * Schema-aware rewrite
709                  */
710                 if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) {
711                         ldap_dnfree_x( *dn, ctx );
712                         *dn = NULL;
713                         return LDAP_INVALID_SYNTAX;
714                 }
715         }
716
717         Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n", 
718                         flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
719                         0, 0 );
720
721         return LDAP_SUCCESS;
722 }
723
724 /*
725  * Combination of both dnPretty and dnNormalize
726  */
727 int
728 dnPrettyNormal(
729         Syntax *syntax,
730         struct berval *val,
731         struct berval *pretty,
732         struct berval *normal,
733         void *ctx)
734 {
735         Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val, 0, 0 );
736
737         assert( val != NULL );
738         assert( pretty != NULL );
739         assert( normal != NULL );
740
741         if ( val->bv_len == 0 ) {
742                 ber_dupbv_x( pretty, val, ctx );
743                 ber_dupbv_x( normal, val, ctx );
744
745         } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
746                 /* too big */
747                 return LDAP_INVALID_SYNTAX;
748
749         } else {
750                 LDAPDN          dn = NULL;
751                 int             rc;
752
753                 pretty->bv_val = NULL;
754                 normal->bv_val = NULL;
755                 pretty->bv_len = 0;
756                 normal->bv_len = 0;
757
758                 /* FIXME: should be liberal in what we accept */
759                 rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
760                 if ( rc != LDAP_SUCCESS ) {
761                         return LDAP_INVALID_SYNTAX;
762                 }
763
764                 assert( strlen( val->bv_val ) == val->bv_len );
765
766                 /*
767                  * Schema-aware rewrite
768                  */
769                 if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
770                         ldap_dnfree_x( dn, ctx );
771                         return LDAP_INVALID_SYNTAX;
772                 }
773
774                 rc = ldap_dn2bv_x( dn, pretty,
775                         LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
776
777                 if ( rc != LDAP_SUCCESS ) {
778                         ldap_dnfree_x( dn, ctx );
779                         return LDAP_INVALID_SYNTAX;
780                 }
781
782                 if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
783                         ldap_dnfree_x( dn, ctx );
784                         ber_memfree_x( pretty->bv_val, ctx );
785                         pretty->bv_val = NULL;
786                         pretty->bv_len = 0;
787                         return LDAP_INVALID_SYNTAX;
788                 }
789
790                 rc = ldap_dn2bv_x( dn, normal,
791                         LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
792
793                 ldap_dnfree_x( dn, ctx );
794                 if ( rc != LDAP_SUCCESS ) {
795                         ber_memfree_x( pretty->bv_val, ctx );
796                         pretty->bv_val = NULL;
797                         pretty->bv_len = 0;
798                         return LDAP_INVALID_SYNTAX;
799                 }
800         }
801
802         Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n",
803                 pretty->bv_val, normal->bv_val, 0 );
804
805         return LDAP_SUCCESS;
806 }
807
808 /*
809  * dnMatch routine
810  */
811 int
812 dnMatch(
813         int *matchp,
814         slap_mask_t flags,
815         Syntax *syntax,
816         MatchingRule *mr,
817         struct berval *value,
818         void *assertedValue )
819 {
820         int match;
821         struct berval *asserted = (struct berval *) assertedValue;
822
823         assert( matchp != NULL );
824         assert( value != NULL );
825         assert( assertedValue != NULL );
826         assert( !BER_BVISNULL( value ) );
827         assert( !BER_BVISNULL( asserted ) );
828         
829         match = value->bv_len - asserted->bv_len;
830
831         if ( match == 0 ) {
832                 match = memcmp( value->bv_val, asserted->bv_val, 
833                                 value->bv_len );
834         }
835
836         Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
837                 match, value->bv_val, asserted->bv_val );
838
839         *matchp = match;
840         return LDAP_SUCCESS;
841 }
842
843 /*
844  * dnRelativeMatch routine
845  */
846 int
847 dnRelativeMatch(
848         int *matchp,
849         slap_mask_t flags,
850         Syntax *syntax,
851         MatchingRule *mr,
852         struct berval *value,
853         void *assertedValue )
854 {
855         int match;
856         struct berval *asserted = (struct berval *) assertedValue;
857
858         assert( matchp != NULL );
859         assert( value != NULL );
860         assert( assertedValue != NULL );
861         assert( !BER_BVISNULL( value ) );
862         assert( !BER_BVISNULL( asserted ) );
863
864         if( mr == slap_schema.si_mr_dnSubtreeMatch ) {
865                 if( asserted->bv_len > value->bv_len ) {
866                         match = -1;
867                 } else if ( asserted->bv_len == value->bv_len ) {
868                         match = memcmp( value->bv_val, asserted->bv_val, 
869                                 value->bv_len );
870                 } else {
871                         if( DN_SEPARATOR(
872                                 value->bv_val[value->bv_len - asserted->bv_len - 1] ))
873                         {
874                                 match = memcmp(
875                                         &value->bv_val[value->bv_len - asserted->bv_len],
876                                         asserted->bv_val, 
877                                         asserted->bv_len );
878                         } else {
879                                 match = 1;
880                         }
881                 }
882
883                 *matchp = match;
884                 return LDAP_SUCCESS;
885         }
886
887         if( mr == slap_schema.si_mr_dnSuperiorMatch ) {
888                 asserted = value;
889                 value = (struct berval *) assertedValue;
890                 mr = slap_schema.si_mr_dnSubordinateMatch;
891         }
892
893         if( mr == slap_schema.si_mr_dnSubordinateMatch ) {
894                 if( asserted->bv_len >= value->bv_len ) {
895                         match = -1;
896                 } else {
897                         if( DN_SEPARATOR(
898                                 value->bv_val[value->bv_len - asserted->bv_len - 1] ))
899                         {
900                                 match = memcmp(
901                                         &value->bv_val[value->bv_len - asserted->bv_len],
902                                         asserted->bv_val, 
903                                         asserted->bv_len );
904                         } else {
905                                 match = 1;
906                         }
907                 }
908
909                 *matchp = match;
910                 return LDAP_SUCCESS;
911         }
912
913         if( mr == slap_schema.si_mr_dnOneLevelMatch ) {
914                 if( asserted->bv_len >= value->bv_len ) {
915                         match = -1;
916                 } else {
917                         if( DN_SEPARATOR(
918                                 value->bv_val[value->bv_len - asserted->bv_len - 1] ))
919                         {
920                                 match = memcmp(
921                                         &value->bv_val[value->bv_len - asserted->bv_len],
922                                         asserted->bv_val, 
923                                         asserted->bv_len );
924
925                                 if( !match ) {
926                                         struct berval rdn;
927                                         rdn.bv_val = value->bv_val;
928                                         rdn.bv_len = value->bv_len - asserted->bv_len - 1;
929                                         match = dnIsOneLevelRDN( &rdn ) ? 0 : 1;
930                                 }
931                         } else {
932                                 match = 1;
933                         }
934                 }
935
936                 *matchp = match;
937                 return LDAP_SUCCESS;
938         }
939
940         /* should not be reachable */
941         assert( 0 );
942         return LDAP_OTHER;
943 }
944
945 int
946 rdnMatch(
947         int *matchp,
948         slap_mask_t flags,
949         Syntax *syntax,
950         MatchingRule *mr,
951         struct berval *value,
952         void *assertedValue )
953 {
954         int match;
955         struct berval *asserted = (struct berval *) assertedValue;
956
957         assert( matchp != NULL );
958         assert( value != NULL );
959         assert( assertedValue != NULL );
960         
961         match = value->bv_len - asserted->bv_len;
962
963         if ( match == 0 ) {
964                 match = memcmp( value->bv_val, asserted->bv_val, 
965                                 value->bv_len );
966         }
967
968         Debug( LDAP_DEBUG_ARGS, "rdnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
969                 match, value->bv_val, asserted->bv_val );
970
971         *matchp = match;
972         return LDAP_SUCCESS;
973 }
974
975
976 /*
977  * dnParent - dn's parent, in-place
978  * note: the incoming dn is assumed to be normalized/prettyfied,
979  * so that escaped rdn/ava separators are in '\'+hexpair form
980  *
981  * note: "dn" and "pdn" can point to the same berval;
982  * beware that, in this case, the pointer to the original buffer
983  * will get lost.
984  */
985 void
986 dnParent( 
987         struct berval   *dn, 
988         struct berval   *pdn )
989 {
990         char    *p;
991
992         p = ber_bvchr( dn, ',' );
993
994         /* one-level dn */
995         if ( p == NULL ) {
996                 pdn->bv_len = 0;
997                 pdn->bv_val = dn->bv_val + dn->bv_len;
998                 return;
999         }
1000
1001         assert( DN_SEPARATOR( p[ 0 ] ) );
1002         p++;
1003
1004         assert( ATTR_LEADCHAR( p[ 0 ] ) );
1005         pdn->bv_len = dn->bv_len - (p - dn->bv_val);
1006         pdn->bv_val = p;
1007
1008         return;
1009 }
1010
1011 /*
1012  * dnRdn - dn's rdn, in-place
1013  * note: the incoming dn is assumed to be normalized/prettyfied,
1014  * so that escaped rdn/ava separators are in '\'+hexpair form
1015  */
1016 void
1017 dnRdn( 
1018         struct berval   *dn, 
1019         struct berval   *rdn )
1020 {
1021         char    *p;
1022
1023         *rdn = *dn;
1024         p = ber_bvchr( dn, ',' );
1025
1026         /* one-level dn */
1027         if ( p == NULL ) {
1028                 return;
1029         }
1030
1031         assert( DN_SEPARATOR( p[ 0 ] ) );
1032         assert( ATTR_LEADCHAR( p[ 1 ] ) );
1033         rdn->bv_len = p - dn->bv_val;
1034
1035         return;
1036 }
1037
1038 int
1039 dnExtractRdn( 
1040         struct berval   *dn, 
1041         struct berval   *rdn,
1042         void *ctx )
1043 {
1044         LDAPRDN         tmpRDN;
1045         const char      *p;
1046         int             rc;
1047
1048         assert( dn != NULL );
1049         assert( rdn != NULL );
1050
1051         if( dn->bv_len == 0 ) {
1052                 return LDAP_OTHER;
1053         }
1054
1055         rc = ldap_bv2rdn_x( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP, ctx );
1056         if ( rc != LDAP_SUCCESS ) {
1057                 return rc;
1058         }
1059
1060         rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY,
1061                 ctx );
1062
1063         ldap_rdnfree_x( tmpRDN, ctx );
1064         return rc;
1065 }
1066
1067 /*
1068  * We can assume the input is a prettied or normalized DN
1069  */
1070 ber_len_t
1071 dn_rdnlen(
1072         Backend         *be,
1073         struct berval   *dn_in )
1074 {
1075         const char      *p;
1076
1077         assert( dn_in != NULL );
1078
1079         if ( dn_in == NULL ) {
1080                 return 0;
1081         }
1082
1083         if ( !dn_in->bv_len ) {
1084                 return 0;
1085         }
1086
1087         if ( be != NULL && be_issuffix( be, dn_in ) ) {
1088                 return 0;
1089         }
1090
1091         p = ber_bvchr( dn_in, ',' );
1092
1093         return p ? p - dn_in->bv_val : dn_in->bv_len;
1094 }
1095
1096
1097 /* rdnValidate:
1098  *
1099  * LDAP_SUCCESS if rdn is a legal rdn;
1100  * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns)
1101  */
1102 int
1103 rdn_validate( struct berval *rdn )
1104 {
1105 #if 1
1106         /* Major cheat!
1107          * input is a pretty or normalized DN
1108          * hence, we can just search for ','
1109          */
1110         if( rdn == NULL || rdn->bv_len == 0 ||
1111                 rdn->bv_len > SLAP_LDAPDN_MAXLEN )
1112         {
1113                 return LDAP_INVALID_SYNTAX;
1114         }
1115         return ber_bvchr( rdn, ',' ) == NULL
1116                 ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1117
1118 #else
1119         LDAPRDN         *RDN, **DN[ 2 ] = { &RDN, NULL };
1120         const char      *p;
1121         int             rc;
1122
1123         /*
1124          * must be non-empty
1125          */
1126         if ( rdn == NULL || rdn == '\0' ) {
1127                 return 0;
1128         }
1129
1130         /*
1131          * must be parsable
1132          */
1133         rc = ldap_bv2rdn( rdn, &RDN, (char **)&p, LDAP_DN_FORMAT_LDAP );
1134         if ( rc != LDAP_SUCCESS ) {
1135                 return 0;
1136         }
1137
1138         /*
1139          * Must be one-level
1140          */
1141         if ( p[ 0 ] != '\0' ) {
1142                 return 0;
1143         }
1144
1145         /*
1146          * Schema-aware validate
1147          */
1148         if ( rc == LDAP_SUCCESS ) {
1149                 rc = LDAPDN_validate( DN );
1150         }
1151         ldap_rdnfree( RDN );
1152
1153         /*
1154          * Must validate (there's a repeated parsing ...)
1155          */
1156         return ( rc == LDAP_SUCCESS );
1157 #endif
1158 }
1159
1160
1161 /* build_new_dn:
1162  *
1163  * Used by back-bdb back_modrdn to create the new dn of entries being
1164  * renamed.
1165  *
1166  * new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
1167  */
1168
1169 void
1170 build_new_dn( struct berval * new_dn,
1171         struct berval * parent_dn,
1172         struct berval * newrdn,
1173         void *memctx )
1174 {
1175         char *ptr;
1176
1177         if ( parent_dn == NULL || parent_dn->bv_len == 0 ) {
1178                 ber_dupbv_x( new_dn, newrdn, memctx );
1179                 return;
1180         }
1181
1182         new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
1183         new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx );
1184
1185         ptr = lutil_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len );
1186         *ptr++ = ',';
1187         strcpy( ptr, parent_dn->bv_val );
1188 }
1189
1190
1191 /*
1192  * dnIsSuffix - tells whether suffix is a suffix of dn.
1193  * Both dn and suffix must be normalized.
1194  */
1195 int
1196 dnIsSuffix(
1197         const struct berval *dn,
1198         const struct berval *suffix )
1199 {
1200         int     d = dn->bv_len - suffix->bv_len;
1201
1202         assert( dn != NULL );
1203         assert( suffix != NULL );
1204
1205         /* empty suffix matches any dn */
1206         if ( suffix->bv_len == 0 ) {
1207                 return 1;
1208         }
1209
1210         /* suffix longer than dn */
1211         if ( d < 0 ) {
1212                 return 0;
1213         }
1214
1215         /* no rdn separator or escaped rdn separator */
1216         if ( d > 1 && !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) ) {
1217                 return 0;
1218         }
1219
1220         /* no possible match or malformed dn */
1221         if ( d == 1 ) {
1222                 return 0;
1223         }
1224
1225         /* compare */
1226         return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
1227 }
1228
1229 int
1230 dnIsOneLevelRDN( struct berval *rdn )
1231 {
1232         ber_len_t       len = rdn->bv_len;
1233         for ( ; len--; ) {
1234                 if ( DN_SEPARATOR( rdn->bv_val[ len ] ) ) {
1235                         return 0;
1236                 }
1237         }
1238
1239         return 1;
1240 }
1241
1242 #ifdef HAVE_TLS
1243 static SLAP_CERT_MAP_FN *DNX509PeerNormalizeCertMap = NULL;
1244 #endif
1245
1246 int register_certificate_map_function(SLAP_CERT_MAP_FN *fn)
1247 {
1248 #ifdef HAVE_TLS
1249         if ( DNX509PeerNormalizeCertMap == NULL ) {
1250                 DNX509PeerNormalizeCertMap = fn;
1251                 return 0;
1252         }
1253 #endif
1254
1255         return -1;
1256 }
1257
1258 /*
1259  * Convert an X.509 DN into a normalized LDAP DN
1260  */
1261 int
1262 dnX509normalize( void *x509_name, struct berval *out )
1263 {
1264         /* Invoke the LDAP library's converter with our schema-rewriter */
1265         int rc = ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 );
1266
1267         Debug( LDAP_DEBUG_TRACE,
1268                 "dnX509Normalize: <%s> (%d)\n",
1269                 BER_BVISNULL( out ) ? "(null)" : out->bv_val, rc, 0 );
1270
1271         return rc;
1272 }
1273
1274 #ifdef HAVE_TLS
1275 /*
1276  * Get the TLS session's peer's DN into a normalized LDAP DN
1277  */
1278 int
1279 dnX509peerNormalize( void *ssl, struct berval *dn )
1280 {
1281         int rc = LDAP_INVALID_CREDENTIALS;
1282
1283         if ( DNX509PeerNormalizeCertMap != NULL )
1284                 rc = (*DNX509PeerNormalizeCertMap)( ssl, dn );
1285
1286         if ( rc != LDAP_SUCCESS ) {
1287                 rc = ldap_pvt_tls_get_peer_dn( ssl, dn,
1288                         (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );
1289         }
1290
1291         return rc;
1292 }
1293 #endif