schema_init.c 25.2 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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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(
	int *match,
	unsigned use,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	struct berval *asserted = (struct berval *) assertedValue;
	ber_slen_t diff;
	
	diff = value->bv_len - asserted->bv_len;
	if( diff ) return diff;
	
#ifdef USE_DN_NORMALIZE
	return strcmp( value->bv_val, asserted->bv_val );
#else
	return strcasecmp( value->bv_val, asserted->bv_val );
#endif
}
	
89
90
91
92
93
94
95
96
97
static int
inValidate(
	Syntax *syntax,
	struct berval *in )
{
	/* any value allowed */
	return LDAP_OTHER;
}

98
static int
99
blobValidate(
100
101
102
103
	Syntax *syntax,
	struct berval *in )
{
	/* any value allowed */
104
	return LDAP_SUCCESS;
105
106
}

107
108
#define berValidate blobValidate

109
110
111
112
113
114
115
116
117
static int
UTF8StringValidate(
	Syntax *syntax,
	struct berval *in )
{
	ber_len_t count;
	int len;
	unsigned char *u = in->bv_val;

118
	for( count = in->bv_len; count > 0; count-=len, u+=len ) {
119
120
121
122
		/* get the length indicated by the first byte */
		len = LDAP_UTF8_CHARLEN( u );

		/* should not be zero */
123
		if( len == 0 ) return LDAP_INVALID_SYNTAX;
124
125
126

		/* make sure len corresponds with the offset
			to the next character */
127
		if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
128
129
	}

130
	if( count != 0 ) return LDAP_INVALID_SYNTAX;
131

132
	return LDAP_SUCCESS;
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
}

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 );
	}

153
	if( *p == '\0' ) {
154
		ch_free( newval );
155
		return LDAP_INVALID_SYNTAX;
156
157
158
159
160
161
162
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
	}

	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;
207
	*normalized = newval;
208

209
	return LDAP_SUCCESS;
210
211
}

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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 {
229
				return LDAP_INVALID_SYNTAX;
230
231
232
			}
		}

233
		return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
234
235
236
237

	} else if( isalpha(val->bv_val[0]) ) {
		for(i=1; i < val->bv_len; i++) {
			if( !isalpha(val->bv_val[i] ) ) {
238
				return LDAP_INVALID_SYNTAX;
239
240
241
			}
		}

242
		return LDAP_SUCCESS;
243
244
	}
	
245
	return LDAP_INVALID_SYNTAX;
246
247
}

248
249
250
251
252
253
254
255
static int
integerValidate(
	Syntax *syntax,
	struct berval *val )
{
	ber_len_t i;

	for(i=0; i < val->bv_len; i++) {
256
		if( !isdigit(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
257
258
	}

259
	return LDAP_SUCCESS;
260
261
262
263
264
265
266
267
268
269
}

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

	for(i=0; i < val->bv_len; i++) {
270
		if( !isprint(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
271
272
	}

273
	return LDAP_SUCCESS;
274
275
}

276
static int
277
278
279
280
281
282
283
IA5StringValidate(
	Syntax *syntax,
	struct berval *val )
{
	ber_len_t i;

	for(i=0; i < val->bv_len; i++) {
284
		if( !isascii(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
285
286
	}

287
	return LDAP_SUCCESS;
288
289
290
291
292
293
294
295
}

static int
IA5StringConvert(
	Syntax *syntax,
	struct berval *in,
	struct berval **out )
{
296
297
	ldap_unicode_t *u;
	ber_len_t i, len = in->bv_len;
298
299
	struct berval *bv = ch_malloc( sizeof(struct berval) );

300
301
302
303
	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++ ) {
304
305
306
307
		/*
		 * IA5StringValidate should have been called to ensure
		 * input is limited to IA5.
		 */
308
		u[i] = in->bv_val[i];
309
	}
310
	u[i] = 0;
311
312

	*out = bv;
313
	return LDAP_SUCCESS;
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
}

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 */  ;
	}

334
	if( *p != '\0' ) {
335
		ch_free( newval );
336
		return LDAP_INVALID_SYNTAX;
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
	}

	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;
379
	*normalized = newval;
380

381
	return LDAP_SUCCESS;
382
383
384
385
}

static int
caseExactIA5Match(
386
	int *match,
387
	unsigned use,
388
389
390
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
391
	void *assertedValue )
392
{
393
	*match = strcmp( value->bv_val,
394
		((struct berval *) assertedValue)->bv_val );
395
	return LDAP_SUCCESS;
396
397
}

398
399
400
401
402
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
#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;
441
		inlen -= sub->sa_initial->bv_len;
442
443
444
445
446
447
448
449
450
451
452
453
	}

	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;
454
		inlen -= sub->sa_initial->bv_len;
455
456
457
	}

	if( sub->sa_any ) {
458
459
460
461
462
463
464
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
		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;
		}
509
510
511
512
513
514
515
516
	}

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

517
518
static int
caseIgnoreIA5Match(
519
	int *match,
520
	unsigned use,
521
522
523
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
524
	void *assertedValue )
525
{
526
	*match = strcasecmp( value->bv_val,
527
		((struct berval *) assertedValue)->bv_val );
528
	return LDAP_SUCCESS;
529
530
}

531
#ifdef SLAPD_SCHEMA_NOT_COMPAT
532
533
534
535
536
537
538
539
540
541
542
543
544
545
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;
	}
}

546
547
548
549
550
551
552
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
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 ) {
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
641
642
643
644
645
646
647
648
649
650
651
652
653
		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;
		}
654
655
656
657
658
659
660
661
	}

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

662
663
struct syntax_defs_rec {
	char *sd_desc;
664
	int sd_flags;
665
	slap_syntax_validate_func *sd_validate;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
666
667
668
	slap_syntax_transform_func *sd_normalize;
	slap_syntax_transform_func *sd_pretty;
#ifdef SLAPD_BINARY_CONVERSION
669
670
	slap_syntax_transform_func *sd_ber2str;
	slap_syntax_transform_func *sd_str2ber;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
671
#endif
672
673
};

674
#define X_HIDE "X-HIDE 'TRUE' "
675
676
#define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
#define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
677

678
struct syntax_defs_rec syntax_defs[] = {
679
680
681
682
	{"( 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},
683
	{"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
684
		0, NULL, NULL, NULL},
685
686
687
688
	{"( 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},
689
	{"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
690
		0, NULL, NULL, NULL},
691
	{"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
692
		0, NULL, NULL, NULL},
693
694
695
696
697
698
	{"( 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
699
700
	{"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
		X_BINARY X_NOT_H_R ")",
701
		SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
702
703
	{"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
		0, NULL, NULL, NULL},
704
705
	{"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
		0, dnValidate, dnNormalize, NULL},
706
	{"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
707
		0, NULL, NULL, NULL},
708
	{"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
709
		0, NULL, NULL, NULL},
710
	{"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
711
		0, UTF8StringValidate, UTF8StringNormalize, NULL},
712
	{"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
713
		0, NULL, NULL, NULL},
714
	{"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
715
		0, NULL, NULL, NULL},
716
	{"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
717
		0, NULL, NULL, NULL},
718
	{"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
719
		0, NULL, NULL, NULL},
720
	{"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
721
		0, NULL, NULL, NULL},
722
	{"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
723
		0, blobValidate, NULL, NULL},
724
725
	{"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
		SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
726
	{"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
727
		0, NULL, NULL, NULL},
728
	{"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
729
		0, NULL, NULL, NULL},
730
	{"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
731
		0, IA5StringValidate, IA5StringNormalize, NULL},
732
	{"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
733
		0, integerValidate, NULL, NULL},
734
735
	{"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
		SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
736
	{"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
737
		0, NULL, NULL, NULL},
738
	{"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
739
		0, NULL, NULL, NULL},
740
	{"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
741
		0, NULL, NULL, NULL},
742
	{"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
743
		0, NULL, NULL, NULL},
744
	{"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
745
		0, NULL, NULL, NULL},
746
	{"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
747
		0, NULL, NULL, NULL},
748
	{"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
749
		0, NULL, NULL, NULL},
750
751
752
	{"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
		0, NULL, NULL, NULL},
	{"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
753
		0, NULL, NULL, NULL},
754
	{"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
755
		0, oidValidate, NULL, NULL},
756
	{"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
757
		0, NULL, NULL, NULL},
758
	{"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
759
		0, blobValidate, NULL, NULL},
760
	{"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
761
		0, blobValidate, NULL, NULL},
762
	{"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
763
		0, NULL, NULL, NULL},
764
	{"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
765
		0, NULL, NULL, NULL},
766
	{"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
767
		0, printableStringValidate, NULL, NULL},
768
769
770
	{"( 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},
771
	{"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
772
		0, blobValidate, NULL, NULL},
773
774
775
776
777
	{"( 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' )",
778
		0, NULL, NULL, NULL},
779
	{"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
780
		0, NULL, NULL, NULL},
781
	{"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
782
		0, NULL, NULL, NULL},
783
	{"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
784
		0, NULL, NULL, NULL},
785
	{"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
786
		0, NULL, NULL, NULL},
787
	{"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
788
		0, NULL, NULL, NULL},
789

790
	/* OpenLDAP Experimental Syntaxes */
791
	{"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
792
		0, NULL, NULL, NULL},
793
794
795
796
	{"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP void' " X_HIDE ")" ,
		SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
	{"( 1.3.6.1.4.1.4203.666.2.3 DESC 'OpenLDAP DN' " X_HIDE ")" ,
		SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
797

798
	{NULL, 0, NULL, NULL, NULL}
799
800
801
};

struct mrule_defs_rec {
802
	char *						mrd_desc;
803
	unsigned					mrd_usage;
804
805
806
807
808
	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;
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
};

/*
 * 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
 */

837
838
839
840
841
#ifndef SLAPD_SCHEMA_NOT_COMPAT
#define caseIgnoreIA5SubstringsMatch NULL
#define caseExactIA5SubstringsMatch NULL
#endif

842
843
/* recycled matching functions */
#define caseIgnoreMatch caseIgnoreIA5Match
844
845
#define caseIgnoreOrderingMatch caseIgnoreMatch
#define caseIgnoreSubstringsMatch caseIgnoreIA5SubstringsMatch
846
#define caseExactMatch caseExactIA5Match
847
848
#define caseExactOrderingMatch caseExactMatch
#define caseExactSubstringsMatch caseExactIA5SubstringsMatch
849
850
851
852
853
854

/* unimplemented matching functions */
#define objectIdentifierMatch NULL
#define numericStringMatch NULL
#define numericStringSubstringsMatch NULL
#define caseIgnoreListMatch NULL
Kurt Zeilenga's avatar
Kurt Zeilenga committed
855
#define caseIgnoreListSubstringsMatch NULL
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
#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

struct mrule_defs_rec mrule_defs[] = {
	{"( 2.5.13.0 NAME 'objectIdentifierMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
872
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
873
		NULL, NULL, objectIdentifierMatch, NULL, NULL},
874
875
876

	{"( 2.5.13.1 NAME 'distinguishedNameMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
877
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
878
		NULL, NULL, dnMatch, NULL, NULL},
879
880
881

	{"( 2.5.13.2 NAME 'caseIgnoreMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
882
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
883
		NULL, NULL, caseIgnoreMatch, NULL, NULL},
884
885
886

	{"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
887
		SLAP_MR_ORDERING,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
888
		NULL, NULL, caseIgnoreOrderingMatch, NULL, NULL},
889
890
891

	{"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
892
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
893
		NULL, NULL, caseIgnoreSubstringsMatch, NULL, NULL},
894
895
896
897

	/* 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 )",
898
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
899
		NULL, NULL, caseExactMatch, NULL, NULL},
900
901
902

	{"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
903
		SLAP_MR_ORDERING,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
904
		NULL, NULL, caseExactOrderingMatch, NULL, NULL},
905
906
907

	{"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
908
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
909
		NULL, NULL, caseExactSubstringsMatch, NULL, NULL},
910
911
912

	{"( 2.5.13.8 NAME 'numericStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
913
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
914
		NULL, NULL, numericStringMatch, NULL, NULL},
915
916
917

	{"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
918
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
919
		NULL, NULL, numericStringSubstringsMatch, NULL, NULL},
920
921
922

	{"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
923
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
924
		NULL, NULL, caseIgnoreListMatch, NULL, NULL},
925

Kurt Zeilenga's avatar
Kurt Zeilenga committed
926
927
928
929
930
	{"( 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},

931
932
	{"( 2.5.13.14 NAME 'integerMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
933
		SLAP_MR_NONE | SLAP_MR_EXT,
934
		NULL, NULL, integerMatch, NULL, NULL},
935
936
937

	{"( 2.5.13.16 NAME 'bitStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
938
		SLAP_MR_NONE | SLAP_MR_EXT,
939
		NULL, NULL, bitStringMatch, NULL, NULL},
940
941
942

	{"( 2.5.13.17 NAME 'octetStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
943
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
944
		NULL, NULL, octetStringMatch, NULL, NULL},
945
946
947

	{"( 2.5.13.20 NAME 'telephoneNumberMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
948
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
949
		NULL, NULL, telephoneNumberMatch, NULL, NULL},
950
951
952

	{"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
953
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
954
		NULL, NULL, telephoneNumberSubstringsMatch, NULL, NULL},
955
956
957

	{"( 2.5.13.22 NAME 'presentationAddressMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
958
		SLAP_MR_NONE | SLAP_MR_EXT,
959
		NULL, NULL, presentationAddressMatch, NULL, NULL},
960
961
962

	{"( 2.5.13.23 NAME 'uniqueMemberMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
963
		SLAP_MR_NONE | SLAP_MR_EXT,
964
		NULL, NULL, uniqueMemberMatch, NULL, NULL},
965
966
967

	{"( 2.5.13.24 NAME 'protocolInformationMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
968
		SLAP_MR_NONE | SLAP_MR_EXT,
969
		NULL, NULL, protocolInformationMatch, NULL, NULL},
970
971
972

	{"( 2.5.13.27 NAME 'generalizedTimeMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
973
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
974
		NULL, NULL, generalizedTimeMatch, NULL, NULL},
975
976
977

	{"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
978
		SLAP_MR_ORDERING,
979
		NULL, NULL, generalizedTimeOrderingMatch, NULL, NULL},
980
981
982

	{"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
983
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
984
		NULL, NULL, integerFirstComponentMatch, NULL, NULL},
985
986
987

	{"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
988
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
989
		NULL, NULL, objectIdentifierFirstComponentMatch, NULL, NULL},
990
991
992

	{"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
993
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
994
		NULL, NULL, caseExactIA5Match, NULL, NULL},
995
996
997

	{"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
998
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
999
		NULL, NULL, caseIgnoreIA5Match, NULL, NULL},
1000
1001
1002

	{"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
1003
		SLAP_MR_SUBSTR,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1004
		NULL, NULL, caseIgnoreIA5SubstringsMatch, NULL, NULL},
1005

1006
	{NULL, SLAP_MR_NONE, NULL, NULL, NULL}
1007
1008
1009
1010
1011
1012
1013
1014
};

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

1015
1016
	/* we should only be called once (from main) */
	assert( schema_init_done == 0 );
1017
1018
1019

	for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
		res = register_syntax( syntax_defs[i].sd_desc,
1020
		    syntax_defs[i].sd_flags,
1021
		    syntax_defs[i].sd_validate,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1022
1023
1024
1025
		    syntax_defs[i].sd_normalize,
			syntax_defs[i].sd_pretty
#ifdef SLAPD_BINARY_CONVERSION
			,
1026
		    syntax_defs[i].sd_ber2str,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1027
1028
1029
			syntax_defs[i].sd_str2ber
#endif
		);
1030
1031
1032
1033

		if ( res ) {
			fprintf( stderr, "schema_init: Error registering syntax %s\n",
				 syntax_defs[i].sd_desc );
1034
			return LDAP_OTHER;
1035
1036
1037
1038
		}
	}

	for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
1039
1040
1041
1042
1043
1044
1045
		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;
		}

1046
1047
		res = register_matching_rule(
			mrule_defs[i].mrd_desc,
1048
			mrule_defs[i].mrd_usage,
1049
1050
			mrule_defs[i].mrd_convert,
			mrule_defs[i].mrd_normalize,
1051
1052
1053
		    mrule_defs[i].mrd_match,
			mrule_defs[i].mrd_indexer,
			mrule_defs[i].mrd_filter );
1054
1055
1056
1057
1058

		if ( res ) {
			fprintf( stderr,
				"schema_init: Error registering matching rule %s\n",
				 mrule_defs[i].mrd_desc );
1059
			return LDAP_OTHER;
1060
1061
1062
		}
	}
	schema_init_done = 1;
1063
	return LDAP_SUCCESS;
1064
}