schema_init.c 92.1 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
 * 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"
18

19
20
#ifdef USE_MD5
#include "lutil_md5.h"
21
22
23
24
25
26
/* We should replace MD5 with a faster hash */
#define HASH_BYTES				LUTIL_MD5_BYTES
#define HASH_CONTEXT			lutil_MD5_CTX
#define HASH_Init(c)			lutil_MD5Init(c)
#define HASH_Update(c,buf,len)	lutil_MD5Update(c,buf,len)
#define HASH_Final(d,c)			lutil_MD5Final(d,c)
27
28
29
30
31
32
33
34
35
#else
#include "lutil_hash.h"
/* We should replace MD5 with a faster hash */
#define HASH_BYTES				LUTIL_HASH_BYTES
#define HASH_CONTEXT			lutil_HASH_CTX
#define HASH_Init(c)			lutil_HASHInit(c)
#define HASH_Update(c,buf,len)	lutil_HASHUpdate(c,buf,len)
#define HASH_Final(d,c)			lutil_HASHFinal(d,c)
#endif
36

37
/* recycled validatation routines */
38
#define berValidate						blobValidate
39

40
/* recycled normalization routines */
41
42
43
#define faxNumberNormalize				numericStringNormalize
#define phoneNumberNormalize			numericStringNormalize
#define telexNumberNormalize			numericStringNormalize
44
45
46
47

/* unimplemented pretters */
#define dnPretty						NULL
#define integerPretty					NULL
48
49

/* recycled matching routines */
50
#define bitStringMatch					octetStringMatch
51
#define integerMatch					caseIgnoreIA5Match
52
53
54
#define numericStringMatch				caseIgnoreMatch
#define objectIdentifierMatch			numericStringMatch
#define telephoneNumberMatch			numericStringMatch
55
#define telephoneNumberSubstringsMatch	caseIgnoreIA5SubstringsMatch
56
57
#define generalizedTimeMatch			numericStringMatch
#define generalizedTimeOrderingMatch	numericStringMatch
58
#define uniqueMemberMatch				dnMatch
59

60
61
62
63
64
65
/* approx matching rules */
#define directoryStringApproxMatchOID	"1.3.6.1.4.1.4203.666.4.4"
#define directoryStringApproxMatch		NULL
#define IA5StringApproxMatchOID			"1.3.6.1.4.1.4203.666.4.5"
#define IA5StringApproxMatch			NULL

66
67
68
69
/* orderring matching rules */
#define caseIgnoreOrderingMatch			caseIgnoreMatch
#define caseExactOrderingMatch			caseExactMatch

70
/* unimplemented matching routines */
71
72
73
74
75
76
77
78
#define caseIgnoreListMatch				NULL
#define caseIgnoreListSubstringsMatch	NULL
#define presentationAddressMatch		NULL
#define protocolInformationMatch		NULL
#define integerFirstComponentMatch		NULL

#define OpenLDAPaciMatch				NULL
#define authPasswordMatch				NULL
79
80

/* recycled indexing/filtering routines */
81
82
#define dnIndexer						caseIgnoreIndexer
#define dnFilter						caseIgnoreFilter
83
84
#define integerIndexer					caseIgnoreIA5Indexer
#define integerFilter					caseIgnoreIA5Filter
85

86
87
88
89
static char *strcasechr( const char *str, int c )
{
	char *lower = strchr( str, TOLOWER(c) );
	char *upper = strchr( str, TOUPPER(c) );
90

91
92
93
94
95
96
97
98
	if( lower && upper ) {
		return lower < upper ? lower : upper;
	} else if ( lower ) {
		return lower;
	} else {
		return upper;
	}
}
99

100
101
102
static int
octetStringMatch(
	int *matchp,
103
	slap_mask_t flags,
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;

	if( match == 0 ) {
		match = memcmp( value->bv_val,
			((struct berval *) assertedValue)->bv_val,
			value->bv_len );
	}

	*matchp = match;
	return LDAP_SUCCESS;
}

/* Index generation function */
int octetStringIndexer(
123
124
	slap_mask_t use,
	slap_mask_t flags,
125
126
127
128
129
130
131
132
133
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *prefix,
	struct berval **values,
	struct berval ***keysp )
{
	int i;
	size_t slen, mlen;
	struct berval **keys;
134
135
	HASH_CONTEXT   HASHcontext;
	unsigned char   HASHdigest[HASH_BYTES];
136
	struct berval digest;
137
138
	digest.bv_val = HASHdigest;
	digest.bv_len = sizeof(HASHdigest);
139

140
141
142
	/* we should have at least one value at this point */
	assert( values != NULL && values[0] != NULL );

143
144
145
146
147
148
149
150
151
152
	for( i=0; values[i] != NULL; i++ ) {
		/* just count them */
	}

	keys = ch_malloc( sizeof( struct berval * ) * (i+1) );

	slen = strlen( syntax->ssyn_oid );
	mlen = strlen( mr->smr_oid );

	for( i=0; values[i] != NULL; i++ ) {
153
		HASH_Init( &HASHcontext );
154
		if( prefix != NULL && prefix->bv_len > 0 ) {
155
			HASH_Update( &HASHcontext,
156
157
				prefix->bv_val, prefix->bv_len );
		}
158
		HASH_Update( &HASHcontext,
159
			syntax->ssyn_oid, slen );
160
		HASH_Update( &HASHcontext,
161
			mr->smr_oid, mlen );
162
		HASH_Update( &HASHcontext,
163
			values[i]->bv_val, values[i]->bv_len );
164
		HASH_Final( HASHdigest, &HASHcontext );
165
166
167
168
169
170
171
172
173
174
175
176
177

		keys[i] = ber_bvdup( &digest );
	}

	keys[i] = NULL;

	*keysp = keys;

	return LDAP_SUCCESS;
}

/* Index generation function */
int octetStringFilter(
178
179
	slap_mask_t use,
	slap_mask_t flags,
180
181
182
183
184
185
186
187
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *prefix,
	void * assertValue,
	struct berval ***keysp )
{
	size_t slen, mlen;
	struct berval **keys;
188
189
	HASH_CONTEXT   HASHcontext;
	unsigned char   HASHdigest[HASH_BYTES];
190
191
	struct berval *value = (struct berval *) assertValue;
	struct berval digest;
192
193
	digest.bv_val = HASHdigest;
	digest.bv_len = sizeof(HASHdigest);
194
195
196
197
198
199

	slen = strlen( syntax->ssyn_oid );
	mlen = strlen( mr->smr_oid );

	keys = ch_malloc( sizeof( struct berval * ) * 2 );

200
	HASH_Init( &HASHcontext );
201
	if( prefix != NULL && prefix->bv_len > 0 ) {
202
		HASH_Update( &HASHcontext,
203
204
			prefix->bv_val, prefix->bv_len );
	}
205
	HASH_Update( &HASHcontext,
206
		syntax->ssyn_oid, slen );
207
	HASH_Update( &HASHcontext,
208
		mr->smr_oid, mlen );
209
	HASH_Update( &HASHcontext,
210
		value->bv_val, value->bv_len );
211
	HASH_Final( HASHdigest, &HASHcontext );
212
213
214
215
216
217
218
219

	keys[0] = ber_bvdup( &digest );
	keys[1] = NULL;

	*keysp = keys;

	return LDAP_SUCCESS;
}
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
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(
271
	int *matchp,
272
	slap_mask_t flags,
273
274
275
276
277
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
278
	int match;
279
280
	struct berval *asserted = (struct berval *) assertedValue;
	
281
282
283
	match = value->bv_len - asserted->bv_len;

	if( match == 0 ) {
284
#ifdef USE_DN_NORMALIZE
285
		match = strcmp( value->bv_val, asserted->bv_val );
286
#else
287
		match = strcasecmp( value->bv_val, asserted->bv_val );
288
#endif
289
290
291
292
293
294
295
	}

	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;
296
}
297

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
static int
nameUIDValidate(
	Syntax *syntax,
	struct berval *in )
{
	int rc;
	struct berval *dn;

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

	dn = ber_bvdup( in );

	if( dn->bv_val[dn->bv_len-1] == '\'' ) {
		/* assume presence of optional UID */
		ber_len_t i;

		for(i=dn->bv_len-2; i>2; i--) {
			if( dn->bv_val[i] != '0' &&	dn->bv_val[i] != '1' ) {
				break;
			}
		}
		if( dn->bv_val[i] != '\'' ) {
			return LDAP_INVALID_SYNTAX;
		}
		if( dn->bv_val[i-1] != 'B' ) {
			return LDAP_INVALID_SYNTAX;
		}
		if( dn->bv_val[i-2] != '#' ) {
			return LDAP_INVALID_SYNTAX;
		}

		/* trim the UID to allow use of dn_validate */
		dn->bv_val[i-2] = '\0';
	}

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

	ber_bvfree( dn );
	return rc;
}

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

	if( out->bv_len != 0 ) {
		char *dn;
		ber_len_t dnlen;
		char *uid = NULL;
		ber_len_t uidlen = 0;

		if( out->bv_val[out->bv_len-1] == '\'' ) {
			/* assume presence of optional UID */
			uid = strrchr( out->bv_val, '#' );

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

			uidlen = out->bv_len - (out->bv_val - uid);
			/* temporarily trim the UID */
			*uid = '\0';
		}

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

		dnlen = strlen(dn);

		if( uidlen ) {
			/* restore the separator */
			*uid = '#';
			/* shift the UID */
			SAFEMEMCPY( &dn[dnlen], uid, uidlen );
		}

		out->bv_val = dn;
		out->bv_len = dnlen + uidlen;
	}

	*normalized = out;
	return LDAP_SUCCESS;
}

396
397
398
399
400
401
402
403
404
static int
inValidate(
	Syntax *syntax,
	struct berval *in )
{
	/* any value allowed */
	return LDAP_OTHER;
}

405
static int
406
blobValidate(
407
408
409
410
	Syntax *syntax,
	struct berval *in )
{
	/* any value allowed */
411
	return LDAP_SUCCESS;
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
static int
bitStringValidate(
	Syntax *syntax,
	struct berval *in )
{
	ber_len_t i;

	/* very unforgiving validation, requires no normalization
	 * before simplistic matching
	 */
	if( in->bv_len < 3 ) {
		return LDAP_INVALID_SYNTAX;
	}
	if( in->bv_val[0] != 'B' ||
		in->bv_val[1] != '\'' ||
		in->bv_val[in->bv_len-1] != '\'' )
	{
		return LDAP_INVALID_SYNTAX;
	}

	for( i=in->bv_len-2; i>1; i-- ) {
		if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
			return LDAP_INVALID_SYNTAX;
		}
	}

	return LDAP_SUCCESS;
}

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
/*
 * Handling boolean syntax and matching is quite rigid.
 * A more flexible approach would be to allow a variety
 * of strings to be normalized and prettied into TRUE
 * and FALSE.
 */
static int
booleanValidate(
	Syntax *syntax,
	struct berval *in )
{
	/* very unforgiving validation, requires no normalization
	 * before simplistic matching
	 */

	if( in->bv_len == 4 ) {
		if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
			return LDAP_SUCCESS;
		}
	} else if( in->bv_len == 5 ) {
		if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
			return LDAP_SUCCESS;
		}
	}

	return LDAP_INVALID_SYNTAX;
}

static int
booleanMatch(
	int *matchp,
474
	slap_mask_t flags,
475
476
477
478
479
480
481
482
483
484
485
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	/* simplistic matching allowed by rigid validation */
	struct berval *asserted = (struct berval *) assertedValue;
	*matchp = value->bv_len != asserted->bv_len;
	return LDAP_SUCCESS;
}

486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
#if 0
static int
UTF8casecmp(
	struct berval *right,
	struct berval *left )
{
	ber_len_t r, l;
	int rlen, llen;
	ldap_unicode_t ru, lu;
	ldap_unicode_t ruu, luu;

	for( r=0, l=0;
		r < right->bv_len && l < left->bv_len;
		r+=rlen, l+=llen )
	{
		/*
		 * XXYYZ: we convert to ucs4 even though -llunicode
		 * expects ucs2 in an unsigned long
		 */
		ru = ldap_utf8_to_ucs4( &right->bv_val[r] );
		if( ru == LDAP_UCS4_INVALID ) {
			return 1;
		}

		lu = ldap_utf8_to_ucs4( &left->bv_val[l] );
		if( lu == LDAP_UCS4_INVALID ) {
			return -1;
		}

		ruu = uctoupper( ru );
		luu = uctoupper( lu );

		if( ruu > luu ) {
			return 1;
		} else if( luu > ruu ) {
			return -1;
		}

		rlen = LDAP_UTF8_CHARLEN( &right->bv_val[r] );
		llen = LDAP_UTF8_CHARLEN( &left->bv_val[l] );
	}

	if( r < right->bv_len ) {
		/* less left */
		return -1;
	}

	if( l < left->bv_len ) {
		/* less right */
		return 1;
	}

	return 0;
}
#endif

542
543
544
545
546
547
548
549
550
static int
UTF8StringValidate(
	Syntax *syntax,
	struct berval *in )
{
	ber_len_t count;
	int len;
	unsigned char *u = in->bv_val;

551
552
	if( !in->bv_len ) return LDAP_INVALID_SYNTAX;

553
	for( count = in->bv_len; count > 0; count-=len, u+=len ) {
554
555
556
557
		/* get the length indicated by the first byte */
		len = LDAP_UTF8_CHARLEN( u );

		/* should not be zero */
558
		if( len == 0 ) return LDAP_INVALID_SYNTAX;
559
560
561

		/* make sure len corresponds with the offset
			to the next character */
562
		if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
563
564
	}

565
	if( count != 0 ) return LDAP_INVALID_SYNTAX;
566

567
	return LDAP_SUCCESS;
568
569
570
571
572
573
574
575
576
}

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

579
	newval = ch_malloc( sizeof( struct berval ) );
580

581
	p = val->bv_val;
582

583
584
585
	/* Ignore initial whitespace */
	while ( ldap_utf8_isspace( p ) ) {
		LDAP_UTF8_INCR( p );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
586
	}
587

588
589
	if( *p == '\0' ) {
		ch_free( newval );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
590
591
		return LDAP_INVALID_SYNTAX;
	}
592

593
594
595
	newval->bv_val = ch_strdup( p );
	p = q = newval->bv_val;
	s = NULL;
596

597
598
	while ( *p ) {
		int len;
599

600
601
602
603
604
		if ( ldap_utf8_isspace( p ) ) {
			len = LDAP_UTF8_COPY(q,p);
			s=q;
			p+=len;
			q+=len;
605

606
607
608
609
			/* Ignore the extra whitespace */
			while ( ldap_utf8_isspace( p ) ) {
				LDAP_UTF8_INCR( p );
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
610
		} else {
611
612
613
614
			len = LDAP_UTF8_COPY(q,p);
			s=NULL;
			p+=len;
			q+=len;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
615
		}
616
617
618
619
	}

	assert( *newval->bv_val );
	assert( newval->bv_val < p );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
620
	assert( q <= p );
621

622
623
624
625
626
627
628
629
630
631
632
	/* 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;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
633
	}
634

635
636
637
638
639
640
641
642
	/* cannot end with a space */
	assert( !ldap_utf8_isspace( LDAP_UTF8_PREV(q) ) );

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

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

644
	return LDAP_SUCCESS;
645
646
}

647
static int
648
caseExactMatch(
649
	int *matchp,
650
	slap_mask_t flags,
651
652
653
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
654
	void *assertedValue )
655
{
656
657
658
	int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;

	if( match == 0 ) {
659
660
661
		match = strncmp( value->bv_val,
			((struct berval *) assertedValue)->bv_val,
			value->bv_len );
662
663
664
	}

	*matchp = match;
665
	return LDAP_SUCCESS;
666
667
}

668
static int
669
caseExactSubstringsMatch(
670
	int *matchp,
671
	slap_mask_t flags,
672
673
674
675
676
677
678
679
680
681
682
	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;

683
	/* Add up asserted input length */
684
685
686
687
	if( sub->sa_initial ) {
		inlen += sub->sa_initial->bv_len;
	}
	if( sub->sa_any ) {
688
689
		for(i=0; sub->sa_any[i] != NULL; i++) {
			inlen += sub->sa_any[i]->bv_len;
690
691
692
693
694
695
696
		}
	}
	if( sub->sa_final ) {
		inlen += sub->sa_final->bv_len;
	}

	if( sub->sa_initial ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
697
698
699
700
701
		if( inlen > left.bv_len ) {
			match = 1;
			goto done;
		}

702
703
		match = strncmp( sub->sa_initial->bv_val, left.bv_val,
			sub->sa_initial->bv_len );
704
705
706
707
708
709
710

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

		left.bv_val += sub->sa_initial->bv_len;
		left.bv_len -= sub->sa_initial->bv_len;
711
		inlen -= sub->sa_initial->bv_len;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
712
	}
713

Kurt Zeilenga's avatar
Kurt Zeilenga committed
714
	if( sub->sa_final ) {
715
716
717
718
		if( inlen > left.bv_len ) {
			match = 1;
			goto done;
		}
719

720
721
722
		match = strncmp( sub->sa_final->bv_val,
			&left.bv_val[left.bv_len - sub->sa_final->bv_len],
			sub->sa_final->bv_len );
723
724
725
726
727
728

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

		left.bv_len -= sub->sa_final->bv_len;
729
		inlen -= sub->sa_final->bv_len;
730
731
732
	}

	if( sub->sa_any ) {
733
734
735
736
737
		for(i=0; sub->sa_any[i]; i++) {
			ber_len_t idx;
			char *p;

retry:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
738
739
740
741
742
743
			if( inlen > left.bv_len ) {
				/* not enough length */
				match = 1;
				goto done;
			}

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

748
			p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771

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

772
773
774
			match = strncmp( left.bv_val,
				sub->sa_any[i]->bv_val,
				sub->sa_any[i]->bv_len );
775
776

			if( match != 0 ) {
777
778
				left.bv_val++;
				left.bv_len--;
779
780
781
782
783
				goto retry;
			}

			left.bv_val += sub->sa_any[i]->bv_len;
			left.bv_len -= sub->sa_any[i]->bv_len;
784
			inlen -= sub->sa_any[i]->bv_len;
785
		}
786
787
788
789
790
791
792
	}

done:
	*matchp = match;
	return LDAP_SUCCESS;
}

793
/* Index generation function */
794
int caseExactIndexer(
795
796
	slap_mask_t use,
	slap_mask_t flags,
797
798
799
800
801
802
803
804
805
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *prefix,
	struct berval **values,
	struct berval ***keysp )
{
	int i;
	size_t slen, mlen;
	struct berval **keys;
806
807
	HASH_CONTEXT   HASHcontext;
	unsigned char   HASHdigest[HASH_BYTES];
808
	struct berval digest;
809
810
	digest.bv_val = HASHdigest;
	digest.bv_len = sizeof(HASHdigest);
811

812
813
814
	/* we should have at least one value at this point */
	assert( values != NULL && values[0] != NULL );

815
816
817
818
819
820
821
822
823
824
825
826
	for( i=0; values[i] != NULL; i++ ) {
		/* just count them */
	}

	keys = ch_malloc( sizeof( struct berval * ) * (i+1) );

	slen = strlen( syntax->ssyn_oid );
	mlen = strlen( mr->smr_oid );

	for( i=0; values[i] != NULL; i++ ) {
		struct berval *value = values[i];

827
		HASH_Init( &HASHcontext );
828
		if( prefix != NULL && prefix->bv_len > 0 ) {
829
			HASH_Update( &HASHcontext,
830
831
				prefix->bv_val, prefix->bv_len );
		}
832
		HASH_Update( &HASHcontext,
833
			syntax->ssyn_oid, slen );
834
		HASH_Update( &HASHcontext,
835
			mr->smr_oid, mlen );
836
		HASH_Update( &HASHcontext,
837
			value->bv_val, value->bv_len );
838
		HASH_Final( HASHdigest, &HASHcontext );
839
840
841
842
843
844
845
846
847
848

		keys[i] = ber_bvdup( &digest );
	}

	keys[i] = NULL;
	*keysp = keys;
	return LDAP_SUCCESS;
}

/* Index generation function */
849
int caseExactFilter(
850
851
	slap_mask_t use,
	slap_mask_t flags,
852
853
854
855
856
857
858
859
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *prefix,
	void * assertValue,
	struct berval ***keysp )
{
	size_t slen, mlen;
	struct berval **keys;
860
861
	HASH_CONTEXT   HASHcontext;
	unsigned char   HASHdigest[HASH_BYTES];
862
863
	struct berval *value;
	struct berval digest;
864
865
	digest.bv_val = HASHdigest;
	digest.bv_len = sizeof(HASHdigest);
866
867
868
869
870
871
872
873

	slen = strlen( syntax->ssyn_oid );
	mlen = strlen( mr->smr_oid );

	value = (struct berval *) assertValue;

	keys = ch_malloc( sizeof( struct berval * ) * 2 );

874
	HASH_Init( &HASHcontext );
875
	if( prefix != NULL && prefix->bv_len > 0 ) {
876
		HASH_Update( &HASHcontext,
877
878
			prefix->bv_val, prefix->bv_len );
	}
879
	HASH_Update( &HASHcontext,
880
		syntax->ssyn_oid, slen );
881
	HASH_Update( &HASHcontext,
882
		mr->smr_oid, mlen );
883
	HASH_Update( &HASHcontext,
884
		value->bv_val, value->bv_len );
885
	HASH_Final( HASHdigest, &HASHcontext );
886
887
888
889
890
891
892

	keys[0] = ber_bvdup( &digest );
	keys[1] = NULL;

	*keysp = keys;
	return LDAP_SUCCESS;
}
893

894
/* Substrings Index generation function */
895
int caseExactSubstringsIndexer(
896
897
	slap_mask_t use,
	slap_mask_t flags,
898
899
900
901
902
903
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *prefix,
	struct berval **values,
	struct berval ***keysp )
{
904
	ber_len_t i, nkeys;
905
906
	size_t slen, mlen;
	struct berval **keys;
907
908
	HASH_CONTEXT   HASHcontext;
	unsigned char   HASHdigest[HASH_BYTES];
909
	struct berval digest;
910
911
	digest.bv_val = HASHdigest;
	digest.bv_len = sizeof(HASHdigest);
912

913
914
915
	/* we should have at least one value at this point */
	assert( values != NULL && values[0] != NULL );

916
917
918
	nkeys=0;
	for( i=0; values[i] != NULL; i++ ) {
		/* count number of indices to generate */
919
		if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
920
921
922
			continue;
		}

923
		if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
924
			if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
925
				nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
926
					( SLAP_INDEX_SUBSTR_MINLEN - 1);
927
			} else {
928
				nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
929
930
931
			}
		}

932
		if( flags & SLAP_INDEX_SUBSTR_ANY ) {
933
934
			if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
				nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
935
936
937
			}
		}

938
		if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
939
			if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
940
				nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
941
					( SLAP_INDEX_SUBSTR_MINLEN - 1);
942
			} else {
943
				nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
944
			}
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
		}
	}

	if( nkeys == 0 ) {
		/* no keys to generate */
		*keysp = NULL;
		return LDAP_SUCCESS;
	}

	keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );

	slen = strlen( syntax->ssyn_oid );
	mlen = strlen( mr->smr_oid );

	nkeys=0;
	for( i=0; values[i] != NULL; i++ ) {
961
		ber_len_t j,max;
962
963
		struct berval *value;

964
		value = values[i];
965
		if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
966

967
		if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
968
			( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
969
970
		{
			char pre = SLAP_INDEX_SUBSTR_PREFIX;
971
			max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
972

973
			for( j=0; j<max; j++ ) {
974
				HASH_Init( &HASHcontext );
975
				if( prefix != NULL && prefix->bv_len > 0 ) {
976
					HASH_Update( &HASHcontext,
977
978
						prefix->bv_val, prefix->bv_len );
				}
979

980
				HASH_Update( &HASHcontext,
981
					&pre, sizeof( pre ) );
982
				HASH_Update( &HASHcontext,
983
					syntax->ssyn_oid, slen );
984
				HASH_Update( &HASHcontext,
985
					mr->smr_oid, mlen );
986
				HASH_Update( &HASHcontext,
987
988
					&value->bv_val[j],
					SLAP_INDEX_SUBSTR_MAXLEN );
989
				HASH_Final( HASHdigest, &HASHcontext );
990
991
992
993
994

				keys[nkeys++] = ber_bvdup( &digest );
			}
		}

995
996
		max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
			? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
997

998
		for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
999
1000
			char pre;

1001
			if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1002
				pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1003
				HASH_Init( &HASHcontext );
1004
				if( prefix != NULL && prefix->bv_len > 0 ) {
1005
					HASH_Update( &HASHcontext,
1006
1007
						prefix->bv_val, prefix->bv_len );
				}
1008
				HASH_Update( &HASHcontext,
1009
					&pre, sizeof( pre ) );
1010
				HASH_Update( &HASHcontext,
1011
					syntax->ssyn_oid, slen );
1012
				HASH_Update( &HASHcontext,
1013
					mr->smr_oid, mlen );
1014
				HASH_Update( &HASHcontext,
1015
					value->bv_val, j );
1016
				HASH_Final( HASHdigest, &HASHcontext );
1017
1018
1019
1020

				keys[nkeys++] = ber_bvdup( &digest );
			}

1021
			if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1022
				pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1023
				HASH_Init( &HASHcontext );
1024
				if( prefix != NULL && prefix->bv_len > 0 ) {
1025
					HASH_Update( &HASHcontext,
1026
1027
						prefix->bv_val, prefix->bv_len );
				}
1028
				HASH_Update( &HASHcontext,
1029
					&pre, sizeof( pre ) );
1030
				HASH_Update( &HASHcontext,
1031
					syntax->ssyn_oid, slen );
1032
				HASH_Update( &HASHcontext,
1033
					mr->smr_oid, mlen );
1034
				HASH_Update( &HASHcontext,
1035
					&value->bv_val[value->bv_len-j], j );
1036
				HASH_Final( HASHdigest, &HASHcontext );
1037
1038
1039
1040
1041
1042
1043

				keys[nkeys++] = ber_bvdup( &digest );
			}

		}
	}

1044
1045
1046
1047
1048
1049
1050
1051
	if( nkeys > 0 ) {
		keys[nkeys] = NULL;
		*keysp = keys;
	} else {
		ch_free( keys );
		*keysp = NULL;
	}

1052
1053
	return LDAP_SUCCESS;
}
1054

1055
int caseExactSubstringsFilter(
1056
1057
	slap_mask_t use,
	slap_mask_t flags,
1058
1059
1060
1061
1062
1063
1064
1065
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *prefix,
	void * assertValue,
	struct berval ***keysp )
{
	SubstringsAssertion *sa = assertValue;
	char pre;
1066
	ber_len_t nkeys = 0;
1067
1068
	size_t slen, mlen, klen;
	struct berval **keys;
1069
1070
	HASH_CONTEXT   HASHcontext;
	unsigned char   HASHdigest[HASH_BYTES];
1071
1072
1073
	struct berval *value;
	struct berval digest;

1074
	if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1075
		sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1076
1077
1078
	{
		nkeys++;
	}
1079

1080
	if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1081
1082
		ber_len_t i;
		for( i=0; sa->sa_any[i] != NULL; i++ ) {
1083
			if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1084
				/* don't bother accounting for stepping */
1085
				nkeys += sa->sa_any[i]->bv_len -
1086
1087
1088
1089
1090
					( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
			}
		}
	}

1091
	if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1092
		sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1093
1094
1095
1096
1097
1098
1099
1100
1101
	{
		nkeys++;
	}

	if( nkeys == 0 ) {
		*keysp = NULL;
		return LDAP_SUCCESS;
	}

1102
1103
	digest.bv_val = HASHdigest;
	digest.bv_len = sizeof(HASHdigest);
1104
1105
1106
1107
1108
1109
1110

	slen = strlen( syntax->ssyn_oid );
	mlen = strlen( mr->smr_oid );

	keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
	nkeys = 0;

1111
	if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1112
		sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1113
1114
1115
1116
	{
		pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
		value = sa->sa_initial;

1117
1118
		klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
			? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1119

1120
		HASH_Init( &HASHcontext );
1121
		if( prefix != NULL && prefix->bv_len > 0 ) {
1122
			HASH_Update( &HASHcontext,
1123
1124
				prefix->bv_val, prefix->bv_len );
		}
1125
		HASH_Update( &HASHcontext,
1126
			&pre, sizeof( pre ) );
1127
		HASH_Update( &HASHcontext,
1128
			syntax->ssyn_oid, slen );
1129
		HASH_Update( &HASHcontext,
1130
			mr->smr_oid, mlen );
1131
		HASH_Update( &HASHcontext,
1132
			value->bv_val, klen );
1133
		HASH_Final( HASHdigest, &HASHcontext );
1134
1135
1136
1137

		keys[nkeys++] = ber_bvdup( &digest );
	}

1138
	if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1139
1140
		ber_len_t i, j;
		pre = SLAP_INDEX_SUBSTR_PREFIX;
1141
		klen = SLAP_INDEX_SUBSTR_MAXLEN;
1142
1143

		for( i=0; sa->sa_any[i] != NULL; i++ ) {
1144
			if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1145
1146
1147
1148
1149
				continue;
			}

			value = sa->sa_any[i];

Kurt Zeilenga's avatar
Kurt Zeilenga committed
1150
			for(j=0;
1151
1152
				j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
				j += SLAP_INDEX_SUBSTR_STEP )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1153
			{
1154
				HASH_Init( &HASHcontext );
1155
				if( prefix != NULL && prefix->bv_len > 0 ) {
1156
					HASH_Update( &HASHcontext,
1157
1158
						prefix->bv_val, prefix->bv_len );
				}
1159
				HASH_Update( &HASHcontext,
1160
					&pre, sizeof( pre ) );
1161
				HASH_Update( &HASHcontext,
1162
					syntax->ssyn_oid, slen );
1163
				HASH_Update( &HASHcontext,
1164
					mr->smr_oid, mlen );
1165
				HASH_Update( &HASHcontext,
1166
					&value->bv_val[j], klen ); 
1167
				HASH_Final( HASHdigest, &HASHcontext );
1168
1169
1170
1171
1172
1173

				keys[nkeys++] = ber_bvdup( &digest );
			}
		}
	}

1174
	if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1175
		sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1176
1177
1178
1179
	{
		pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
		value = sa->sa_final;

1180
1181
		klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
			? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1182

1183
		HASH_Init( &HASHcontext );
1184
		if( prefix != NULL && prefix->bv_len > 0 ) {
1185
			HASH_Update( &HASHcontext,
1186
1187
				prefix->bv_val, prefix->bv_len );
		}
1188
		HASH_Update( &HASHcontext,
1189
			&pre, sizeof( pre ) );
1190
		HASH_Update( &HASHcontext,
1191
			syntax->ssyn_oid, slen );
1192
		HASH_Update( &HASHcontext,
Kurt Zeilenga's avatar