xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/dn.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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