dn.c 26.5 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* dn.c - routines for dealing with distinguished names */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
5
 * Copyright 1998-2020 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of Michigan at Ann Arbor. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
26
27

#include "portable.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
28
29
30
31
32
33
34
35

#include <stdio.h>

#include <ac/ctype.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>

Kurt Zeilenga's avatar
Kurt Zeilenga committed
36
#include "slap.h"
37
38
#include "lutil.h"

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
 * The DN syntax-related functions take advantage of the dn representation
 * handling functions ldap_str2dn/ldap_dn2str.  The latter are not schema-
 * aware, so the attributes and their values need be validated (and possibly
 * normalized).  In the current implementation the required validation/nor-
 * malization/"pretty"ing are done on newly created DN structural represen-
 * tations; however the idea is to move towards DN handling in structural
 * representation instead of the current string representation.  To this
 * purpose, we need to do only the required operations and keep track of
 * what has been done to minimize their impact on performances.
 *
 * Developers are strongly encouraged to use this feature, to speed-up
 * its stabilization.
 */

#define	AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )

56
57
int slap_DN_strict = SLAP_AD_NOINSERT;

58
59
60
61
62
63
static int
LDAPRDN_validate( LDAPRDN rdn )
{
	int		iAVA;
	int 		rc;

64
	assert( rdn != NULL );
65
66
67
68
69
70

	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
		LDAPAVA			*ava = rdn[ iAVA ];
		AttributeDescription	*ad;
		slap_syntax_validate_func *validate = NULL;

71
		assert( ava != NULL );
72
73
74
75
76
77
		
		if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
			const char	*text = NULL;

			rc = slap_bv2ad( &ava->la_attr, &ad, &text );
			if ( rc != LDAP_SUCCESS ) {
78
79
				rc = slap_bv2undef_ad( &ava->la_attr,
					&ad, &text,
80
					SLAP_AD_PROXIED|slap_DN_strict );
81
82
83
				if ( rc != LDAP_SUCCESS ) {
					return LDAP_INVALID_SYNTAX;
				}
84
85
86
87
88
			}

			ava->la_private = ( void * )ad;
		}

89
90
91
92
93
94
95
		/*
		 * Do not allow X-ORDERED 'VALUES' naming attributes
		 */
		if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
			return LDAP_INVALID_SYNTAX;
		}

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
		/* 
		 * Replace attr oid/name with the canonical name
		 */
		ava->la_attr = ad->ad_cname;

		validate = ad->ad_type->sat_syntax->ssyn_validate;

		if ( validate ) {
			/*
		 	 * validate value by validate function
			 */
			rc = ( *validate )( ad->ad_type->sat_syntax,
				&ava->la_value );
			
			if ( rc != LDAP_SUCCESS ) {
				return LDAP_INVALID_SYNTAX;
			}
		}
	}
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
115
116

	return LDAP_SUCCESS;
117
118
}

119
120
121
122
123
/*
 * In-place, schema-aware validation of the
 * structural representation of a distinguished name.
 */
static int
Howard Chu's avatar
Howard Chu committed
124
LDAPDN_validate( LDAPDN dn )
125
126
127
128
{
	int 		iRDN;
	int 		rc;

129
	assert( dn != NULL );
130

Howard Chu's avatar
Howard Chu committed
131
	for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
132
133
134
		rc = LDAPRDN_validate( dn[ iRDN ] );
		if ( rc != LDAP_SUCCESS ) {
			return rc;
135
136
137
138
139
140
		}
	}

	return LDAP_SUCCESS;
}

141
/*
142
 * dn validate routine
143
 */
144
145
146
147
int
dnValidate(
	Syntax *syntax,
	struct berval *in )
148
{
149
	int		rc;
Howard Chu's avatar
Howard Chu committed
150
	LDAPDN		dn = NULL;
151

152
	assert( in != NULL );
153
154

	if ( in->bv_len == 0 ) {
155
156
157
158
		return LDAP_SUCCESS;

	} else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
		return LDAP_INVALID_SYNTAX;
159
160
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
161
	rc = ldap_bv2dn( in, &dn, LDAP_DN_FORMAT_LDAP );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
162
163
164
165
166
	if ( rc != LDAP_SUCCESS ) {
		return LDAP_INVALID_SYNTAX;
	}

	assert( strlen( in->bv_val ) == in->bv_len );
167

168
	/*
169
	 * Schema-aware validate
170
	 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
171
	rc = LDAPDN_validate( dn );
172
173
174
175
	ldap_dnfree( dn );

	if ( rc != LDAP_SUCCESS ) {
		return LDAP_INVALID_SYNTAX;
176
	}
177
178

	return LDAP_SUCCESS;
179
180
}

181
182
183
184
185
186
187
188
189
int
rdnValidate(
	Syntax *syntax,
	struct berval *in )
{
	int		rc;
	LDAPRDN		rdn;
	char*		p;

190
	assert( in != NULL );
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
	if ( in->bv_len == 0 ) {
		return LDAP_SUCCESS;

	} else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
		return LDAP_INVALID_SYNTAX;
	}

	rc = ldap_bv2rdn_x( in , &rdn, (char **) &p,
				LDAP_DN_FORMAT_LDAP, NULL);
	if ( rc != LDAP_SUCCESS ) {
		return LDAP_INVALID_SYNTAX;
	}

	assert( strlen( in->bv_val ) == in->bv_len );

	/*
	 * Schema-aware validate
	 */
	rc = LDAPRDN_validate( rdn );
	ldap_rdnfree( rdn );

	if ( rc != LDAP_SUCCESS ) {
		return LDAP_INVALID_SYNTAX;
	}

	return LDAP_SUCCESS;
}


220
221
222
/*
 * AVA sorting inside a RDN
 *
223
 * Rule: sort attributeTypes in alphabetical order.
224
 *
225
226
227
 * Note: the sorting can be slightly improved by sorting first
 * by attribute type length, then by alphabetical order.
 *
228
 * uses an insertion sort; should be fine since the number of AVAs in
229
230
 * a RDN should be limited.
 */
231
static int
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
241
242
	for ( i = 1; i < nAVAs; i++ ) {
		LDAPAVA *ava_j;
		int j;
243

244
245
246
		ava_i = rdn[ i ];
		for ( j = i-1; j >=0; j-- ) {
			int a;
247

248
249
			ava_j = rdn[ j ];
			a = strcmp( ava_i->la_attr.bv_val, ava_j->la_attr.bv_val );
250

251
252
			/* RFC4512 does not allow multiple AVAs
			 * 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
258
				break;

259
			rdn[ j+1 ] = rdn[ j ];
260
		}
261
		rdn[ j+1 ] = ava_i;
262
	}
263
	return rc;
264
265
}

266
267
268
269
static int
LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
{

270
271
	int rc, iAVA, do_sort = 0;

272
273
274
275
276
277
278
279
280
	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
		LDAPAVA			*ava = rdn[ iAVA ];
		AttributeDescription	*ad;
		slap_syntax_validate_func *validf = NULL;
		slap_mr_normalize_func *normf = NULL;
		slap_syntax_transform_func *transf = NULL;
		MatchingRule *mr = NULL;
		struct berval		bv = BER_BVNULL;

281
		assert( ava != NULL );
282
283
284
285
286
287

		if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
			const char	*text = NULL;

			rc = slap_bv2ad( &ava->la_attr, &ad, &text );
			if ( rc != LDAP_SUCCESS ) {
288
289
				rc = slap_bv2undef_ad( &ava->la_attr,
					&ad, &text,
290
					SLAP_AD_PROXIED|slap_DN_strict );
291
292
293
				if ( rc != LDAP_SUCCESS ) {
					return LDAP_INVALID_SYNTAX;
				}
294
295
296
297
298
299
300
301
302
303
304
305
			}
			
			ava->la_private = ( void * )ad;
			do_sort = 1;
		}

		/* 
		 * Replace attr oid/name with the canonical name
		 */
		ava->la_attr = ad->ad_cname;

		if( ava->la_flags & LDAP_AVA_BINARY ) {
306
307
			/* AVA is binary encoded, not supported */
			return LDAP_INVALID_SYNTAX;
308

309
310
311
312
			/* Do not allow X-ORDERED 'VALUES' naming attributes */
		} else if( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
			return LDAP_INVALID_SYNTAX;

313
314
315
316
317
318
319
320
		} else if( flags & SLAP_LDAPDN_PRETTY ) {
			transf = ad->ad_type->sat_syntax->ssyn_pretty;
			if( !transf ) {
				validf = ad->ad_type->sat_syntax->ssyn_validate;
			}
		} else { /* normalization */
			validf = ad->ad_type->sat_syntax->ssyn_validate;
			mr = ad->ad_type->sat_equality;
321
322
323
			if( mr && (!( mr->smr_usage & SLAP_MR_MUTATION_NORMALIZER ))) {
				normf = mr->smr_normalize;
			}
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
		}

		if ( validf ) {
			/* validate value before normalization */
			rc = ( *validf )( ad->ad_type->sat_syntax,
				ava->la_value.bv_len
					? &ava->la_value
					: (struct berval *) &slap_empty_bv );

			if ( rc != LDAP_SUCCESS ) {
				return LDAP_INVALID_SYNTAX;
			}
		}

		if ( transf ) {
			/*
		 	 * transform value by pretty function
			 *	if value is empty, use empty_bv
			 */
			rc = ( *transf )( ad->ad_type->sat_syntax,
				ava->la_value.bv_len
					? &ava->la_value
					: (struct berval *) &slap_empty_bv,
				&bv, ctx );
		
			if ( rc != LDAP_SUCCESS ) {
				return LDAP_INVALID_SYNTAX;
			}
		}

		if ( normf ) {
			/*
		 	 * normalize value
			 *	if value is empty, use empty_bv
			 */
			rc = ( *normf )(
				SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
				ad->ad_type->sat_syntax,
				mr,
				ava->la_value.bv_len
					? &ava->la_value
					: (struct berval *) &slap_empty_bv,
				&bv, ctx );
		
			if ( rc != LDAP_SUCCESS ) {
				return LDAP_INVALID_SYNTAX;
			}
		}


		if( bv.bv_val ) {
			if ( ava->la_flags & LDAP_AVA_FREE_VALUE )
				ber_memfree_x( ava->la_value.bv_val, ctx );
			ava->la_value = bv;
			ava->la_flags |= LDAP_AVA_FREE_VALUE;
		}
380
381
382
383
		/* reject empty values */
		if (!ava->la_value.bv_len) {
			return LDAP_INVALID_SYNTAX;
		}
384
	}
385
	rc = LDAP_SUCCESS;
386

387
388
389
390
391
	if ( do_sort ) {
		rc = AVA_Sort( rdn, iAVA );
	}

	return rc;
392
393
}

394
395
396
397
398
/*
 * In-place, schema-aware normalization / "pretty"ing of the
 * structural representation of a distinguished name.
 */
static int
Howard Chu's avatar
Howard Chu committed
399
LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx )
400
401
402
403
{
	int 		iRDN;
	int 		rc;

404
	assert( dn != NULL );
405

Howard Chu's avatar
Howard Chu committed
406
	for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
407
408
409
		rc = LDAPRDN_rewrite( dn[ iRDN ], flags, ctx );
		if ( rc != LDAP_SUCCESS ) {
			return rc;
410
411
412
413
414
415
416
417
		}
	}

	return LDAP_SUCCESS;
}

int
dnNormalize(
418
419
420
421
    slap_mask_t use,
    Syntax *syntax,
    MatchingRule *mr,
    struct berval *val,
Howard Chu's avatar
Howard Chu committed
422
423
    struct berval *out,
    void *ctx)
424
{
425
426
	assert( val != NULL );
	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 ) {
Howard Chu's avatar
Howard Chu committed
431
		LDAPDN		dn = NULL;
432
433
434
435
436
		int		rc;

		/*
		 * Go to structural representation
		 */
Howard Chu's avatar
Howard Chu committed
437
		rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
438
439
440
441
		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
442
443
		assert( strlen( val->bv_val ) == val->bv_len );

444
445
446
		/*
		 * Schema-aware rewrite
		 */
Howard Chu's avatar
Howard Chu committed
447
		if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
Howard Chu's avatar
Howard Chu committed
448
			ldap_dnfree_x( dn, ctx );
449
450
451
452
453
454
			return LDAP_INVALID_SYNTAX;
		}

		/*
		 * Back to string representation
		 */
Howard Chu's avatar
Howard Chu committed
455
456
		rc = ldap_dn2bv_x( dn, out,
			LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
457

Howard Chu's avatar
Howard Chu committed
458
		ldap_dnfree_x( dn, ctx );
459
460
461
462
463

		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}
	} else {
Howard Chu's avatar
Howard Chu committed
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
470
471

	return LDAP_SUCCESS;
}

472
473
474
475
476
477
478
479
480
int
rdnNormalize(
    slap_mask_t use,
    Syntax *syntax,
    MatchingRule *mr,
    struct berval *val,
    struct berval *out,
    void *ctx)
{
481
482
	assert( val != NULL );
	assert( out != NULL );
483

484
	Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val ? val->bv_val : "" );
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
	if ( val->bv_len != 0 ) {
		LDAPRDN		rdn = NULL;
		int		rc;
		char*		p;

		/*
		 * Go to structural representation
		 */
		rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
					LDAP_DN_FORMAT_LDAP, ctx);

		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}

		assert( strlen( val->bv_val ) == val->bv_len );

		/*
		 * Schema-aware rewrite
		 */
		if ( LDAPRDN_rewrite( rdn, 0, ctx ) != LDAP_SUCCESS ) {
			ldap_rdnfree_x( rdn, ctx );
			return LDAP_INVALID_SYNTAX;
		}

		/*
		 * Back to string representation
		 */
		rc = ldap_rdn2bv_x( rdn, out,
			LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );

		ldap_rdnfree_x( rdn, ctx );

		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}
	} else {
		ber_dupbv_x( out, val, ctx );
	}

525
	Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val ? out->bv_val : "" );
526
527
528
529

	return LDAP_SUCCESS;
}

530
531
int
dnPretty(
532
533
	Syntax *syntax,
	struct berval *val,
Howard Chu's avatar
Howard Chu committed
534
535
	struct berval *out,
	void *ctx)
536
{
537
538
	assert( val != NULL );
	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 ) {
Howard Chu's avatar
Howard Chu committed
543
		ber_dupbv_x( out, val, ctx );
544
545
546
547
548

	} else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
		return LDAP_INVALID_SYNTAX;

	} else {
Howard Chu's avatar
Howard Chu committed
549
		LDAPDN		dn = NULL;
550
551
552
		int		rc;

		/* FIXME: should be liberal in what we accept */
Howard Chu's avatar
Howard Chu committed
553
		rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
554
555
556
557
		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
558
559
		assert( strlen( val->bv_val ) == val->bv_len );

560
561
562
		/*
		 * Schema-aware rewrite
		 */
Howard Chu's avatar
Howard Chu committed
563
564
		if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
			ldap_dnfree_x( dn, ctx );
565
566
567
568
569
570
571
			return LDAP_INVALID_SYNTAX;
		}

		/* FIXME: not sure why the default isn't pretty */
		/* RE: the default is the form that is used as
		 * an internal representation; the pretty form
		 * is a variant */
Howard Chu's avatar
Howard Chu committed
572
573
		rc = ldap_dn2bv_x( dn, out,
			LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
574

Howard Chu's avatar
Howard Chu committed
575
		ldap_dnfree_x( dn, ctx );
576
577
578
579
580
581

		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}
	}

582
	Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "" );
583
584

	return LDAP_SUCCESS;
585
}
586

587
588
589
590
591
592
593
int
rdnPretty(
	Syntax *syntax,
	struct berval *val,
	struct berval *out,
	void *ctx)
{
594
595
	assert( val != NULL );
	assert( out != NULL );
596

597
	Debug( LDAP_DEBUG_TRACE, ">>> rdnPretty: <%s>\n", val->bv_val ? val->bv_val : "" );
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640

	if ( val->bv_len == 0 ) {
		ber_dupbv_x( out, val, ctx );

	} else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
		return LDAP_INVALID_SYNTAX;

	} else {
		LDAPRDN		rdn = NULL;
		int		rc;
		char*		p;

		/* FIXME: should be liberal in what we accept */
		rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
					LDAP_DN_FORMAT_LDAP, ctx);
		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}

		assert( strlen( val->bv_val ) == val->bv_len );

		/*
		 * Schema-aware rewrite
		 */
		if ( LDAPRDN_rewrite( rdn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
			ldap_rdnfree_x( rdn, ctx );
			return LDAP_INVALID_SYNTAX;
		}

		/* FIXME: not sure why the default isn't pretty */
		/* RE: the default is the form that is used as
		 * an internal representation; the pretty form
		 * is a variant */
		rc = ldap_rdn2bv_x( rdn, out,
			LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );

		ldap_rdnfree_x( rdn, ctx );

		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}
	}

641
	Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "" );
642
643
644
645
646

	return LDAP_SUCCESS;
}


647
648
649
650
int
dnPrettyNormalDN(
	Syntax *syntax,
	struct berval *val,
Howard Chu's avatar
Howard Chu committed
651
652
653
	LDAPDN *dn,
	int flags,
	void *ctx )
654
{
655
656
	assert( val != NULL );
	assert( dn != NULL );
657
658
659

	Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n", 
			flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal", 
660
			val->bv_val ? val->bv_val : "" );
661
662
663
664
665
666
667
668
669
670
671

	if ( val->bv_len == 0 ) {
		return LDAP_SUCCESS;

	} else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
		return LDAP_INVALID_SYNTAX;

	} else {
		int		rc;

		/* FIXME: should be liberal in what we accept */
Howard Chu's avatar
Howard Chu committed
672
		rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx );
673
674
675
676
677
678
679
680
681
		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}

		assert( strlen( val->bv_val ) == val->bv_len );

		/*
		 * Schema-aware rewrite
		 */
Howard Chu's avatar
Howard Chu committed
682
683
		if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) {
			ldap_dnfree_x( *dn, ctx );
684
685
686
687
688
689
			*dn = NULL;
			return LDAP_INVALID_SYNTAX;
		}
	}

	Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n", 
690
			flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal" );
691
692
693
694

	return LDAP_SUCCESS;
}

695
696
697
698
699
700
701
702
/*
 * Combination of both dnPretty and dnNormalize
 */
int
dnPrettyNormal(
	Syntax *syntax,
	struct berval *val,
	struct berval *pretty,
Howard Chu's avatar
Howard Chu committed
703
704
	struct berval *normal,
	void *ctx)
705
{
706
707
708
	assert( val != NULL );
	assert( pretty != NULL );
	assert( normal != NULL );
709
	Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val ? val->bv_val : "" );
710

711
	if ( val->bv_len == 0 ) {
Howard Chu's avatar
Howard Chu committed
712
713
		ber_dupbv_x( pretty, val, ctx );
		ber_dupbv_x( normal, val, ctx );
714
715
716
717
718
719

	} else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
		/* too big */
		return LDAP_INVALID_SYNTAX;

	} else {
Howard Chu's avatar
Howard Chu committed
720
		LDAPDN		dn = NULL;
721
722
723
724
725
726
727
728
		int		rc;

		pretty->bv_val = NULL;
		normal->bv_val = NULL;
		pretty->bv_len = 0;
		normal->bv_len = 0;

		/* FIXME: should be liberal in what we accept */
Howard Chu's avatar
Howard Chu committed
729
		rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
730
731
732
733
		if ( rc != LDAP_SUCCESS ) {
			return LDAP_INVALID_SYNTAX;
		}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
734
735
		assert( strlen( val->bv_val ) == val->bv_len );

736
737
738
		/*
		 * Schema-aware rewrite
		 */
Howard Chu's avatar
Howard Chu committed
739
740
		if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
			ldap_dnfree_x( dn, ctx );
741
742
743
			return LDAP_INVALID_SYNTAX;
		}

Howard Chu's avatar
Howard Chu committed
744
745
		rc = ldap_dn2bv_x( dn, pretty,
			LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
746
747

		if ( rc != LDAP_SUCCESS ) {
Howard Chu's avatar
Howard Chu committed
748
			ldap_dnfree_x( dn, ctx );
749
750
751
			return LDAP_INVALID_SYNTAX;
		}

Howard Chu's avatar
Howard Chu committed
752
753
754
		if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
			ldap_dnfree_x( dn, ctx );
			ber_memfree_x( pretty->bv_val, ctx );
755
756
757
758
759
			pretty->bv_val = NULL;
			pretty->bv_len = 0;
			return LDAP_INVALID_SYNTAX;
		}

Howard Chu's avatar
Howard Chu committed
760
761
		rc = ldap_dn2bv_x( dn, normal,
			LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
762

Howard Chu's avatar
Howard Chu committed
763
		ldap_dnfree_x( dn, ctx );
764
		if ( rc != LDAP_SUCCESS ) {
Howard Chu's avatar
Howard Chu committed
765
			ber_memfree_x( pretty->bv_val, ctx );
766
767
768
769
770
771
772
			pretty->bv_val = NULL;
			pretty->bv_len = 0;
			return LDAP_INVALID_SYNTAX;
		}
	}

	Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n",
773
		pretty->bv_val ? pretty->bv_val : "",
774
		normal->bv_val ? normal->bv_val : "" );
775
776
777
778

	return LDAP_SUCCESS;
}

779
/*
780
 * dnMatch routine
781
782
783
784
785
786
787
788
789
790
791
792
793
 */
int
dnMatch(
	int *matchp,
	slap_mask_t flags,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	int match;
	struct berval *asserted = (struct berval *) assertedValue;

794
795
796
	assert( matchp != NULL );
	assert( value != NULL );
	assert( assertedValue != NULL );
797
798
	assert( !BER_BVISNULL( value ) );
	assert( !BER_BVISNULL( asserted ) );
799
800
801
802
	
	match = value->bv_len - asserted->bv_len;

	if ( match == 0 ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
803
804
		match = memcmp( value->bv_val, asserted->bv_val, 
				value->bv_len );
805
806
807
808
	}

	Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
		match, value->bv_val, asserted->bv_val );
809

810
	*matchp = match;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
	return LDAP_SUCCESS;
}

/*
 * dnRelativeMatch routine
 */
int
dnRelativeMatch(
	int *matchp,
	slap_mask_t flags,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	int match;
	struct berval *asserted = (struct berval *) assertedValue;

829
830
831
	assert( matchp != NULL );
	assert( value != NULL );
	assert( assertedValue != NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
	assert( !BER_BVISNULL( value ) );
	assert( !BER_BVISNULL( asserted ) );

	if( mr == slap_schema.si_mr_dnSubtreeMatch ) {
		if( asserted->bv_len > value->bv_len ) {
			match = -1;
		} else if ( asserted->bv_len == value->bv_len ) {
			match = memcmp( value->bv_val, asserted->bv_val, 
				value->bv_len );
		} else {
			if( DN_SEPARATOR(
				value->bv_val[value->bv_len - asserted->bv_len - 1] ))
			{
				match = memcmp(
					&value->bv_val[value->bv_len - asserted->bv_len],
					asserted->bv_val, 
					asserted->bv_len );
			} else {
850
				match = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
851
852
853
			}
		}

854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
		*matchp = match;
		return LDAP_SUCCESS;
	}

	if( mr == slap_schema.si_mr_dnSuperiorMatch ) {
		asserted = value;
		value = (struct berval *) assertedValue;
		mr = slap_schema.si_mr_dnSubordinateMatch;
	}

	if( mr == slap_schema.si_mr_dnSubordinateMatch ) {
		if( asserted->bv_len >= value->bv_len ) {
			match = -1;
		} else {
			if( DN_SEPARATOR(
				value->bv_val[value->bv_len - asserted->bv_len - 1] ))
			{
				match = memcmp(
					&value->bv_val[value->bv_len - asserted->bv_len],
					asserted->bv_val, 
					asserted->bv_len );
			} else {
876
				match = 1;
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
			}
		}

		*matchp = match;
		return LDAP_SUCCESS;
	}

	if( mr == slap_schema.si_mr_dnOneLevelMatch ) {
		if( asserted->bv_len >= value->bv_len ) {
			match = -1;
		} else {
			if( DN_SEPARATOR(
				value->bv_val[value->bv_len - asserted->bv_len - 1] ))
			{
				match = memcmp(
					&value->bv_val[value->bv_len - asserted->bv_len],
					asserted->bv_val, 
					asserted->bv_len );

				if( !match ) {
					struct berval rdn;
					rdn.bv_val = value->bv_val;
					rdn.bv_len = value->bv_len - asserted->bv_len - 1;
					match = dnIsOneLevelRDN( &rdn ) ? 0 : 1;
				}
			} else {
903
				match = 1;
904
905
906
			}
		}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
907
908
909
910
		*matchp = match;
		return LDAP_SUCCESS;
	}

911
912
	/* should not be reachable */
	assert( 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
913
	return LDAP_OTHER;
914
915
}

916
917
918
919
920
921
922
923
924
925
926
927
int
rdnMatch(
	int *matchp,
	slap_mask_t flags,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	int match;
	struct berval *asserted = (struct berval *) assertedValue;

928
929
930
	assert( matchp != NULL );
	assert( value != NULL );
	assert( assertedValue != NULL );
931
932
933
934
935
936
937
938
	
	match = value->bv_len - asserted->bv_len;

	if ( match == 0 ) {
		match = memcmp( value->bv_val, asserted->bv_val, 
				value->bv_len );
	}

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
939
	Debug( LDAP_DEBUG_ARGS, "rdnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
940
941
942
		match, value->bv_val, asserted->bv_val );

	*matchp = match;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
943
	return LDAP_SUCCESS;
944
945
946
}


947
948
949
950
/*
 * dnParent - dn's parent, in-place
 * note: the incoming dn is assumed to be normalized/prettyfied,
 * so that escaped rdn/ava separators are in '\'+hexpair form
951
952
953
954
 *
 * note: "dn" and "pdn" can point to the same berval;
 * beware that, in this case, the pointer to the original buffer
 * will get lost.
955
 */
956
void
957
dnParent( 
958
959
	struct berval	*dn, 
	struct berval	*pdn )
960
{
Howard Chu's avatar
Howard Chu committed
961
	char	*p;
962

963
	p = ber_bvchr( dn, ',' );
964
965
966

	/* one-level dn */
	if ( p == NULL ) {
967
		pdn->bv_val = dn->bv_val + dn->bv_len;
968
		pdn->bv_len = 0;
969
		return;
970
971
	}

972
	assert( DN_SEPARATOR( p[ 0 ] ) );
973
974
975
	p++;

	assert( ATTR_LEADCHAR( p[ 0 ] ) );
976
	pdn->bv_len = dn->bv_len - (p - dn->bv_val);
977
	pdn->bv_val = p;
978

979
	return;
980
981
}

982
983
984
985
986
987
988
989
990
991
992
993
994
/*
 * dnRdn - dn's rdn, in-place
 * note: the incoming dn is assumed to be normalized/prettyfied,
 * so that escaped rdn/ava separators are in '\'+hexpair form
 */
void
dnRdn( 
	struct berval	*dn, 
	struct berval	*rdn )
{
	char	*p;

	*rdn = *dn;
995
	p = ber_bvchr( dn, ',' );
996
997
998
999
1000

	/* one-level dn */
	if ( p == NULL ) {
		return;
	}
For faster browsing, not all history is shown. View entire blame