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