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