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