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