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