schema_init.c 25.4 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
667
668
	}

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

669
670
struct syntax_defs_rec {
	char *sd_desc;
671
	int sd_flags;
672
	slap_syntax_validate_func *sd_validate;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
673
674
675
	slap_syntax_transform_func *sd_normalize;
	slap_syntax_transform_func *sd_pretty;
#ifdef SLAPD_BINARY_CONVERSION
676
677
	slap_syntax_transform_func *sd_ber2str;
	slap_syntax_transform_func *sd_str2ber;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
678
#endif
679
680
};

681
#define X_HIDE "X-HIDE 'TRUE' "
682
683
#define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
#define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
684

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

797
	/* OpenLDAP Experimental Syntaxes */
798
	{"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
799
		0, NULL, NULL, NULL},
800
801
802
803
	{"( 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},
804

805
	{NULL, 0, NULL, NULL, NULL}
806
807
808
};

struct mrule_defs_rec {
809
	char *						mrd_desc;
810
	unsigned					mrd_usage;
811
812
813
814
815
	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;
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
};

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

844
845
846
847
848
#ifndef SLAPD_SCHEMA_NOT_COMPAT
#define caseIgnoreIA5SubstringsMatch NULL
#define caseExactIA5SubstringsMatch NULL
#endif

849
850
/* recycled matching functions */
#define caseIgnoreMatch caseIgnoreIA5Match
851
852
#define caseIgnoreOrderingMatch caseIgnoreMatch
#define caseIgnoreSubstringsMatch caseIgnoreIA5SubstringsMatch
853
#define caseExactMatch caseExactIA5Match
854
855
#define caseExactOrderingMatch caseExactMatch
#define caseExactSubstringsMatch caseExactIA5SubstringsMatch
856
857
858
859
860
861

/* unimplemented matching functions */
#define objectIdentifierMatch NULL
#define numericStringMatch NULL
#define numericStringSubstringsMatch NULL
#define caseIgnoreListMatch NULL
Kurt Zeilenga's avatar
Kurt Zeilenga committed
862
#define caseIgnoreListSubstringsMatch NULL
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
#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 )",
879
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
880
		NULL, NULL, objectIdentifierMatch, NULL, NULL},
881
882
883

	{"( 2.5.13.1 NAME 'distinguishedNameMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
884
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
885
		NULL, NULL, dnMatch, NULL, NULL},
886
887
888

	{"( 2.5.13.2 NAME 'caseIgnoreMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
889
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
890
		NULL, NULL, caseIgnoreMatch, NULL, NULL},
891
892
893

	{"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
894
		SLAP_MR_ORDERING,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
895
		NULL, NULL, caseIgnoreOrderingMatch, NULL, NULL},
896
897
898

	{"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
899
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
900
		NULL, NULL, caseIgnoreSubstringsMatch, NULL, NULL},
901
902
903
904

	/* 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 )",
905
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
906
		NULL, NULL, caseExactMatch, NULL, NULL},
907
908
909

	{"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
910
		SLAP_MR_ORDERING,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
911
		NULL, NULL, caseExactOrderingMatch, NULL, NULL},
912
913
914

	{"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
915
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
916
		NULL, NULL, caseExactSubstringsMatch, NULL, NULL},
917
918
919

	{"( 2.5.13.8 NAME 'numericStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
920
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
921
		NULL, NULL, numericStringMatch, NULL, NULL},
922
923
924

	{"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
925
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
926
		NULL, NULL, numericStringSubstringsMatch, NULL, NULL},
927
928
929

	{"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
930
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
931
		NULL, NULL, caseIgnoreListMatch, NULL, NULL},
932

Kurt Zeilenga's avatar
Kurt Zeilenga committed
933
934
935
936
937
	{"( 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},

938
939
	{"( 2.5.13.14 NAME 'integerMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
940
		SLAP_MR_NONE | SLAP_MR_EXT,
941
		NULL, NULL, integerMatch, NULL, NULL},
942
943
944

	{"( 2.5.13.16 NAME 'bitStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
945
		SLAP_MR_NONE | SLAP_MR_EXT,
946
		NULL, NULL, bitStringMatch, NULL, NULL},
947
948
949

	{"( 2.5.13.17 NAME 'octetStringMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
950
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
951
		NULL, NULL, octetStringMatch, NULL, NULL},
952
953
954

	{"( 2.5.13.20 NAME 'telephoneNumberMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
955
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
956
		NULL, NULL, telephoneNumberMatch, NULL, NULL},
957
958
959

	{"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
960
		SLAP_MR_SUBSTR | SLAP_MR_EXT,
961
		NULL, NULL, telephoneNumberSubstringsMatch, NULL, NULL},
962
963
964

	{"( 2.5.13.22 NAME 'presentationAddressMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
965
		SLAP_MR_NONE | SLAP_MR_EXT,
966
		NULL, NULL, presentationAddressMatch, NULL, NULL},
967
968
969

	{"( 2.5.13.23 NAME 'uniqueMemberMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
970
		SLAP_MR_NONE | SLAP_MR_EXT,
971
		NULL, NULL, uniqueMemberMatch, NULL, NULL},
972
973
974

	{"( 2.5.13.24 NAME 'protocolInformationMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
975
		SLAP_MR_NONE | SLAP_MR_EXT,
976
		NULL, NULL, protocolInformationMatch, NULL, NULL},
977
978
979

	{"( 2.5.13.27 NAME 'generalizedTimeMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
980
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
981
		NULL, NULL, generalizedTimeMatch, NULL, NULL},
982
983
984

	{"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
985
		SLAP_MR_ORDERING,
986
		NULL, NULL, generalizedTimeOrderingMatch, NULL, NULL},
987
988
989

	{"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
990
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
991
		NULL, NULL, integerFirstComponentMatch, NULL, NULL},
992
993
994

	{"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
995
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
996
		NULL, NULL, objectIdentifierFirstComponentMatch, NULL, NULL},
997
998
999

	{"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
1000
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1001
		NULL, NULL, caseExactIA5Match, NULL, NULL},
1002
1003
1004

	{"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
1005
		SLAP_MR_EQUALITY | SLAP_MR_EXT,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1006
		NULL, NULL, caseIgnoreIA5Match, NULL, NULL},
1007
1008
1009

	{"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
		"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
1010
		SLAP_MR_SUBSTR,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1011
		NULL, NULL, caseIgnoreIA5SubstringsMatch, NULL, NULL},
1012

1013
	{NULL, SLAP_MR_NONE, NULL, NULL, NULL}
1014
1015
1016
1017
1018
1019
1020
1021
};

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

1022
1023
	/* we should only be called once (from main) */
	assert( schema_init_done == 0 );
1024
1025
1026

	for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
		res = register_syntax( syntax_defs[i].sd_desc,
1027
		    syntax_defs[i].sd_flags,
1028
		    syntax_defs[i].sd_validate,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1029
1030
1031
1032
		    syntax_defs[i].sd_normalize,
			syntax_defs[i].sd_pretty
#ifdef SLAPD_BINARY_CONVERSION
			,
1033
		    syntax_defs[i].sd_ber2str,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1034
1035
1036
			syntax_defs[i].sd_str2ber
#endif
		);
1037
1038
1039
1040

		if ( res ) {
			fprintf( stderr, "schema_init: Error registering syntax %s\n",
				 syntax_defs[i].sd_desc );
1041
			return LDAP_OTHER;
1042
1043
1044
1045
		}
	}

	for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
1046
1047
1048
1049
1050
1051
1052
		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;
		}

1053
1054
		res = register_matching_rule(
			mrule_defs[i].mrd_desc,
1055
			mrule_defs[i].mrd_usage,
1056
1057
			mrule_defs[i].mrd_convert,
			mrule_defs[i].mrd_normalize,
1058
1059
1060
		    mrule_defs[i].mrd_match,
			mrule_defs[i].mrd_indexer,
			mrule_defs[i].mrd_filter );
1061
1062
1063
1064
1065

		if ( res ) {
			fprintf( stderr,
				"schema_init: Error registering matching rule %s\n",
				 mrule_defs[i].mrd_desc );
1066
			return LDAP_OTHER;
1067
1068
1069
		}
	}
	schema_init_done = 1;
1070
	return LDAP_SUCCESS;
1071
}