schema_init.c 26.7 KB
Newer Older
1
2
3
/* schema_init.c - init builtin schema */
/* $OpenLDAP$ */
/*
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
 */

#include "portable.h"

#include <stdio.h>

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

#include "slap.h"
#include "ldap_pvt.h"

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
static int
dnValidate(
	Syntax *syntax,
	struct berval *in )
{
	int rc;
	char *dn;

	if( in->bv_len == 0 ) return LDAP_SUCCESS;

	dn = ch_strdup( in->bv_val );

	rc = dn_validate( dn ) == NULL
		? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;

	ch_free( dn );
	return rc;
}

static int
dnNormalize(
	Syntax *syntax,
	struct berval *val,
	struct berval **normalized )
{
	struct berval *out = ber_bvdup( val );

	if( out->bv_len != 0 ) {
		char *dn;
#ifdef USE_DN_NORMALIZE
		dn = dn_normalize( out->bv_val );
#else
		dn = dn_validate( out->bv_val );
#endif

		if( dn == NULL ) {
			ber_bvfree( out );
			return LDAP_INVALID_SYNTAX;
		}

		out->bv_val = dn;
		out->bv_len = strlen( dn );
	}

	*normalized = out;
	return LDAP_SUCCESS;
}

static int
dnMatch(
69
	int *matchp,
70
71
72
73
74
75
	unsigned use,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
76
	int match;
77
78
	struct berval *asserted = (struct berval *) assertedValue;
	
79
80
81
	match = value->bv_len - asserted->bv_len;

	if( match == 0 ) {
82
#ifdef USE_DN_NORMALIZE
83
		match = strcmp( value->bv_val, asserted->bv_val );
84
#else
85
		match = strcasecmp( value->bv_val, asserted->bv_val );
86
#endif
87
88
89
90
91
92
93
	}

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

	*matchp = match;
	return LDAP_SUCCESS;
94
95
}
	
96
97
98
99
100
101
102
103
104
static int
inValidate(
	Syntax *syntax,
	struct berval *in )
{
	/* any value allowed */
	return LDAP_OTHER;
}

105
static int
106
blobValidate(
107
108
109
110
	Syntax *syntax,
	struct berval *in )
{
	/* any value allowed */
111
	return LDAP_SUCCESS;
112
113
}

114
115
#define berValidate blobValidate

116
117
118
119
120
121
122
123
124
static int
UTF8StringValidate(
	Syntax *syntax,
	struct berval *in )
{
	ber_len_t count;
	int len;
	unsigned char *u = in->bv_val;

125
	for( count = in->bv_len; count > 0; count-=len, u+=len ) {
126
127
128
129
		/* get the length indicated by the first byte */
		len = LDAP_UTF8_CHARLEN( u );

		/* should not be zero */
130
		if( len == 0 ) return LDAP_INVALID_SYNTAX;
131
132
133

		/* make sure len corresponds with the offset
			to the next character */
134
		if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
135
136
	}

137
	if( count != 0 ) return LDAP_INVALID_SYNTAX;
138

139
	return LDAP_SUCCESS;
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
}

static int
UTF8StringNormalize(
	Syntax *syntax,
	struct berval *val,
	struct berval **normalized )
{
	struct berval *newval;
	char *p, *q, *s;

	newval = ch_malloc( sizeof( struct berval ) );

	p = val->bv_val;

	/* Ignore initial whitespace */
	while ( ldap_utf8_isspace( p ) ) {
		LDAP_UTF8_INCR( p );
	}

160
	if( *p == '\0' ) {
161
		ch_free( newval );
162
		return LDAP_INVALID_SYNTAX;
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
	}

	newval->bv_val = ch_strdup( p );
	p = q = newval->bv_val;
	s = NULL;

	while ( *p ) {
		int len;

		if ( ldap_utf8_isspace( p ) ) {
			len = LDAP_UTF8_COPY(q,p);
			s=q;
			p+=len;
			q+=len;

			/* Ignore the extra whitespace */
			while ( ldap_utf8_isspace( p ) ) {
				LDAP_UTF8_INCR( p );
			}
		} else {
			len = LDAP_UTF8_COPY(q,p);
			s=NULL;
			p+=len;
			q+=len;
		}
	}

	assert( *newval->bv_val );
	assert( newval->bv_val < p );
	assert( p <= q );

	/* cannot start with a space */
	assert( !ldap_utf8_isspace(newval->bv_val) );

	/*
	 * If the string ended in space, backup the pointer one
	 * position.  One is enough because the above loop collapsed
	 * all whitespace to a single space.
	 */

	if ( s != NULL ) {
		q = s;
	}

	/* cannot end with a space */
	assert( !ldap_utf8_isspace( LDAP_UTF8_PREV(q) ) );

	/* null terminate */
	*q = '\0';

	newval->bv_len = q - newval->bv_val;
214
	*normalized = newval;
215

216
	return LDAP_SUCCESS;
217
218
}

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
static int
oidValidate(
	Syntax *syntax,
	struct berval *val )
{
	ber_len_t i;

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

	if( isdigit(val->bv_val[0]) ) {
		int dot = 0;
		for(i=1; i < val->bv_len; i++) {
			if( val->bv_val[i] == '.' ) {
				if( dot++ ) return 1;
			} else if ( isdigit(val->bv_val[i]) ) {
				dot = 0;
			} else {
236
				return LDAP_INVALID_SYNTAX;
237
238
239
			}
		}

240
		return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
241
242
243
244

	} else if( isalpha(val->bv_val[0]) ) {
		for(i=1; i < val->bv_len; i++) {
			if( !isalpha(val->bv_val[i] ) ) {
245
				return LDAP_INVALID_SYNTAX;
246
247
248
			}
		}

249
		return LDAP_SUCCESS;
250
251
	}
	
252
	return LDAP_INVALID_SYNTAX;
253
254
}

255
256
257
258
259
260
261
262
static int
integerValidate(
	Syntax *syntax,
	struct berval *val )
{
	ber_len_t i;

	for(i=0; i < val->bv_len; i++) {
263
		if( !isdigit(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
264
265
	}

266
	return LDAP_SUCCESS;
267
268
269
270
271
272
273
274
275
276
}

static int
printableStringValidate(
	Syntax *syntax,
	struct berval *val )
{
	ber_len_t i;

	for(i=0; i < val->bv_len; i++) {
277
		if( !isprint(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
278
279
	}

280
	return LDAP_SUCCESS;
281
282
}

283
static int
284
285
286
287
288
289
290
IA5StringValidate(
	Syntax *syntax,
	struct berval *val )
{
	ber_len_t i;

	for(i=0; i < val->bv_len; i++) {
291
		if( !isascii(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
292
293
	}

294
	return LDAP_SUCCESS;
295
296
297
298
299
300
301
302
}

static int
IA5StringConvert(
	Syntax *syntax,
	struct berval *in,
	struct berval **out )
{
303
304
	ldap_unicode_t *u;
	ber_len_t i, len = in->bv_len;
305
306
	struct berval *bv = ch_malloc( sizeof(struct berval) );

307
308
309
310
	bv->bv_len = len * sizeof( ldap_unicode_t );
	bv->bv_val = (char *) u = ch_malloc( bv->bv_len + sizeof( ldap_unicode_t ) );;

	for(i=0; i < len; i++ ) {
311
312
313
314
		/*
		 * IA5StringValidate should have been called to ensure
		 * input is limited to IA5.
		 */
315
		u[i] = in->bv_val[i];
316
	}
317
	u[i] = 0;
318
319

	*out = bv;
320
	return LDAP_SUCCESS;
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
}

static int
IA5StringNormalize(
	Syntax *syntax,
	struct berval *val,
	struct berval **normalized )
{
	struct berval *newval;
	char *p, *q;

	newval = ch_malloc( sizeof( struct berval ) );

	p = val->bv_val;

	/* Ignore initial whitespace */
	while ( isspace( *p++ ) ) {
		/* EMPTY */  ;
	}

341
	if( *p != '\0' ) {
342
		ch_free( newval );
343
		return LDAP_INVALID_SYNTAX;
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
380
381
382
383
384
385
	}

	newval->bv_val = ch_strdup( p );
	p = q = newval->bv_val;

	while ( *p ) {
		if ( isspace( *p ) ) {
			*q++ = *p++;

			/* Ignore the extra whitespace */
			while ( isspace( *p++ ) ) {
				/* EMPTY */  ;
			}
		} else {
			*q++ = *p++;
		}
	}

	assert( *newval->bv_val );
	assert( newval->bv_val < p );
	assert( p <= q );

	/* cannot start with a space */
	assert( !isspace(*newval->bv_val) );

	/*
	 * If the string ended in space, backup the pointer one
	 * position.  One is enough because the above loop collapsed
	 * all whitespace to a single space.
	 */

	if ( isspace( q[-1] ) ) {
		--q;
	}

	/* cannot end with a space */
	assert( !isspace( q[-1] ) );

	/* null terminate */
	*q = '\0';

	newval->bv_len = q - newval->bv_val;
386
	*normalized = newval;
387

388
	return LDAP_SUCCESS;
389
390
391
392
}

static int
caseExactIA5Match(
393
	int *match,
394
	unsigned use,
395
396
397
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
398
	void *assertedValue )
399
{
400
	*match = strcmp( value->bv_val,
401
		((struct berval *) assertedValue)->bv_val );
402
	return LDAP_SUCCESS;
403
404
}

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
#ifdef SLAPD_SCHEMA_NOT_COMPAT
static int
caseExactIA5SubstringsMatch(
	int *matchp,
	unsigned use,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	int match = 0;
	SubstringsAssertion *sub = assertedValue;
	struct berval left = *value;
	int i;
	ber_len_t inlen=0;

	if( sub->sa_initial ) {
		inlen += sub->sa_initial->bv_len;
	}
	if( sub->sa_any ) {
		for(i=0; sub->sa_any[i]; i++) {
			inlen += sub->sa_final->bv_len;
		}
	}
	if( sub->sa_final ) {
		inlen += sub->sa_final->bv_len;
	}

	if( inlen > value->bv_len ) {
		match = 1;
		goto done;
	}

	if( sub->sa_initial ) {
		match = strncmp( sub->sa_initial->bv_val, left.bv_val,
			sub->sa_initial->bv_len );

		if( match != 0 ) {
			goto done;
		}

		left.bv_val += sub->sa_initial->bv_len;
		left.bv_len -= sub->sa_initial->bv_len;
448
		inlen -= sub->sa_initial->bv_len;
449
450
451
452
453
454
455
456
457
458
459
460
	}

	if( sub->sa_final ) {
		match = strncmp( sub->sa_final->bv_val,
			&left.bv_val[left.bv_len - sub->sa_final->bv_len],
			sub->sa_final->bv_len );

		if( match != 0 ) {
			goto done;
		}

		left.bv_len -= sub->sa_final->bv_len;
461
		inlen -= sub->sa_initial->bv_len;
462
463
464
	}

	if( sub->sa_any ) {
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
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
		for(i=0; sub->sa_any[i]; i++) {
			ber_len_t idx;
			char *p;

retry:
			if( inlen < left.bv_len ) {
				/* not enough length */
				match = 1;
				goto done;
			}

			if( sub->sa_any[i]->bv_len == 0 ) {
				continue;
			}

			p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );

			if( p == NULL ) {
				match = 1;
				goto done;
			}

			idx = p - left.bv_val;
			assert( idx < left.bv_len );

			if( idx >= left.bv_len ) {
				/* this shouldn't happen */
				return LDAP_OTHER;
			}

			left.bv_val = p;
			left.bv_len -= idx;

			if( sub->sa_any[i]->bv_len > left.bv_len ) {
				/* not enough left */
				match = 1;
				goto done;
			}

			match = strncmp( left.bv_val,
				sub->sa_any[i]->bv_val,
				sub->sa_any[i]->bv_len );


			if( match != 0 ) {
				goto retry;
			}

			left.bv_val += sub->sa_any[i]->bv_len;
			left.bv_len -= sub->sa_any[i]->bv_len;
		}
516
517
518
519
520
521
522
523
	}

done:
	*matchp = match;
	return LDAP_SUCCESS;
}
#endif

524
525
static int
caseIgnoreIA5Match(
526
	int *match,
527
	unsigned use,
528
529
530
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
531
	void *assertedValue )
532
{
533
	*match = strcasecmp( value->bv_val,
534
		((struct berval *) assertedValue)->bv_val );
535
	return LDAP_SUCCESS;
536
537
}

538
#ifdef SLAPD_SCHEMA_NOT_COMPAT
539
540
541
542
543
544
545
546
547
548
549
550
551
552
static char *strcasechr( const char *str, int c )
{
	char *lower = strchr( str, TOLOWER(c) );
	char *upper = strchr( str, TOUPPER(c) );

	if( lower && upper ) {
		return lower < upper ? lower : upper;
	} else if ( lower ) {
		return lower;
	} else {
		return upper;
	}
}

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
static int
caseIgnoreIA5SubstringsMatch(
	int *matchp,
	unsigned use,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	int match = 0;
	SubstringsAssertion *sub = assertedValue;
	struct berval left = *value;
	int i;
	ber_len_t inlen=0;

	if( sub->sa_initial ) {
		inlen += sub->sa_initial->bv_len;
	}
	if( sub->sa_any ) {
		for(i=0; sub->sa_any[i]; i++) {
			inlen += sub->sa_final->bv_len;
		}
	}
	if( sub->sa_final ) {
		inlen += sub->sa_final->bv_len;
	}

	if( inlen > value->bv_len ) {
		match = 1;
		goto done;
	}

	if( sub->sa_initial ) {
		match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
			sub->sa_initial->bv_len );

		if( match != 0 ) {
			goto done;
		}

		left.bv_val += sub->sa_initial->bv_len;
		left.bv_len -= sub->sa_initial->bv_len;
	}

	if( sub->sa_final ) {
		match = strncasecmp( sub->sa_final->bv_val,
			&left.bv_val[left.bv_len - sub->sa_final->bv_len],
			sub->sa_final->bv_len );

		if( match != 0 ) {
			goto done;
		}

		left.bv_len -= sub->sa_final->bv_len;
	}

	if( sub->sa_any ) {
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
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
		for(i=0; sub->sa_any[i]; i++) {
			ber_len_t idx;
			char *p;

retry:
			if( inlen < left.bv_len ) {
				/* not enough length */
				match = 1;
				goto done;
			}

			if( sub->sa_any[i]->bv_len == 0 ) {
				continue;
			}

			p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );

			if( p == NULL ) {
				match = 1;
				goto done;
			}

			idx = p - left.bv_val;
			assert( idx < left.bv_len );

			if( idx >= left.bv_len ) {
				/* this shouldn't happen */
				return LDAP_OTHER;
			}

			left.bv_val = p;
			left.bv_len -= idx;

			if( sub->sa_any[i]->bv_len > left.bv_len ) {
				/* not enough left */
				match = 1;
				goto done;
			}

			match = strncasecmp( left.bv_val,
				sub->sa_any[i]->bv_val,
				sub->sa_any[i]->bv_len );


			if( match != 0 ) {
				goto retry;
			}

			left.bv_val += sub->sa_any[i]->bv_len;
			left.bv_len -= sub->sa_any[i]->bv_len;
		}
661
662
663
664
665
666
	}

done:
	*matchp = match;
	return LDAP_SUCCESS;
}
667
#endif
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

static int
NumericStringNormalize(
	Syntax *syntax,
	struct berval *val,
	struct berval **normalized )
{
	/* similiar to IA5StringNormalize except removes all spaces */
	struct berval *newval;
	char *p, *q;

	newval = ch_malloc( sizeof( struct berval ) );

	p = val->bv_val;

	/* Ignore initial whitespace */
	while ( isspace( *p++ ) ) {
		/* EMPTY */  ;
	}

	if( *p != '\0' ) {
		ch_free( newval );
		return LDAP_INVALID_SYNTAX;
	}

	newval->bv_val = ch_strdup( p );
	p = q = newval->bv_val;

	while ( *p ) {
		if ( isspace( *p ) ) {
			/* Ignore whitespace */
			p++;
		} else {
			*q++ = *p++;
		}
	}

	assert( *newval->bv_val );
	assert( newval->bv_val < p );
	assert( p <= q );

	/* cannot start with a space */
	assert( !isspace(*newval->bv_val) );

	/* cannot end with a space */
	assert( !isspace( q[-1] ) );

	/* null terminate */
	*q = '\0';

	newval->bv_len = q - newval->bv_val;
	*normalized = newval;

	return LDAP_SUCCESS;
}

724
725
struct syntax_defs_rec {
	char *sd_desc;
726
	int sd_flags;
727
	slap_syntax_validate_func *sd_validate;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
728
729
730
	slap_syntax_transform_func *sd_normalize;
	slap_syntax_transform_func *sd_pretty;
#ifdef SLAPD_BINARY_CONVERSION
731
732
	slap_syntax_transform_func *sd_ber2str;
	slap_syntax_transform_func *sd_str2ber;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
733
#endif
734
735
};

736
#define X_HIDE "X-HIDE 'TRUE' "
737
738
#define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
#define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
739

740
struct syntax_defs_rec syntax_defs[] = {
741
742
743
744
	{"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
		SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
	{"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
		0, NULL, NULL, NULL},
745
	{"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
746
		0, NULL, NULL, NULL},
747
748
749
750
	{"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
		SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
	{"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_BINARY X_NOT_H_R ")",
		SLAP_SYNTAX_BER, berValidate, NULL, NULL},
751
	{"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
752
		0, NULL, NULL, NULL},
753
	{"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
754
		0, NULL, NULL, NULL},
755
756
757
758
759
760
	{"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
		X_BINARY X_NOT_H_R ")",
		SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
	{"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
		X_BINARY X_NOT_H_R ")",
		SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
Kurt Zeilenga's avatar
Kurt Zeilenga committed
761
762
	{"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
		X_BINARY X_NOT_H_R ")",
763
		SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
764
765
	{"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
		0, NULL, NULL, NULL},
766
767
	{"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
		0, dnValidate, dnNormalize, NULL},
768
	{"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
769
		0, NULL, NULL, NULL},
770
	{"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
771
		0, NULL, NULL, NULL},
772
	{"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
773
		0, UTF8StringValidate, UTF8StringNormalize, NULL},
774
	{"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
775
		0, NULL, NULL, NULL},
776
	{"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
777
		0, NULL, NULL, NULL},
778
	{"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
779
		0, NULL, NULL, NULL},
780
	{"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
781
		0, NULL, NULL, NULL},
782
	{"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
783
		0, NULL, NULL, NULL},
784
	{"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
785
		0, blobValidate, NULL, NULL},
786
787
	{"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
		SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
788
	{"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
789
		0, NULL, NULL, NULL},
790
	{"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
791
		0, NULL, NULL, NULL},
792
	{"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
793
		0, IA5StringValidate, IA5StringNormalize, NULL},
794
	{"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
795
		0, integerValidate, NULL, NULL},
796
797
	{"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
		SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
798
	{"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
799
		0, NULL, NULL, NULL},
800
	{"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
801
		0, NULL, NULL, NULL},
802
	{"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
803
		0, NULL, NULL, NULL},
804
	{"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
805
		0, NULL, NULL, NULL},
806
	{"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
807
		0, NULL, NULL, NULL},
808
	{"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
809
		0, NULL, NULL, NULL},
810
	{"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
811
		0, NULL, NULL, NULL},
812
	{"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
813
		0, IA5StringValidate, NumericStringNormalize, NULL},
814
	{"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
815
		0, NULL, NULL, NULL},
816
	{"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
817
		0, oidValidate, NULL, NULL},
818
	{"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
819
		0, NULL, NULL, NULL},
820
	{"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
821
		0, blobValidate, NULL, NULL},
822
	{"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
823
		0, blobValidate, NULL, NULL},
824
	{"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
825
		0, NULL, NULL, NULL},
826
	{"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
827
		0, NULL, NULL, NULL},
828
	{"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
829
		0, printableStringValidate, NULL, NULL},
830
831
832
	{"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
		X_BINARY X_NOT_H_R ")",
		SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
833
	{"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
834
		0, blobValidate, NULL, NULL},
835
836
837
838
839
	{"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
		0, NULL, NULL, NULL},
	{"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
		0, NULL, NULL, NULL},
	{"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
840
		0, NULL, NULL, NULL},
841
	{"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
842
		0, NULL, NULL, NULL},
843
	{"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
844
		0, NULL, NULL, NULL},
845
	{"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
846
		0, NULL, NULL, NULL},
847
	{"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
848
		0, NULL, NULL, NULL},
849
	{"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
850
		0, NULL, NULL, NULL},
851

852
	/* OpenLDAP Experimental Syntaxes */
853
	{"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
854
		0, NULL, NULL, NULL},
855
856
857
858
859
860
	{"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
		0, NULL, NULL, NULL},
	{"( 1.3.6.1.4.1.4203.666.2.3 DESC 'OpenLDAP void' " X_HIDE ")" ,
		SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
	{"( 1.3.6.1.4.1.4203.666.2.4 DESC 'OpenLDAP DN' " X_HIDE ")" ,
		SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
861

862
	{NULL, 0, NULL, NULL, NULL}
863
864
865
};

struct mrule_defs_rec {
866
	char *						mrd_desc;
867
	unsigned					mrd_usage;
868
869
870
871
872
	slap_mr_convert_func *		mrd_convert;
	slap_mr_normalize_func *	mrd_normalize;
	slap_mr_match_func *		mrd_match;
	slap_mr_indexer_func *		mrd_indexer;
	slap_mr_filter_func *		mrd_filter;
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
};

/*
 * Other matching rules in X.520 that we do not use:
 *
 * 2.5.13.9		numericStringOrderingMatch
 * 2.5.13.13	booleanMatch
 * 2.5.13.15	integerOrderingMatch
 * 2.5.13.18	octetStringOrderingMatch
 * 2.5.13.19	octetStringSubstringsMatch
 * 2.5.13.25	uTCTimeMatch
 * 2.5.13.26	uTCTimeOrderingMatch
 * 2.5.13.31	directoryStringFirstComponentMatch
 * 2.5.13.32	wordMatch
 * 2.5.13.33	keywordMatch
 * 2.5.13.34	certificateExactMatch
 * 2.5.13.35	certificateMatch
 * 2.5.13.36	certificatePairExactMatch
 * 2.5.13.37	certificatePairMatch
 * 2.5.13.38	certificateListExactMatch
 * 2.5.13.39	certificateListMatch
 * 2.5.13.40	algorithmIdentifierMatch
 * 2.5.13.41	storedPrefixMatch
 * 2.5.13.42	attributeCertificateMatch
 * 2.5.13.43	readerAndKeyIDMatch
 * 2.5.13.44	attributeIntegrityMatch
 */

901
902
903
904
905
#ifndef SLAPD_SCHEMA_NOT_COMPAT
#define caseIgnoreIA5SubstringsMatch NULL
#define caseExactIA5SubstringsMatch NULL
#endif

906
907
/* recycled matching functions */
#define caseIgnoreMatch caseIgnoreIA5Match
908
909
#define caseIgnoreOrderingMatch caseIgnoreMatch
#define caseIgnoreSubstringsMatch caseIgnoreIA5SubstringsMatch
910
#define caseExactMatch caseExactIA5Match
911
912
#define caseExactOrderingMatch caseExactMatch
#define caseExactSubstringsMatch caseExactIA5SubstringsMatch
913
914
915
916

/* unimplemented matching functions */
#define objectIdentifierMatch NULL
#define caseIgnoreListMatch NULL
Kurt Zeilenga's avatar
Kurt Zeilenga committed
917
#define caseIgnoreListSubstringsMatch NULL
918
919
920
921
922
923
924
925
926
927
928
929
930
#define integerMatch NULL
#define bitStringMatch NULL
#define octetStringMatch NULL
#define telephoneNumberMatch NULL
#define telephoneNumberSubstringsMatch NULL
#define presentationAddressMatch NULL
#define uniqueMemberMatch NULL
#define protocolInformationMatch NULL
#define generalizedTimeMatch NULL
#define generalizedTimeOrderingMatch NULL
#define integerFirstComponentMatch NULL
#define objectIdentifierFirstComponentMatch NULL

931
932
933
#define OpenLDAPaciMatch NULL
#define authPasswordMatch NULL

934
935
936
struct mrule_defs_rec mrule_defs[] = {
	{"( 2.5.13.0 NAME 'objectIdentifierMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
937
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
938
		NULL, NULL, objectIdentifierMatch, NULL, NULL},
939
940
941

	{"( 2.5.13.1 NAME 'distinguishedNameMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
942
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
943
		NULL, NULL, dnMatch, NULL, NULL},
944
945
946

	{"( 2.5.13.2 NAME 'caseIgnoreMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
947
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
948
		NULL, NULL, caseIgnoreMatch, NULL, NULL},
949
950
951

	{"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
952
		SLAP_MR_ORDERING,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
953
		NULL, NULL, caseIgnoreOrderingMatch, NULL, NULL},
954
955
956

	{"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
957
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
958
		NULL, NULL, caseIgnoreSubstringsMatch, NULL, NULL},
959
960
961
962

	/* Next three are not in the RFC's, but are needed for compatibility */
	{"( 2.5.13.5 NAME 'caseExactMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
963
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
964
		NULL, NULL, caseExactMatch, NULL, NULL},
965
966
967

	{"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
968
		SLAP_MR_ORDERING,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
969
		NULL, NULL, caseExactOrderingMatch, NULL, NULL},
970
971
972

	{"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
973
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
974
		NULL, NULL, caseExactSubstringsMatch, NULL, NULL},
975
976
977

	{"( 2.5.13.8 NAME 'numericStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
978
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
979
		NULL, NULL, caseIgnoreIA5Match, NULL, NULL},
980
981
982

	{"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
983
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
984
		NULL, NULL, caseIgnoreIA5SubstringsMatch, NULL, NULL},
985
986
987

	{"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
988
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
989
		NULL, NULL, caseIgnoreListMatch, NULL, NULL},
990

Kurt Zeilenga's avatar
Kurt Zeilenga committed
991
992
993
994
995
	{"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
		NULL, NULL, caseIgnoreListSubstringsMatch, NULL, NULL},

996
997
	{"( 2.5.13.14 NAME 'integerMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
998
		SLAP_MR_NONE | SLAP_MR_EXT,
999
		NULL, NULL, integerMatch, NULL, NULL},
1000
1001
1002

	{"( 2.5.13.16 NAME 'bitStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
1003
		SLAP_MR_NONE | SLAP_MR_EXT,
1004
		NULL, NULL, bitStringMatch, NULL, NULL},
1005
1006
1007

	{"( 2.5.13.17 NAME 'octetStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
1008
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
1009
		NULL, NULL, octetStringMatch, NULL, NULL},
1010
1011
1012

	{"( 2.5.13.20 NAME 'telephoneNumberMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
1013
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
1014
		NULL, NULL, telephoneNumberMatch, NULL, NULL},
1015
1016
1017

	{"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
1018
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
1019
		NULL, NULL, telephoneNumberSubstringsMatch, NULL, NULL},
1020
1021
1022

	{"( 2.5.13.22 NAME 'presentationAddressMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
1023
		SLAP_MR_NONE | SLAP_MR_EXT,
1024
		NULL, NULL, presentationAddressMatch, NULL, NULL},
1025
1026
1027

	{"( 2.5.13.23 NAME 'uniqueMemberMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
1028
		SLAP_MR_NONE | SLAP_MR_EXT,
1029
		NULL, NULL, uniqueMemberMatch, NULL, NULL},
1030
1031
1032

	{"( 2.5.13.24 NAME 'protocolInformationMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
1033
		SLAP_MR_NONE | SLAP_MR_EXT,
1034
		NULL, NULL, protocolInformationMatch, NULL, NULL},
1035
1036
1037

	{"( 2.5.13.27 NAME 'generalizedTimeMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
1038
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
1039
		NULL, NULL, generalizedTimeMatch, NULL, NULL},
1040
1041
1042

	{"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
1043
		SLAP_MR_ORDERING,
1044
		NULL, NULL, generalizedTimeOrderingMatch, NULL, NULL},
1045
1046
1047

	{"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
1048
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
1049
		NULL, NULL, integerFirstComponentMatch, NULL, NULL},
1050
1051
1052

	{"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
1053
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
1054
		NULL, NULL, objectIdentifierFirstComponentMatch, NULL, NULL},
1055
1056
1057

	{"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
1058
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1059
		NULL, NULL, caseExactIA5Match, NULL, NULL},
1060
1061
1062

	{"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
1063
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1064
		NULL, NULL, caseIgnoreIA5Match, NULL, NULL},
1065
1066
1067

	{"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
1068
		SLAP_MR_SUBSTR,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1069
		NULL, NULL, caseIgnoreIA5SubstringsMatch, NULL, NULL},
1070

1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
	{"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
		SLAP_MR_EQUALITY,
		NULL, NULL, authPasswordMatch, NULL, NULL},

	{"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
		"SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
		SLAP_MR_EQUALITY,
		NULL, NULL, OpenLDAPaciMatch, NULL, NULL},

1081
	{NULL, SLAP_MR_NONE, NULL, NULL, NULL}
1082
1083
1084
1085
1086
1087
1088
1089
};

int
schema_init( void )
{
	int		res;
	int		i;

1090
1091
	/* we should only be called once (from main) */
	assert( schema_init_done == 0 );
1092
1093
1094

	for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
		res = register_syntax( syntax_defs[i].sd_desc,
1095
		    syntax_defs[i].sd_flags,
1096
		    syntax_defs[i].sd_validate,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1097
1098
1099
1100
		    syntax_defs[i].sd_normalize,
			syntax_defs[i].sd_pretty
#ifdef SLAPD_BINARY_CONVERSION
			,
1101
		    syntax_defs[i].sd_ber2str,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1102
1103
1104
			syntax_defs[i].sd_str2ber
#endif
		);
1105
1106
1107
1108

		if ( res ) {
			fprintf( stderr, "schema_init: Error registering syntax %s\n",
				 syntax_defs[i].sd_desc );
1109
			return LDAP_OTHER;
1110
1111
1112
1113
		}
	}

	for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
1114
1115
1116
1117
1118
1119
1120
		if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
			fprintf( stderr,
				"schema_init: Ingoring unusable matching rule %s\n",
				 mrule_defs[i].mrd_desc );
			continue;
		}

1121
1122
		res = register_matching_rule(
			mrule_defs[i].mrd_desc,
1123
			mrule_defs[i].mrd_usage,
1124
1125
			mrule_defs[i].mrd_convert,
			mrule_defs[i].mrd_normalize,
1126
1127
1128
		    mrule_defs[i].mrd_match,
			mrule_defs[i].mrd_indexer,
			mrule_defs[i].mrd_filter );
1129
1130
1131
1132
1133

		if ( res ) {
			fprintf( stderr,
				"schema_init: Error registering matching rule %s\n",
				 mrule_defs[i].mrd_desc );
1134
			return LDAP_OTHER;
1135
1136
1137
		}
	}
	schema_init_done = 1;
1138
	return LDAP_SUCCESS;
1139
}