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