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