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