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