]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
2e4bfbb23bec24a87401c03349d139a5c1604e37
[openldap] / servers / slapd / schema_init.c
1 /* schema_init.c - init builtin schema */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/string.h>
14 #include <ac/socket.h>
15
16 #include "slap.h"
17 #include "ldap_pvt.h"
18 #include "ldap_pvt_uc.h"
19 #include "lutil_md5.h"
20
21 /* recycled validatation routines */
22 #define berValidate                                             blobValidate
23 #define nameUIDValidate                                 dnValidate
24
25 /* unimplemented validators */
26 #define bitStringValidate                               NULL
27
28 /* recycled normalization routines */
29 #define faxNumberNormalize                              numericStringNormalize
30 #define phoneNumberNormalize                    numericStringNormalize
31 #define telexNumberNormalize                    numericStringNormalize
32 #define integerNormalize                                numericStringNormalize
33 #define nameUIDNormalize                                dnNormalize
34
35 /* unimplemented normalizers */
36 #define bitStringNormalize                              NULL
37
38 /* unimplemented pretters */
39 #define dnPretty                                                NULL
40 #define integerPretty                                   NULL
41
42 /* recyclied pretters */
43 #define nameUIDPretty                                   dnPretty
44
45 /* recycled matching routines */
46 #define numericStringMatch                              caseIgnoreMatch
47 #define objectIdentifierMatch                   numericStringMatch
48 #define integerMatch                                    numericStringMatch
49 #define telephoneNumberMatch                    numericStringMatch
50 #define telephoneNumberSubstringsMatch  caseIgnoreSubstringsMatch
51 #define generalizedTimeMatch                    numericStringMatch
52 #define generalizedTimeOrderingMatch    numericStringMatch
53 #define uniqueMemberMatch                               dnMatch
54
55 /* approx matching rules */
56 #define directoryStringApproxMatchOID   "1.3.6.1.4.1.4203.666.4.4"
57 #define directoryStringApproxMatch              NULL
58 #define IA5StringApproxMatchOID                 "1.3.6.1.4.1.4203.666.4.5"
59 #define IA5StringApproxMatch                    NULL
60
61 /* orderring matching rules */
62 #define caseIgnoreOrderingMatch                 caseIgnoreMatch
63 #define caseExactOrderingMatch                  caseExactMatch
64
65 /* unimplemented matching routines */
66 #define caseIgnoreListMatch                             NULL
67 #define caseIgnoreListSubstringsMatch   NULL
68 #define bitStringMatch                                  NULL
69 #define presentationAddressMatch                NULL
70 #define protocolInformationMatch                NULL
71 #define integerFirstComponentMatch              NULL
72
73 #define OpenLDAPaciMatch                                NULL
74 #define authPasswordMatch                               NULL
75
76 /* recycled indexing/filtering routines */
77 #define dnIndexer                                               caseIgnoreIndexer
78 #define dnFilter                                                caseIgnoreFilter
79
80 static char *strcasechr( const char *str, int c )
81 {
82         char *lower = strchr( str, TOLOWER(c) );
83         char *upper = strchr( str, TOUPPER(c) );
84
85         if( lower && upper ) {
86                 return lower < upper ? lower : upper;
87         } else if ( lower ) {
88                 return lower;
89         } else {
90                 return upper;
91         }
92 }
93
94 static int
95 octetStringMatch(
96         int *matchp,
97         slap_mask_t flags,
98         Syntax *syntax,
99         MatchingRule *mr,
100         struct berval *value,
101         void *assertedValue )
102 {
103         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
104
105         if( match == 0 ) {
106                 match = memcmp( value->bv_val,
107                         ((struct berval *) assertedValue)->bv_val,
108                         value->bv_len );
109         }
110
111         *matchp = match;
112         return LDAP_SUCCESS;
113 }
114
115 /* Index generation function */
116 int octetStringIndexer(
117         slap_mask_t use,
118         slap_mask_t flags,
119         Syntax *syntax,
120         MatchingRule *mr,
121         struct berval *prefix,
122         struct berval **values,
123         struct berval ***keysp )
124 {
125         int i;
126         size_t slen, mlen;
127         struct berval **keys;
128         lutil_MD5_CTX   MD5context;
129         unsigned char   MD5digest[16];
130         struct berval digest;
131         digest.bv_val = MD5digest;
132         digest.bv_len = sizeof(MD5digest);
133
134         for( i=0; values[i] != NULL; i++ ) {
135                 /* just count them */
136         }
137
138         assert( i > 0 );
139
140         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
141
142         slen = strlen( syntax->ssyn_oid );
143         mlen = strlen( mr->smr_oid );
144
145         for( i=0; values[i] != NULL; i++ ) {
146                 lutil_MD5Init( &MD5context );
147                 if( prefix != NULL && prefix->bv_len > 0 ) {
148                         lutil_MD5Update( &MD5context,
149                                 prefix->bv_val, prefix->bv_len );
150                 }
151                 lutil_MD5Update( &MD5context,
152                         syntax->ssyn_oid, slen );
153                 lutil_MD5Update( &MD5context,
154                         mr->smr_oid, mlen );
155                 lutil_MD5Update( &MD5context,
156                         values[i]->bv_val, values[i]->bv_len );
157                 lutil_MD5Final( MD5digest, &MD5context );
158
159                 keys[i] = ber_bvdup( &digest );
160         }
161
162         keys[i] = NULL;
163
164         *keysp = keys;
165
166         return LDAP_SUCCESS;
167 }
168
169 /* Index generation function */
170 int octetStringFilter(
171         slap_mask_t use,
172         slap_mask_t flags,
173         Syntax *syntax,
174         MatchingRule *mr,
175         struct berval *prefix,
176         void * assertValue,
177         struct berval ***keysp )
178 {
179         size_t slen, mlen;
180         struct berval **keys;
181         lutil_MD5_CTX   MD5context;
182         unsigned char   MD5digest[LUTIL_MD5_BYTES];
183         struct berval *value = (struct berval *) assertValue;
184         struct berval digest;
185         digest.bv_val = MD5digest;
186         digest.bv_len = sizeof(MD5digest);
187
188         slen = strlen( syntax->ssyn_oid );
189         mlen = strlen( mr->smr_oid );
190
191         keys = ch_malloc( sizeof( struct berval * ) * 2 );
192
193         lutil_MD5Init( &MD5context );
194         if( prefix != NULL && prefix->bv_len > 0 ) {
195                 lutil_MD5Update( &MD5context,
196                         prefix->bv_val, prefix->bv_len );
197         }
198         lutil_MD5Update( &MD5context,
199                 syntax->ssyn_oid, slen );
200         lutil_MD5Update( &MD5context,
201                 mr->smr_oid, mlen );
202         lutil_MD5Update( &MD5context,
203                 value->bv_val, value->bv_len );
204         lutil_MD5Final( MD5digest, &MD5context );
205
206         keys[0] = ber_bvdup( &digest );
207         keys[1] = NULL;
208
209         *keysp = keys;
210
211         return LDAP_SUCCESS;
212 }
213
214 static int
215 dnValidate(
216         Syntax *syntax,
217         struct berval *in )
218 {
219         int rc;
220         char *dn;
221
222         if( in->bv_len == 0 ) return LDAP_SUCCESS;
223
224         dn = ch_strdup( in->bv_val );
225
226         rc = dn_validate( dn ) == NULL
227                 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
228
229         ch_free( dn );
230         return rc;
231 }
232
233 static int
234 dnNormalize(
235         Syntax *syntax,
236         struct berval *val,
237         struct berval **normalized )
238 {
239         struct berval *out = ber_bvdup( val );
240
241         if( out->bv_len != 0 ) {
242                 char *dn;
243 #ifdef USE_DN_NORMALIZE
244                 dn = dn_normalize( out->bv_val );
245 #else
246                 dn = dn_validate( out->bv_val );
247 #endif
248
249                 if( dn == NULL ) {
250                         ber_bvfree( out );
251                         return LDAP_INVALID_SYNTAX;
252                 }
253
254                 out->bv_val = dn;
255                 out->bv_len = strlen( dn );
256         }
257
258         *normalized = out;
259         return LDAP_SUCCESS;
260 }
261
262 static int
263 dnMatch(
264         int *matchp,
265         slap_mask_t flags,
266         Syntax *syntax,
267         MatchingRule *mr,
268         struct berval *value,
269         void *assertedValue )
270 {
271         int match;
272         struct berval *asserted = (struct berval *) assertedValue;
273         
274         match = value->bv_len - asserted->bv_len;
275
276         if( match == 0 ) {
277 #ifdef USE_DN_NORMALIZE
278                 match = strcmp( value->bv_val, asserted->bv_val );
279 #else
280                 match = strcasecmp( value->bv_val, asserted->bv_val );
281 #endif
282         }
283
284         Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
285             match, value->bv_val, asserted->bv_val );
286
287         *matchp = match;
288         return LDAP_SUCCESS;
289 }
290
291 static int
292 inValidate(
293         Syntax *syntax,
294         struct berval *in )
295 {
296         /* any value allowed */
297         return LDAP_OTHER;
298 }
299
300 static int
301 blobValidate(
302         Syntax *syntax,
303         struct berval *in )
304 {
305         /* any value allowed */
306         return LDAP_SUCCESS;
307 }
308
309 /*
310  * Handling boolean syntax and matching is quite rigid.
311  * A more flexible approach would be to allow a variety
312  * of strings to be normalized and prettied into TRUE
313  * and FALSE.
314  */
315 static int
316 booleanValidate(
317         Syntax *syntax,
318         struct berval *in )
319 {
320         /* very unforgiving validation, requires no normalization
321          * before simplistic matching
322          */
323
324         if( in->bv_len == 4 ) {
325                 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
326                         return LDAP_SUCCESS;
327                 }
328         } else if( in->bv_len == 5 ) {
329                 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
330                         return LDAP_SUCCESS;
331                 }
332         }
333
334         return LDAP_INVALID_SYNTAX;
335 }
336
337 static int
338 booleanMatch(
339         int *matchp,
340         slap_mask_t flags,
341         Syntax *syntax,
342         MatchingRule *mr,
343         struct berval *value,
344         void *assertedValue )
345 {
346         /* simplistic matching allowed by rigid validation */
347         struct berval *asserted = (struct berval *) assertedValue;
348         *matchp = value->bv_len != asserted->bv_len;
349         return LDAP_SUCCESS;
350 }
351
352 static int
353 UTF8StringValidate(
354         Syntax *syntax,
355         struct berval *in )
356 {
357         ber_len_t count;
358         int len;
359         unsigned char *u = in->bv_val;
360
361         if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
362
363         for( count = in->bv_len; count > 0; count-=len, u+=len ) {
364                 /* get the length indicated by the first byte */
365                 len = LDAP_UTF8_CHARLEN( u );
366
367                 /* should not be zero */
368                 if( len == 0 ) return LDAP_INVALID_SYNTAX;
369
370                 /* make sure len corresponds with the offset
371                         to the next character */
372                 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
373         }
374
375         if( count != 0 ) return LDAP_INVALID_SYNTAX;
376
377         return LDAP_SUCCESS;
378 }
379
380 #define UNICODE2LEN(n)  ((n)*sizeof(ldap_unicode_t))
381 #define LEN2UNICODE(n)  ((n)/sizeof(ldap_unicode_t))
382
383 #define SLAP_INDEX_SUBSTR_UMINLEN       UNICODE2LEN(SLAP_INDEX_SUBSTR_MINLEN)
384 #define SLAP_INDEX_SUBSTR_UMAXLEN       UNICODE2LEN(SLAP_INDEX_SUBSTR_MAXLEN)
385 #define SLAP_INDEX_SUBSTR_USTEP         UNICODE2LEN(SLAP_INDEX_SUBSTR_STEP)
386
387 static int
388 UTF8StringNormalize(
389         Syntax *syntax,
390         struct berval *val,
391         struct berval **normalized )
392 {
393         ber_len_t bcount;
394         ber_len_t ucount;
395         int len, space;
396         char *u;
397         struct berval *newval;
398         ldap_unicode_t *uc;
399
400         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
401
402         u = val->bv_val;
403         ucount = 0;
404         space = 1;
405
406         for( bcount = val->bv_len; bcount > 0; bcount-=len, u+=len ) {
407                 /* get the length indicated by the first byte */
408                 len = LDAP_UTF8_CHARLEN( u );
409
410                 /* should not be zero */
411                 if( len == 0 ) return LDAP_INVALID_SYNTAX;
412
413                 if( ldap_utf8_isspace( u ) ) {
414                         if( space ) continue;
415                 } else {
416                         space=1;
417                 }
418
419                 ucount++;
420         }
421
422         if( ucount <= 1 ) {
423                 return LDAP_INVALID_SYNTAX;
424         }
425
426         if( space ) {
427                 ucount--;
428         }
429
430         newval = ch_malloc( sizeof( struct berval ) );
431         newval->bv_val = ch_malloc( UNICODE2LEN(ucount+1) );
432         uc = (ldap_unicode_t *) newval->bv_val;
433
434         u = val->bv_val;
435         ucount = 0;
436         space = 1;
437
438         for( bcount = val->bv_len; bcount > 0; bcount-=len, u+=len ) {
439                 /* get the length indicated by the first byte */
440                 len = LDAP_UTF8_CHARLEN( u );
441
442                 /* should not be zero */
443                 if( len == 0 ) return LDAP_INVALID_SYNTAX;
444
445                 if( ldap_utf8_isspace( u ) ) {
446                         if( space ) continue;
447                 } else {
448                         space=1;
449                 }
450
451                 uc[ucount++] = ldap_utf8_to_unicode( u );
452         }
453
454         if( space ) ucount--;
455         uc[ucount] = 0;
456
457         newval->bv_len = UNICODE2LEN(ucount);
458         return LDAP_SUCCESS;
459 }
460
461 static int
462 caseExactMatch(
463         int *matchp,
464         slap_mask_t flags,
465         Syntax *syntax,
466         MatchingRule *mr,
467         struct berval *value,
468         void *assertedValue )
469 {
470         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
471
472         if( match == 0 ) {
473                 match = ucstrncmp( (ldap_unicode_t *) value->bv_val,
474                         (ldap_unicode_t *) ((struct berval *) assertedValue)->bv_val,
475                         LEN2UNICODE(value->bv_len) );
476         }
477
478         *matchp = match;
479         return LDAP_SUCCESS;
480 }
481
482 static int
483 caseExactSubstringsMatch(
484         int *matchp,
485         slap_mask_t flags,
486         Syntax *syntax,
487         MatchingRule *mr,
488         struct berval *value,
489         void *assertedValue )
490 {
491         int match = 0;
492         SubstringsAssertion *sub = assertedValue;
493         struct berval left = *value;
494         int i;
495         ber_len_t inlen=0;
496
497         /* Add up asserted input length */
498         if( sub->sa_initial ) {
499                 inlen += sub->sa_initial->bv_len;
500         }
501         if( sub->sa_any ) {
502                 for(i=0; sub->sa_any[i] != NULL; i++) {
503                         inlen += sub->sa_any[i]->bv_len;
504                 }
505         }
506         if( sub->sa_final ) {
507                 inlen += sub->sa_final->bv_len;
508         }
509
510         if( sub->sa_initial ) {
511                 if( inlen > left.bv_len ) {
512                         match = 1;
513                         goto done;
514                 }
515
516                 match = ucstrncmp(
517                         (ldap_unicode_t *) sub->sa_initial->bv_val,
518                         (ldap_unicode_t *) left.bv_val,
519                         LEN2UNICODE(sub->sa_initial->bv_len) );
520
521                 if( match != 0 ) {
522                         goto done;
523                 }
524
525                 left.bv_val += sub->sa_initial->bv_len;
526                 left.bv_len -= sub->sa_initial->bv_len;
527                 inlen -= sub->sa_initial->bv_len;
528         }
529
530         if( sub->sa_final ) {
531                 if( inlen > left.bv_len ) {
532                         match = 1;
533                         goto done;
534                 }
535
536                 match = ucstrncmp(
537                         (ldap_unicode_t *) sub->sa_final->bv_val,
538                         (ldap_unicode_t *) &left.bv_val[left.bv_len - sub->sa_final->bv_len],
539                         LEN2UNICODE(sub->sa_final->bv_len) );
540
541                 if( match != 0 ) {
542                         goto done;
543                 }
544
545                 left.bv_len -= sub->sa_final->bv_len;
546                 inlen -= sub->sa_final->bv_len;
547         }
548
549         if( sub->sa_any ) {
550                 for(i=0; sub->sa_any[i]; i++) {
551                         ber_len_t idx;
552                         char *p;
553
554 retry:
555                         if( inlen > left.bv_len ) {
556                                 /* not enough length */
557                                 match = 1;
558                                 goto done;
559                         }
560
561                         if( sub->sa_any[i]->bv_len == 0 ) {
562                                 continue;
563                         }
564
565                         p = (char *) ucstrnchr(
566                                 (ldap_unicode_t *) left.bv_val,
567                                 LEN2UNICODE(left.bv_len),
568                                 ((ldap_unicode_t *) sub->sa_any[i]->bv_val)[0] );
569
570
571                         if( p == NULL ) {
572                                 match = 1;
573                                 goto done;
574                         }
575
576                         idx = p - left.bv_val;
577                         assert( idx < left.bv_len );
578
579                         if( idx >= left.bv_len ) {
580                                 /* this shouldn't happen */
581                                 return LDAP_OTHER;
582                         }
583
584                         left.bv_val = p;
585                         left.bv_len -= idx;
586
587                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
588                                 /* not enough left */
589                                 match = 1;
590                                 goto done;
591                         }
592
593                         match = ucstrncmp(
594                                 (ldap_unicode_t *) left.bv_val,
595                                 (ldap_unicode_t *) sub->sa_any[i]->bv_val,
596                                 LEN2UNICODE(sub->sa_any[i]->bv_len) );
597
598                         if( match != 0 ) {
599                                 left.bv_val += UNICODE2LEN(1);
600                                 left.bv_len -= UNICODE2LEN(1);
601                                 goto retry;
602                         }
603
604                         left.bv_val += sub->sa_any[i]->bv_len;
605                         left.bv_len -= sub->sa_any[i]->bv_len;
606                         inlen -= sub->sa_any[i]->bv_len;
607                 }
608         }
609
610 done:
611         *matchp = match;
612         return LDAP_SUCCESS;
613 }
614
615 /* Index generation function */
616 int caseExactIndexer(
617         slap_mask_t use,
618         slap_mask_t flags,
619         Syntax *syntax,
620         MatchingRule *mr,
621         struct berval *prefix,
622         struct berval **values,
623         struct berval ***keysp )
624 {
625         int i;
626         size_t slen, mlen;
627         struct berval **keys;
628         lutil_MD5_CTX   MD5context;
629         unsigned char   MD5digest[16];
630         struct berval digest;
631         digest.bv_val = MD5digest;
632         digest.bv_len = sizeof(MD5digest);
633
634         for( i=0; values[i] != NULL; i++ ) {
635                 /* just count them */
636         }
637
638         assert( i > 0 );
639
640         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
641
642         slen = strlen( syntax->ssyn_oid );
643         mlen = strlen( mr->smr_oid );
644
645         for( i=0; values[i] != NULL; i++ ) {
646                 struct berval *value = values[i];
647
648                 lutil_MD5Init( &MD5context );
649                 if( prefix != NULL && prefix->bv_len > 0 ) {
650                         lutil_MD5Update( &MD5context,
651                                 prefix->bv_val, prefix->bv_len );
652                 }
653                 lutil_MD5Update( &MD5context,
654                         syntax->ssyn_oid, slen );
655                 lutil_MD5Update( &MD5context,
656                         mr->smr_oid, mlen );
657                 lutil_MD5Update( &MD5context,
658                         value->bv_val, value->bv_len );
659                 lutil_MD5Final( MD5digest, &MD5context );
660
661                 keys[i] = ber_bvdup( &digest );
662         }
663
664         keys[i] = NULL;
665         *keysp = keys;
666         return LDAP_SUCCESS;
667 }
668
669 /* Index generation function */
670 int caseExactFilter(
671         slap_mask_t use,
672         slap_mask_t flags,
673         Syntax *syntax,
674         MatchingRule *mr,
675         struct berval *prefix,
676         void * assertValue,
677         struct berval ***keysp )
678 {
679         size_t slen, mlen;
680         struct berval **keys;
681         lutil_MD5_CTX   MD5context;
682         unsigned char   MD5digest[LUTIL_MD5_BYTES];
683         struct berval *value;
684         struct berval digest;
685         digest.bv_val = MD5digest;
686         digest.bv_len = sizeof(MD5digest);
687
688         slen = strlen( syntax->ssyn_oid );
689         mlen = strlen( mr->smr_oid );
690
691         value = (struct berval *) assertValue;
692
693         keys = ch_malloc( sizeof( struct berval * ) * 2 );
694
695         lutil_MD5Init( &MD5context );
696         if( prefix != NULL && prefix->bv_len > 0 ) {
697                 lutil_MD5Update( &MD5context,
698                         prefix->bv_val, prefix->bv_len );
699         }
700         lutil_MD5Update( &MD5context,
701                 syntax->ssyn_oid, slen );
702         lutil_MD5Update( &MD5context,
703                 mr->smr_oid, mlen );
704         lutil_MD5Update( &MD5context,
705                 value->bv_val, value->bv_len );
706         lutil_MD5Final( MD5digest, &MD5context );
707
708         keys[0] = ber_bvdup( &digest );
709         keys[1] = NULL;
710
711         *keysp = keys;
712         return LDAP_SUCCESS;
713 }
714
715 /* Substrings Index generation function */
716 int caseExactSubstringsIndexer(
717         slap_mask_t use,
718         slap_mask_t flags,
719         Syntax *syntax,
720         MatchingRule *mr,
721         struct berval *prefix,
722         struct berval **values,
723         struct berval ***keysp )
724 {
725         ber_len_t i, nkeys;
726         size_t slen, mlen;
727         struct berval **keys;
728         lutil_MD5_CTX   MD5context;
729         unsigned char   MD5digest[16];
730         struct berval digest;
731         digest.bv_val = MD5digest;
732         digest.bv_len = sizeof(MD5digest);
733
734         nkeys=0;
735         for( i=0; values[i] != NULL; i++ ) {
736                 /* count number of indices to generate */
737                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_UMINLEN ) {
738                         continue;
739                 }
740
741                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
742                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
743                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
744                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
745                         } else {
746                                 nkeys += LEN2UNICODE(values[i]->bv_len) -
747                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
748                         }
749                 }
750
751                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
752                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
753                                 nkeys += LEN2UNICODE(values[i]->bv_len) -
754                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
755                         }
756                 }
757
758                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
759                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
760                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
761                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
762                         } else {
763                                 nkeys += LEN2UNICODE(values[i]->bv_len) -
764                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
765                         }
766                 }
767         }
768         assert( i > 0 );
769
770         if( nkeys == 0 ) {
771                 /* no keys to generate */
772                 *keysp = NULL;
773                 return LDAP_SUCCESS;
774         }
775
776         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
777
778         slen = strlen( syntax->ssyn_oid );
779         mlen = strlen( mr->smr_oid );
780
781         nkeys=0;
782         for( i=0; values[i] != NULL; i++ ) {
783                 ber_len_t j,max;
784                 struct berval *value;
785
786                 value = values[i];
787                 if( value->bv_len < SLAP_INDEX_SUBSTR_UMINLEN ) continue;
788
789                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
790                         ( value->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) )
791                 {
792                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
793                         max = value->bv_len -
794                                 ( SLAP_INDEX_SUBSTR_UMAXLEN - UNICODE2LEN(1));
795
796                         for( j=0; j<max; j+=UNICODE2LEN(1) ) {
797                                 lutil_MD5Init( &MD5context );
798                                 if( prefix != NULL && prefix->bv_len > 0 ) {
799                                         lutil_MD5Update( &MD5context,
800                                                 prefix->bv_val, prefix->bv_len );
801                                 }
802                                 lutil_MD5Update( &MD5context,
803                                         &pre, sizeof( pre ) );
804                                 lutil_MD5Update( &MD5context,
805                                         syntax->ssyn_oid, slen );
806                                 lutil_MD5Update( &MD5context,
807                                         mr->smr_oid, mlen );
808                                 lutil_MD5Update( &MD5context,
809                                         &value->bv_val[j], SLAP_INDEX_SUBSTR_UMAXLEN );
810                                 lutil_MD5Final( MD5digest, &MD5context );
811
812                                 keys[nkeys++] = ber_bvdup( &digest );
813                         }
814                 }
815
816                 max = SLAP_INDEX_SUBSTR_UMAXLEN < value->bv_len
817                         ? SLAP_INDEX_SUBSTR_UMAXLEN : value->bv_len;
818
819                 for( j=SLAP_INDEX_SUBSTR_UMINLEN; j<=max; j+=UNICODE2LEN(1) ) {
820                         char pre;
821
822                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
823                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
824                                 lutil_MD5Init( &MD5context );
825                                 if( prefix != NULL && prefix->bv_len > 0 ) {
826                                         lutil_MD5Update( &MD5context,
827                                                 prefix->bv_val, prefix->bv_len );
828                                 }
829                                 lutil_MD5Update( &MD5context,
830                                         &pre, sizeof( pre ) );
831                                 lutil_MD5Update( &MD5context,
832                                         syntax->ssyn_oid, slen );
833                                 lutil_MD5Update( &MD5context,
834                                         mr->smr_oid, mlen );
835                                 lutil_MD5Update( &MD5context,
836                                         value->bv_val, j );
837                                 lutil_MD5Final( MD5digest, &MD5context );
838
839                                 keys[nkeys++] = ber_bvdup( &digest );
840                         }
841
842                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
843                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
844                                 lutil_MD5Init( &MD5context );
845                                 if( prefix != NULL && prefix->bv_len > 0 ) {
846                                         lutil_MD5Update( &MD5context,
847                                                 prefix->bv_val, prefix->bv_len );
848                                 }
849                                 lutil_MD5Update( &MD5context,
850                                         &pre, sizeof( pre ) );
851                                 lutil_MD5Update( &MD5context,
852                                         syntax->ssyn_oid, slen );
853                                 lutil_MD5Update( &MD5context,
854                                         mr->smr_oid, mlen );
855                                 lutil_MD5Update( &MD5context,
856                                         &value->bv_val[value->bv_len-j], j );
857                                 lutil_MD5Final( MD5digest, &MD5context );
858
859                                 keys[nkeys++] = ber_bvdup( &digest );
860                         }
861
862                 }
863         }
864
865         if( nkeys > 0 ) {
866                 keys[nkeys] = NULL;
867                 *keysp = keys;
868         } else {
869                 ch_free( keys );
870                 *keysp = NULL;
871         }
872
873         return LDAP_SUCCESS;
874 }
875
876 int caseExactSubstringsFilter(
877         slap_mask_t use,
878         slap_mask_t flags,
879         Syntax *syntax,
880         MatchingRule *mr,
881         struct berval *prefix,
882         void * assertValue,
883         struct berval ***keysp )
884 {
885         SubstringsAssertion *sa = assertValue;
886         char pre;
887         ber_len_t nkeys = 0;
888         size_t slen, mlen, klen;
889         struct berval **keys;
890         lutil_MD5_CTX   MD5context;
891         unsigned char   MD5digest[LUTIL_MD5_BYTES];
892         struct berval *value;
893         struct berval digest;
894
895         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
896                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
897         {
898                 nkeys++;
899         }
900
901         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
902                 ber_len_t i;
903                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
904                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
905                                 /* don't bother accounting for stepping */
906                                 nkeys += LEN2UNICODE(sa->sa_any[i]->bv_len) -
907                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
908                         }
909                 }
910         }
911
912         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
913                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
914         {
915                 nkeys++;
916         }
917
918         if( nkeys == 0 ) {
919                 *keysp = NULL;
920                 return LDAP_SUCCESS;
921         }
922
923         digest.bv_val = MD5digest;
924         digest.bv_len = sizeof(MD5digest);
925
926         slen = strlen( syntax->ssyn_oid );
927         mlen = strlen( mr->smr_oid );
928
929         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
930         nkeys = 0;
931
932         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
933                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
934         {
935                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
936                 value = sa->sa_initial;
937
938                 klen = SLAP_INDEX_SUBSTR_UMAXLEN < value->bv_len
939                         ? SLAP_INDEX_SUBSTR_UMAXLEN : value->bv_len;
940
941                 lutil_MD5Init( &MD5context );
942                 if( prefix != NULL && prefix->bv_len > 0 ) {
943                         lutil_MD5Update( &MD5context,
944                                 prefix->bv_val, prefix->bv_len );
945                 }
946                 lutil_MD5Update( &MD5context,
947                         &pre, sizeof( pre ) );
948                 lutil_MD5Update( &MD5context,
949                         syntax->ssyn_oid, slen );
950                 lutil_MD5Update( &MD5context,
951                         mr->smr_oid, mlen );
952                 lutil_MD5Update( &MD5context,
953                         value->bv_val, klen );
954                 lutil_MD5Final( MD5digest, &MD5context );
955
956                 keys[nkeys++] = ber_bvdup( &digest );
957         }
958
959         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
960                 ber_len_t i, j;
961                 pre = SLAP_INDEX_SUBSTR_PREFIX;
962                 klen = SLAP_INDEX_SUBSTR_UMAXLEN;
963
964                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
965                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_UMAXLEN ) {
966                                 continue;
967                         }
968
969                         value = sa->sa_any[i];
970
971                         for(j=0;
972                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_UMAXLEN;
973                                 j += SLAP_INDEX_SUBSTR_USTEP )
974                         {
975                                 lutil_MD5Init( &MD5context );
976                                 if( prefix != NULL && prefix->bv_len > 0 ) {
977                                         lutil_MD5Update( &MD5context,
978                                                 prefix->bv_val, prefix->bv_len );
979                                 }
980                                 lutil_MD5Update( &MD5context,
981                                         &pre, sizeof( pre ) );
982                                 lutil_MD5Update( &MD5context,
983                                         syntax->ssyn_oid, slen );
984                                 lutil_MD5Update( &MD5context,
985                                         mr->smr_oid, mlen );
986                                 lutil_MD5Update( &MD5context,
987                                         &value->bv_val[j], klen );
988                                 lutil_MD5Final( MD5digest, &MD5context );
989
990                                 keys[nkeys++] = ber_bvdup( &digest );
991                         }
992                 }
993         }
994
995         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
996                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
997         {
998                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
999                 value = sa->sa_final;
1000
1001                 klen = SLAP_INDEX_SUBSTR_UMAXLEN < value->bv_len
1002                         ? SLAP_INDEX_SUBSTR_UMAXLEN : value->bv_len;
1003
1004                 lutil_MD5Init( &MD5context );
1005                 if( prefix != NULL && prefix->bv_len > 0 ) {
1006                         lutil_MD5Update( &MD5context,
1007                                 prefix->bv_val, prefix->bv_len );
1008                 }
1009                 lutil_MD5Update( &MD5context,
1010                         &pre, sizeof( pre ) );
1011                 lutil_MD5Update( &MD5context,
1012                         syntax->ssyn_oid, slen );
1013                 lutil_MD5Update( &MD5context,
1014                         mr->smr_oid, mlen );
1015                 lutil_MD5Update( &MD5context,
1016                         &value->bv_val[value->bv_len-klen], klen );
1017                 lutil_MD5Final( MD5digest, &MD5context );
1018
1019                 keys[nkeys++] = ber_bvdup( &digest );
1020         }
1021
1022         if( nkeys > 0 ) {
1023                 keys[nkeys] = NULL;
1024                 *keysp = keys;
1025         } else {
1026                 ch_free( keys );
1027                 *keysp = NULL;
1028         }
1029
1030         return LDAP_SUCCESS;
1031 }
1032         
1033 static int
1034 caseIgnoreMatch(
1035         int *matchp,
1036         slap_mask_t flags,
1037         Syntax *syntax,
1038         MatchingRule *mr,
1039         struct berval *value,
1040         void *assertedValue )
1041 {
1042         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
1043
1044         if( match == 0 ) {
1045                 match = ucstrncasecmp(
1046                         (ldap_unicode_t *) value->bv_val,
1047                         (ldap_unicode_t *) ((struct berval *) assertedValue)->bv_val,
1048                         LEN2UNICODE(value->bv_len) );
1049         }
1050
1051         *matchp = match;
1052         return LDAP_SUCCESS;
1053 }
1054
1055 static int
1056 caseIgnoreSubstringsMatch(
1057         int *matchp,
1058         slap_mask_t flags,
1059         Syntax *syntax,
1060         MatchingRule *mr,
1061         struct berval *value,
1062         void *assertedValue )
1063 {
1064         int match = 0;
1065         SubstringsAssertion *sub = assertedValue;
1066         struct berval left = *value;
1067         int i;
1068         ber_len_t inlen=0;
1069
1070         /* Add up asserted input length */
1071         if( sub->sa_initial ) {
1072                 inlen += sub->sa_initial->bv_len;
1073         }
1074         if( sub->sa_any ) {
1075                 for(i=0; sub->sa_any[i] != NULL; i++) {
1076                         inlen += sub->sa_any[i]->bv_len;
1077                 }
1078         }
1079         if( sub->sa_final ) {
1080                 inlen += sub->sa_final->bv_len;
1081         }
1082
1083         if( sub->sa_initial ) {
1084                 if( inlen > left.bv_len ) {
1085                         match = 1;
1086                         goto done;
1087                 }
1088
1089                 match = ucstrncasecmp(
1090                         (ldap_unicode_t *) sub->sa_initial->bv_val,
1091                         (ldap_unicode_t *) left.bv_val,
1092                         LEN2UNICODE(sub->sa_initial->bv_len) );
1093
1094                 if( match != 0 ) {
1095                         goto done;
1096                 }
1097
1098                 left.bv_val += sub->sa_initial->bv_len;
1099                 left.bv_len -= sub->sa_initial->bv_len;
1100                 inlen -= sub->sa_initial->bv_len;
1101         }
1102
1103         if( sub->sa_final ) {
1104                 if( inlen > left.bv_len ) {
1105                         match = 1;
1106                         goto done;
1107                 }
1108
1109                 match = ucstrncasecmp(
1110                         (ldap_unicode_t *) sub->sa_final->bv_val,
1111                         (ldap_unicode_t *) &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1112                         LEN2UNICODE(sub->sa_final->bv_len) );
1113
1114                 if( match != 0 ) {
1115                         goto done;
1116                 }
1117
1118                 left.bv_len -= sub->sa_final->bv_len;
1119                 inlen -= sub->sa_final->bv_len;
1120         }
1121
1122         if( sub->sa_any ) {
1123                 for(i=0; sub->sa_any[i]; i++) {
1124                         ber_len_t idx;
1125                         char *p;
1126
1127 retry:
1128                         if( inlen > left.bv_len ) {
1129                                 /* not enough length */
1130                                 match = 1;
1131                                 goto done;
1132                         }
1133
1134                         if( sub->sa_any[i]->bv_len == 0 ) {
1135                                 continue;
1136                         }
1137
1138                         p = (char *) ucstrncasechr(
1139                                 (ldap_unicode_t *) left.bv_val,
1140                                 LEN2UNICODE(left.bv_len),
1141                                 ((ldap_unicode_t *) sub->sa_any[i]->bv_val)[0] );
1142
1143                         if( p == NULL ) {
1144                                 match = 1;
1145                                 goto done;
1146                         }
1147
1148                         idx = p - left.bv_val;
1149                         assert( idx < left.bv_len );
1150
1151                         if( idx >= left.bv_len ) {
1152                                 /* this shouldn't happen */
1153                                 return LDAP_OTHER;
1154                         }
1155
1156                         left.bv_val = p;
1157                         left.bv_len -= idx;
1158
1159                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
1160                                 /* not enough left */
1161                                 match = 1;
1162                                 goto done;
1163                         }
1164
1165                         match = ucstrncasecmp(
1166                                 (ldap_unicode_t *) left.bv_val,
1167                                 (ldap_unicode_t *) sub->sa_any[i]->bv_val,
1168                                 LEN2UNICODE(sub->sa_any[i]->bv_len) );
1169
1170                         if( match != 0 ) {
1171                                 left.bv_val += UNICODE2LEN(1);
1172                                 left.bv_len -= UNICODE2LEN(1);
1173
1174                                 goto retry;
1175                         }
1176
1177                         left.bv_val += sub->sa_any[i]->bv_len;
1178                         left.bv_len -= sub->sa_any[i]->bv_len;
1179                         inlen -= sub->sa_any[i]->bv_len;
1180                 }
1181         }
1182
1183 done:
1184         *matchp = match;
1185         return LDAP_SUCCESS;
1186 }
1187
1188 /* Index generation function */
1189 int caseIgnoreIndexer(
1190         slap_mask_t use,
1191         slap_mask_t flags,
1192         Syntax *syntax,
1193         MatchingRule *mr,
1194         struct berval *prefix,
1195         struct berval **values,
1196         struct berval ***keysp )
1197 {
1198         int i;
1199         size_t slen, mlen;
1200         struct berval **keys;
1201         lutil_MD5_CTX   MD5context;
1202         unsigned char   MD5digest[16];
1203         struct berval digest;
1204         digest.bv_val = MD5digest;
1205         digest.bv_len = sizeof(MD5digest);
1206
1207         for( i=0; values[i] != NULL; i++ ) {
1208                 /* just count them */
1209         }
1210
1211         assert( i > 0 );
1212
1213         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
1214
1215         slen = strlen( syntax->ssyn_oid );
1216         mlen = strlen( mr->smr_oid );
1217
1218         for( i=0; values[i] != NULL; i++ ) {
1219                 struct berval *value = ber_bvdup( values[i] );
1220                 ucstr2upper( (ldap_unicode_t *) value->bv_val,
1221                         LEN2UNICODE(value->bv_len) );
1222
1223                 lutil_MD5Init( &MD5context );
1224                 if( prefix != NULL && prefix->bv_len > 0 ) {
1225                         lutil_MD5Update( &MD5context,
1226                                 prefix->bv_val, prefix->bv_len );
1227                 }
1228                 lutil_MD5Update( &MD5context,
1229                         syntax->ssyn_oid, slen );
1230                 lutil_MD5Update( &MD5context,
1231                         mr->smr_oid, mlen );
1232                 lutil_MD5Update( &MD5context,
1233                         value->bv_val, value->bv_len );
1234                 lutil_MD5Final( MD5digest, &MD5context );
1235
1236                 ber_bvfree( value );
1237                 keys[i] = ber_bvdup( &digest );
1238         }
1239
1240         keys[i] = NULL;
1241         *keysp = keys;
1242         return LDAP_SUCCESS;
1243 }
1244
1245 /* Index generation function */
1246 int caseIgnoreFilter(
1247         slap_mask_t use,
1248         slap_mask_t flags,
1249         Syntax *syntax,
1250         MatchingRule *mr,
1251         struct berval *prefix,
1252         void * assertValue,
1253         struct berval ***keysp )
1254 {
1255         size_t slen, mlen;
1256         struct berval **keys;
1257         lutil_MD5_CTX   MD5context;
1258         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1259         struct berval *value;
1260         struct berval digest;
1261         digest.bv_val = MD5digest;
1262         digest.bv_len = sizeof(MD5digest);
1263
1264         slen = strlen( syntax->ssyn_oid );
1265         mlen = strlen( mr->smr_oid );
1266
1267         value = ber_bvdup( (struct berval *) assertValue );
1268         ucstr2upper( (ldap_unicode_t *) value->bv_val,
1269                 LEN2UNICODE(value->bv_len) );
1270
1271         keys = ch_malloc( sizeof( struct berval * ) * 2 );
1272
1273         lutil_MD5Init( &MD5context );
1274         if( prefix != NULL && prefix->bv_len > 0 ) {
1275                 lutil_MD5Update( &MD5context,
1276                         prefix->bv_val, prefix->bv_len );
1277         }
1278         lutil_MD5Update( &MD5context,
1279                 syntax->ssyn_oid, slen );
1280         lutil_MD5Update( &MD5context,
1281                 mr->smr_oid, mlen );
1282         lutil_MD5Update( &MD5context,
1283                 value->bv_val, value->bv_len );
1284         lutil_MD5Final( MD5digest, &MD5context );
1285
1286         keys[0] = ber_bvdup( &digest );
1287         keys[1] = NULL;
1288
1289         ber_bvfree( value );
1290
1291         *keysp = keys;
1292
1293         return LDAP_SUCCESS;
1294 }
1295
1296 /* Substrings Index generation function */
1297 int caseIgnoreSubstringsIndexer(
1298         slap_mask_t use,
1299         slap_mask_t flags,
1300         Syntax *syntax,
1301         MatchingRule *mr,
1302         struct berval *prefix,
1303         struct berval **values,
1304         struct berval ***keysp )
1305 {
1306         ber_len_t i, nkeys;
1307         size_t slen, mlen;
1308         struct berval **keys;
1309         lutil_MD5_CTX   MD5context;
1310         unsigned char   MD5digest[16];
1311         struct berval digest;
1312         digest.bv_val = MD5digest;
1313         digest.bv_len = sizeof(MD5digest);
1314
1315         nkeys=0;
1316         for( i=0; values[i] != NULL; i++ ) {
1317                 /* count number of indices to generate */
1318                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_UMINLEN ) {
1319                         continue;
1320                 }
1321
1322                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1323                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
1324                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1325                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1326                         } else {
1327                                 nkeys += LEN2UNICODE(values[i]->bv_len) -
1328                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1329                         }
1330                 }
1331
1332                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1333                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
1334                                 nkeys += LEN2UNICODE(values[i]->bv_len) -
1335                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1336                         }
1337                 }
1338
1339                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1340                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
1341                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1342                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1343                         } else {
1344                                 nkeys += LEN2UNICODE(values[i]->bv_len) -
1345                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1346                         }
1347                 }
1348         }
1349         assert( i > 0 );
1350
1351         if( nkeys == 0 ) {
1352                 /* no keys to generate */
1353                 *keysp = NULL;
1354                 return LDAP_SUCCESS;
1355         }
1356
1357         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1358
1359         slen = strlen( syntax->ssyn_oid );
1360         mlen = strlen( mr->smr_oid );
1361
1362         nkeys=0;
1363         for( i=0; values[i] != NULL; i++ ) {
1364                 int j,max;
1365                 struct berval *value;
1366
1367                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_UMINLEN ) continue;
1368
1369                 value = ber_bvdup( values[i] );
1370                 ucstr2upper( (ldap_unicode_t *) value->bv_val,
1371                         LEN2UNICODE(value->bv_len) );
1372
1373                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1374                         ( value->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) )
1375                 {
1376                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
1377                         max = value->bv_len -
1378                                 ( SLAP_INDEX_SUBSTR_UMAXLEN - UNICODE2LEN(1));
1379
1380                         for( j=0; j<max; j+=UNICODE2LEN(1) ) {
1381                                 lutil_MD5Init( &MD5context );
1382                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1383                                         lutil_MD5Update( &MD5context,
1384                                                 prefix->bv_val, prefix->bv_len );
1385                                 }
1386                                 lutil_MD5Update( &MD5context,
1387                                         &pre, sizeof( pre ) );
1388                                 lutil_MD5Update( &MD5context,
1389                                         syntax->ssyn_oid, slen );
1390                                 lutil_MD5Update( &MD5context,
1391                                         mr->smr_oid, mlen );
1392                                 lutil_MD5Update( &MD5context,
1393                                         &value->bv_val[j],
1394                                         SLAP_INDEX_SUBSTR_UMAXLEN );
1395                                 lutil_MD5Final( MD5digest, &MD5context );
1396
1397                                 keys[nkeys++] = ber_bvdup( &digest );
1398                         }
1399                 }
1400
1401                 max = SLAP_INDEX_SUBSTR_UMAXLEN < value->bv_len
1402                         ? SLAP_INDEX_SUBSTR_UMAXLEN : value->bv_len;
1403
1404                 for( j=SLAP_INDEX_SUBSTR_UMINLEN; j<=max; j+=UNICODE2LEN(1) ) {
1405                         char pre;
1406
1407                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1408                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1409                                 lutil_MD5Init( &MD5context );
1410                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1411                                         lutil_MD5Update( &MD5context,
1412                                                 prefix->bv_val, prefix->bv_len );
1413                                 }
1414                                 lutil_MD5Update( &MD5context,
1415                                         &pre, sizeof( pre ) );
1416                                 lutil_MD5Update( &MD5context,
1417                                         syntax->ssyn_oid, slen );
1418                                 lutil_MD5Update( &MD5context,
1419                                         mr->smr_oid, mlen );
1420                                 lutil_MD5Update( &MD5context,
1421                                         value->bv_val, j );
1422                                 lutil_MD5Final( MD5digest, &MD5context );
1423
1424                                 keys[nkeys++] = ber_bvdup( &digest );
1425                         }
1426
1427                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1428                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1429                                 lutil_MD5Init( &MD5context );
1430                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1431                                         lutil_MD5Update( &MD5context,
1432                                                 prefix->bv_val, prefix->bv_len );
1433                                 }
1434                                 lutil_MD5Update( &MD5context,
1435                                         &pre, sizeof( pre ) );
1436                                 lutil_MD5Update( &MD5context,
1437                                         syntax->ssyn_oid, slen );
1438                                 lutil_MD5Update( &MD5context,
1439                                         mr->smr_oid, mlen );
1440                                 lutil_MD5Update( &MD5context,
1441                                         &value->bv_val[value->bv_len-j], j );
1442                                 lutil_MD5Final( MD5digest, &MD5context );
1443
1444                                 keys[nkeys++] = ber_bvdup( &digest );
1445                         }
1446
1447                 }
1448
1449                 ber_bvfree( value );
1450         }
1451
1452         if( nkeys > 0 ) {
1453                 keys[nkeys] = NULL;
1454                 *keysp = keys;
1455         } else {
1456                 ch_free( keys );
1457                 *keysp = NULL;
1458         }
1459
1460         return LDAP_SUCCESS;
1461 }
1462
1463 int caseIgnoreSubstringsFilter(
1464         slap_mask_t use,
1465         slap_mask_t flags,
1466         Syntax *syntax,
1467         MatchingRule *mr,
1468         struct berval *prefix,
1469         void * assertValue,
1470         struct berval ***keysp )
1471 {
1472         SubstringsAssertion *sa = assertValue;
1473         char pre;
1474         ber_len_t nkeys = 0;
1475         size_t slen, mlen, klen;
1476         struct berval **keys;
1477         lutil_MD5_CTX   MD5context;
1478         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1479         struct berval *value;
1480         struct berval digest;
1481
1482         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
1483                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
1484         {
1485                 nkeys++;
1486         }
1487
1488         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
1489                 ber_len_t i;
1490                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1491                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_UMAXLEN ) {
1492                                 /* don't bother accounting for stepping */
1493                                 nkeys += LEN2UNICODE(sa->sa_any[i]->bv_len) -
1494                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1495                         }
1496                 }
1497         }
1498
1499         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
1500                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
1501         {
1502                 nkeys++;
1503         }
1504
1505         if( nkeys == 0 ) {
1506                 *keysp = NULL;
1507                 return LDAP_SUCCESS;
1508         }
1509
1510         digest.bv_val = MD5digest;
1511         digest.bv_len = sizeof(MD5digest);
1512
1513         slen = strlen( syntax->ssyn_oid );
1514         mlen = strlen( mr->smr_oid );
1515
1516         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1517         nkeys = 0;
1518
1519         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
1520                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
1521         {
1522                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1523                 value = ber_bvdup( sa->sa_initial );
1524                 ucstr2upper( (ldap_unicode_t *) value->bv_val,
1525                         LEN2UNICODE(value->bv_len) );
1526
1527                 klen = SLAP_INDEX_SUBSTR_UMAXLEN < value->bv_len
1528                         ? SLAP_INDEX_SUBSTR_UMAXLEN : value->bv_len;
1529
1530                 lutil_MD5Init( &MD5context );
1531                 if( prefix != NULL && prefix->bv_len > 0 ) {
1532                         lutil_MD5Update( &MD5context,
1533                                 prefix->bv_val, prefix->bv_len );
1534                 }
1535                 lutil_MD5Update( &MD5context,
1536                         &pre, sizeof( pre ) );
1537                 lutil_MD5Update( &MD5context,
1538                         syntax->ssyn_oid, slen );
1539                 lutil_MD5Update( &MD5context,
1540                         mr->smr_oid, mlen );
1541                 lutil_MD5Update( &MD5context,
1542                         value->bv_val, klen );
1543                 lutil_MD5Final( MD5digest, &MD5context );
1544
1545                 ber_bvfree( value );
1546                 keys[nkeys++] = ber_bvdup( &digest );
1547         }
1548
1549         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
1550                 ber_len_t i, j;
1551                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1552                 klen = SLAP_INDEX_SUBSTR_UMAXLEN;
1553
1554                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1555                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_UMAXLEN ) {
1556                                 continue;
1557                         }
1558
1559                         value = ber_bvdup( sa->sa_any[i] );
1560                         ucstr2upper( (ldap_unicode_t *) value->bv_val,
1561                                 LEN2UNICODE(value->bv_len) );
1562
1563                         for(j=0;
1564                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_UMAXLEN;
1565                                 j += SLAP_INDEX_SUBSTR_USTEP )
1566                         {
1567                                 lutil_MD5Init( &MD5context );
1568                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1569                                         lutil_MD5Update( &MD5context,
1570                                                 prefix->bv_val, prefix->bv_len );
1571                                 }
1572                                 lutil_MD5Update( &MD5context,
1573                                         &pre, sizeof( pre ) );
1574                                 lutil_MD5Update( &MD5context,
1575                                         syntax->ssyn_oid, slen );
1576                                 lutil_MD5Update( &MD5context,
1577                                         mr->smr_oid, mlen );
1578                                 lutil_MD5Update( &MD5context,
1579                                         &value->bv_val[j], klen );
1580                                 lutil_MD5Final( MD5digest, &MD5context );
1581
1582                                 keys[nkeys++] = ber_bvdup( &digest );
1583                         }
1584
1585                         ber_bvfree( value );
1586                 }
1587         }
1588
1589         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
1590                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_UMINLEN )
1591         {
1592                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1593                 value = ber_bvdup( sa->sa_final );
1594                 ucstr2upper( (ldap_unicode_t *) value->bv_val,
1595                         LEN2UNICODE(value->bv_len) );
1596
1597                 klen = SLAP_INDEX_SUBSTR_UMAXLEN < value->bv_len
1598                         ? SLAP_INDEX_SUBSTR_UMAXLEN : value->bv_len;
1599
1600                 lutil_MD5Init( &MD5context );
1601                 if( prefix != NULL && prefix->bv_len > 0 ) {
1602                         lutil_MD5Update( &MD5context,
1603                                 prefix->bv_val, prefix->bv_len );
1604                 }
1605                 lutil_MD5Update( &MD5context,
1606                         &pre, sizeof( pre ) );
1607                 lutil_MD5Update( &MD5context,
1608                         syntax->ssyn_oid, slen );
1609                 lutil_MD5Update( &MD5context,
1610                         mr->smr_oid, mlen );
1611                 lutil_MD5Update( &MD5context,
1612                         &value->bv_val[value->bv_len-klen], klen );
1613                 lutil_MD5Final( MD5digest, &MD5context );
1614
1615                 ber_bvfree( value );
1616                 keys[nkeys++] = ber_bvdup( &digest );
1617         }
1618
1619         if( nkeys > 0 ) {
1620                 keys[nkeys] = NULL;
1621                 *keysp = keys;
1622         } else {
1623                 ch_free( keys );
1624                 *keysp = NULL;
1625         }
1626
1627         return LDAP_SUCCESS;
1628 }
1629         
1630 static int
1631 oidValidate(
1632         Syntax *syntax,
1633         struct berval *val )
1634 {
1635         ber_len_t i;
1636
1637         if( val->bv_len == 0 ) return 0;
1638
1639         if( OID_LEADCHAR(val->bv_val[0]) ) {
1640                 int dot = 0;
1641                 for(i=1; i < val->bv_len; i++) {
1642                         if( OID_SEPARATOR( val->bv_val[i] ) ) {
1643                                 if( dot++ ) return 1;
1644                         } else if ( OID_CHAR( val->bv_val[i] ) ) {
1645                                 dot = 0;
1646                         } else {
1647                                 return LDAP_INVALID_SYNTAX;
1648                         }
1649                 }
1650
1651                 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1652
1653         } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1654                 for(i=1; i < val->bv_len; i++) {
1655                         if( !DESC_CHAR(val->bv_val[i] ) ) {
1656                                 return LDAP_INVALID_SYNTAX;
1657                         }
1658                 }
1659
1660                 return LDAP_SUCCESS;
1661         }
1662         
1663         return LDAP_INVALID_SYNTAX;
1664 }
1665
1666 static int
1667 integerValidate(
1668         Syntax *syntax,
1669         struct berval *val )
1670 {
1671         ber_len_t i;
1672
1673         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1674
1675         for(i=0; i < val->bv_len; i++) {
1676                 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1677         }
1678
1679         return LDAP_SUCCESS;
1680 }
1681
1682 static int
1683 printableStringValidate(
1684         Syntax *syntax,
1685         struct berval *val )
1686 {
1687         ber_len_t i;
1688
1689         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1690
1691         for(i=0; i < val->bv_len; i++) {
1692                 if( !isprint(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1693         }
1694
1695         return LDAP_SUCCESS;
1696 }
1697
1698 static int
1699 IA5StringValidate(
1700         Syntax *syntax,
1701         struct berval *val )
1702 {
1703         ber_len_t i;
1704
1705         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1706
1707         for(i=0; i < val->bv_len; i++) {
1708                 if( !isascii(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1709         }
1710
1711         return LDAP_SUCCESS;
1712 }
1713
1714 static int
1715 IA5StringConvert(
1716         Syntax *syntax,
1717         struct berval *in,
1718         struct berval **out )
1719 {
1720         ldap_unicode_t *u;
1721         ber_len_t i, len = in->bv_len;
1722         struct berval *bv = ch_malloc( sizeof(struct berval) );
1723
1724         bv->bv_len = len * sizeof( ldap_unicode_t );
1725         u = (ldap_unicode_t *) ch_malloc( bv->bv_len + sizeof(ldap_unicode_t) );
1726         bv->bv_val = (char *) u;
1727
1728         for(i=0; i < len; i++ ) {
1729                 /*
1730                  * IA5StringValidate should have been called to ensure
1731                  * input is limited to IA5.
1732                  */
1733                 u[i] = in->bv_val[i];
1734         }
1735         u[i] = 0;
1736
1737         *out = bv;
1738         return LDAP_SUCCESS;
1739 }
1740
1741 static int
1742 IA5StringNormalize(
1743         Syntax *syntax,
1744         struct berval *val,
1745         struct berval **normalized )
1746 {
1747         struct berval *newval;
1748         char *p, *q;
1749
1750         newval = ch_malloc( sizeof( struct berval ) );
1751
1752         p = val->bv_val;
1753
1754         /* Ignore initial whitespace */
1755         while ( ASCII_SPACE( *p ) ) {
1756                 p++;
1757         }
1758
1759         if( *p == '\0' ) {
1760                 ch_free( newval );
1761                 return LDAP_INVALID_SYNTAX;
1762         }
1763
1764         newval->bv_val = ch_strdup( p );
1765         p = q = newval->bv_val;
1766
1767         while ( *p ) {
1768                 if ( ASCII_SPACE( *p ) ) {
1769                         *q++ = *p++;
1770
1771                         /* Ignore the extra whitespace */
1772                         while ( ASCII_SPACE( *p ) ) {
1773                                 p++;
1774                         }
1775                 } else {
1776                         *q++ = *p++;
1777                 }
1778         }
1779
1780         assert( *newval->bv_val );
1781         assert( newval->bv_val < p );
1782         assert( p <= q );
1783
1784         /* cannot start with a space */
1785         assert( !ASCII_SPACE(*newval->bv_val) );
1786
1787         /*
1788          * If the string ended in space, backup the pointer one
1789          * position.  One is enough because the above loop collapsed
1790          * all whitespace to a single space.
1791          */
1792
1793         if ( ASCII_SPACE( q[-1] ) ) {
1794                 --q;
1795         }
1796
1797         /* cannot end with a space */
1798         assert( !ASCII_SPACE( q[-1] ) );
1799
1800         /* null terminate */
1801         *q = '\0';
1802
1803         newval->bv_len = q - newval->bv_val;
1804         *normalized = newval;
1805
1806         return LDAP_SUCCESS;
1807 }
1808
1809 static int
1810 caseExactIA5Match(
1811         int *matchp,
1812         slap_mask_t flags,
1813         Syntax *syntax,
1814         MatchingRule *mr,
1815         struct berval *value,
1816         void *assertedValue )
1817 {
1818         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
1819
1820         if( match == 0 ) {
1821                 match = strncmp( value->bv_val,
1822                         ((struct berval *) assertedValue)->bv_val,
1823                         value->bv_len );
1824         }
1825
1826         *matchp = match;
1827         return LDAP_SUCCESS;
1828 }
1829
1830 static int
1831 caseExactIA5SubstringsMatch(
1832         int *matchp,
1833         slap_mask_t flags,
1834         Syntax *syntax,
1835         MatchingRule *mr,
1836         struct berval *value,
1837         void *assertedValue )
1838 {
1839         int match = 0;
1840         SubstringsAssertion *sub = assertedValue;
1841         struct berval left = *value;
1842         int i;
1843         ber_len_t inlen=0;
1844
1845         /* Add up asserted input length */
1846         if( sub->sa_initial ) {
1847                 inlen += sub->sa_initial->bv_len;
1848         }
1849         if( sub->sa_any ) {
1850                 for(i=0; sub->sa_any[i] != NULL; i++) {
1851                         inlen += sub->sa_any[i]->bv_len;
1852                 }
1853         }
1854         if( sub->sa_final ) {
1855                 inlen += sub->sa_final->bv_len;
1856         }
1857
1858         if( sub->sa_initial ) {
1859                 if( inlen > left.bv_len ) {
1860                         match = 1;
1861                         goto done;
1862                 }
1863
1864                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
1865                         sub->sa_initial->bv_len );
1866
1867                 if( match != 0 ) {
1868                         goto done;
1869                 }
1870
1871                 left.bv_val += sub->sa_initial->bv_len;
1872                 left.bv_len -= sub->sa_initial->bv_len;
1873                 inlen -= sub->sa_initial->bv_len;
1874         }
1875
1876         if( sub->sa_final ) {
1877                 if( inlen > left.bv_len ) {
1878                         match = 1;
1879                         goto done;
1880                 }
1881
1882                 match = strncmp( sub->sa_final->bv_val,
1883                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1884                         sub->sa_final->bv_len );
1885
1886                 if( match != 0 ) {
1887                         goto done;
1888                 }
1889
1890                 left.bv_len -= sub->sa_final->bv_len;
1891                 inlen -= sub->sa_final->bv_len;
1892         }
1893
1894         if( sub->sa_any ) {
1895                 for(i=0; sub->sa_any[i]; i++) {
1896                         ber_len_t idx;
1897                         char *p;
1898
1899 retry:
1900                         if( inlen > left.bv_len ) {
1901                                 /* not enough length */
1902                                 match = 1;
1903                                 goto done;
1904                         }
1905
1906                         if( sub->sa_any[i]->bv_len == 0 ) {
1907                                 continue;
1908                         }
1909
1910                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
1911
1912                         if( p == NULL ) {
1913                                 match = 1;
1914                                 goto done;
1915                         }
1916
1917                         idx = p - left.bv_val;
1918                         assert( idx < left.bv_len );
1919
1920                         if( idx >= left.bv_len ) {
1921                                 /* this shouldn't happen */
1922                                 return LDAP_OTHER;
1923                         }
1924
1925                         left.bv_val = p;
1926                         left.bv_len -= idx;
1927
1928                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
1929                                 /* not enough left */
1930                                 match = 1;
1931                                 goto done;
1932                         }
1933
1934                         match = strncmp( left.bv_val,
1935                                 sub->sa_any[i]->bv_val,
1936                                 sub->sa_any[i]->bv_len );
1937
1938                         if( match != 0 ) {
1939                                 left.bv_val++;
1940                                 left.bv_len--;
1941                                 goto retry;
1942                         }
1943
1944                         left.bv_val += sub->sa_any[i]->bv_len;
1945                         left.bv_len -= sub->sa_any[i]->bv_len;
1946                         inlen -= sub->sa_any[i]->bv_len;
1947                 }
1948         }
1949
1950 done:
1951         *matchp = match;
1952         return LDAP_SUCCESS;
1953 }
1954
1955 /* Index generation function */
1956 int caseExactIA5Indexer(
1957         slap_mask_t use,
1958         slap_mask_t flags,
1959         Syntax *syntax,
1960         MatchingRule *mr,
1961         struct berval *prefix,
1962         struct berval **values,
1963         struct berval ***keysp )
1964 {
1965         int i;
1966         size_t slen, mlen;
1967         struct berval **keys;
1968         lutil_MD5_CTX   MD5context;
1969         unsigned char   MD5digest[16];
1970         struct berval digest;
1971         digest.bv_val = MD5digest;
1972         digest.bv_len = sizeof(MD5digest);
1973
1974         for( i=0; values[i] != NULL; i++ ) {
1975                 /* just count them */
1976         }
1977
1978         assert( i > 0 );
1979
1980         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
1981
1982         slen = strlen( syntax->ssyn_oid );
1983         mlen = strlen( mr->smr_oid );
1984
1985         for( i=0; values[i] != NULL; i++ ) {
1986                 struct berval *value = values[i];
1987
1988                 lutil_MD5Init( &MD5context );
1989                 if( prefix != NULL && prefix->bv_len > 0 ) {
1990                         lutil_MD5Update( &MD5context,
1991                                 prefix->bv_val, prefix->bv_len );
1992                 }
1993                 lutil_MD5Update( &MD5context,
1994                         syntax->ssyn_oid, slen );
1995                 lutil_MD5Update( &MD5context,
1996                         mr->smr_oid, mlen );
1997                 lutil_MD5Update( &MD5context,
1998                         value->bv_val, value->bv_len );
1999                 lutil_MD5Final( MD5digest, &MD5context );
2000
2001                 keys[i] = ber_bvdup( &digest );
2002         }
2003
2004         keys[i] = NULL;
2005         *keysp = keys;
2006         return LDAP_SUCCESS;
2007 }
2008
2009 /* Index generation function */
2010 int caseExactIA5Filter(
2011         slap_mask_t use,
2012         slap_mask_t flags,
2013         Syntax *syntax,
2014         MatchingRule *mr,
2015         struct berval *prefix,
2016         void * assertValue,
2017         struct berval ***keysp )
2018 {
2019         size_t slen, mlen;
2020         struct berval **keys;
2021         lutil_MD5_CTX   MD5context;
2022         unsigned char   MD5digest[LUTIL_MD5_BYTES];
2023         struct berval *value;
2024         struct berval digest;
2025         digest.bv_val = MD5digest;
2026         digest.bv_len = sizeof(MD5digest);
2027
2028         slen = strlen( syntax->ssyn_oid );
2029         mlen = strlen( mr->smr_oid );
2030
2031         value = (struct berval *) assertValue;
2032
2033         keys = ch_malloc( sizeof( struct berval * ) * 2 );
2034
2035         lutil_MD5Init( &MD5context );
2036         if( prefix != NULL && prefix->bv_len > 0 ) {
2037                 lutil_MD5Update( &MD5context,
2038                         prefix->bv_val, prefix->bv_len );
2039         }
2040         lutil_MD5Update( &MD5context,
2041                 syntax->ssyn_oid, slen );
2042         lutil_MD5Update( &MD5context,
2043                 mr->smr_oid, mlen );
2044         lutil_MD5Update( &MD5context,
2045                 value->bv_val, value->bv_len );
2046         lutil_MD5Final( MD5digest, &MD5context );
2047
2048         keys[0] = ber_bvdup( &digest );
2049         keys[1] = NULL;
2050
2051         *keysp = keys;
2052         return LDAP_SUCCESS;
2053 }
2054
2055 /* Substrings Index generation function */
2056 int caseExactIA5SubstringsIndexer(
2057         slap_mask_t use,
2058         slap_mask_t flags,
2059         Syntax *syntax,
2060         MatchingRule *mr,
2061         struct berval *prefix,
2062         struct berval **values,
2063         struct berval ***keysp )
2064 {
2065         ber_len_t i, nkeys;
2066         size_t slen, mlen;
2067         struct berval **keys;
2068         lutil_MD5_CTX   MD5context;
2069         unsigned char   MD5digest[16];
2070         struct berval digest;
2071         digest.bv_val = MD5digest;
2072         digest.bv_len = sizeof(MD5digest);
2073
2074         nkeys=0;
2075         for( i=0; values[i] != NULL; i++ ) {
2076                 /* count number of indices to generate */
2077                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2078                         continue;
2079                 }
2080
2081                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2082                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2083                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2084                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2085                         } else {
2086                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2087                         }
2088                 }
2089
2090                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2091                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2092                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2093                         }
2094                 }
2095
2096                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2097                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2098                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2099                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2100                         } else {
2101                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2102                         }
2103                 }
2104         }
2105         assert( i > 0 );
2106
2107         if( nkeys == 0 ) {
2108                 /* no keys to generate */
2109                 *keysp = NULL;
2110                 return LDAP_SUCCESS;
2111         }
2112
2113         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2114
2115         slen = strlen( syntax->ssyn_oid );
2116         mlen = strlen( mr->smr_oid );
2117
2118         nkeys=0;
2119         for( i=0; values[i] != NULL; i++ ) {
2120                 ber_len_t j,max;
2121                 struct berval *value;
2122
2123                 value = values[i];
2124                 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2125
2126                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2127                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2128                 {
2129                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
2130                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2131
2132                         for( j=0; j<max; j++ ) {
2133                                 lutil_MD5Init( &MD5context );
2134                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2135                                         lutil_MD5Update( &MD5context,
2136                                                 prefix->bv_val, prefix->bv_len );
2137                                 }
2138                                 lutil_MD5Update( &MD5context,
2139                                         &pre, sizeof( pre ) );
2140                                 lutil_MD5Update( &MD5context,
2141                                         syntax->ssyn_oid, slen );
2142                                 lutil_MD5Update( &MD5context,
2143                                         mr->smr_oid, mlen );
2144                                 lutil_MD5Update( &MD5context,
2145                                         &value->bv_val[j],
2146                                         SLAP_INDEX_SUBSTR_MAXLEN );
2147                                 lutil_MD5Final( MD5digest, &MD5context );
2148
2149                                 keys[nkeys++] = ber_bvdup( &digest );
2150                         }
2151                 }
2152
2153                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2154                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2155
2156                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2157                         char pre;
2158
2159                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2160                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2161                                 lutil_MD5Init( &MD5context );
2162                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2163                                         lutil_MD5Update( &MD5context,
2164                                                 prefix->bv_val, prefix->bv_len );
2165                                 }
2166                                 lutil_MD5Update( &MD5context,
2167                                         &pre, sizeof( pre ) );
2168                                 lutil_MD5Update( &MD5context,
2169                                         syntax->ssyn_oid, slen );
2170                                 lutil_MD5Update( &MD5context,
2171                                         mr->smr_oid, mlen );
2172                                 lutil_MD5Update( &MD5context,
2173                                         value->bv_val, j );
2174                                 lutil_MD5Final( MD5digest, &MD5context );
2175
2176                                 keys[nkeys++] = ber_bvdup( &digest );
2177                         }
2178
2179                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2180                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2181                                 lutil_MD5Init( &MD5context );
2182                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2183                                         lutil_MD5Update( &MD5context,
2184                                                 prefix->bv_val, prefix->bv_len );
2185                                 }
2186                                 lutil_MD5Update( &MD5context,
2187                                         &pre, sizeof( pre ) );
2188                                 lutil_MD5Update( &MD5context,
2189                                         syntax->ssyn_oid, slen );
2190                                 lutil_MD5Update( &MD5context,
2191                                         mr->smr_oid, mlen );
2192                                 lutil_MD5Update( &MD5context,
2193                                         &value->bv_val[value->bv_len-j], j );
2194                                 lutil_MD5Final( MD5digest, &MD5context );
2195
2196                                 keys[nkeys++] = ber_bvdup( &digest );
2197                         }
2198
2199                 }
2200         }
2201
2202         if( nkeys > 0 ) {
2203                 keys[nkeys] = NULL;
2204                 *keysp = keys;
2205         } else {
2206                 ch_free( keys );
2207                 *keysp = NULL;
2208         }
2209
2210         return LDAP_SUCCESS;
2211 }
2212
2213 int caseExactIA5SubstringsFilter(
2214         slap_mask_t use,
2215         slap_mask_t flags,
2216         Syntax *syntax,
2217         MatchingRule *mr,
2218         struct berval *prefix,
2219         void * assertValue,
2220         struct berval ***keysp )
2221 {
2222         SubstringsAssertion *sa = assertValue;
2223         char pre;
2224         ber_len_t nkeys = 0;
2225         size_t slen, mlen, klen;
2226         struct berval **keys;
2227         lutil_MD5_CTX   MD5context;
2228         unsigned char   MD5digest[LUTIL_MD5_BYTES];
2229         struct berval *value;
2230         struct berval digest;
2231
2232         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
2233                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2234         {
2235                 nkeys++;
2236         }
2237
2238         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2239                 ber_len_t i;
2240                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2241                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2242                                 /* don't bother accounting for stepping */
2243                                 nkeys += sa->sa_any[i]->bv_len -
2244                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2245                         }
2246                 }
2247         }
2248
2249         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
2250                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2251         {
2252                 nkeys++;
2253         }
2254
2255         if( nkeys == 0 ) {
2256                 *keysp = NULL;
2257                 return LDAP_SUCCESS;
2258         }
2259
2260         digest.bv_val = MD5digest;
2261         digest.bv_len = sizeof(MD5digest);
2262
2263         slen = strlen( syntax->ssyn_oid );
2264         mlen = strlen( mr->smr_oid );
2265
2266         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2267         nkeys = 0;
2268
2269         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
2270                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2271         {
2272                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2273                 value = sa->sa_initial;
2274
2275                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2276                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2277
2278                 lutil_MD5Init( &MD5context );
2279                 if( prefix != NULL && prefix->bv_len > 0 ) {
2280                         lutil_MD5Update( &MD5context,
2281                                 prefix->bv_val, prefix->bv_len );
2282                 }
2283                 lutil_MD5Update( &MD5context,
2284                         &pre, sizeof( pre ) );
2285                 lutil_MD5Update( &MD5context,
2286                         syntax->ssyn_oid, slen );
2287                 lutil_MD5Update( &MD5context,
2288                         mr->smr_oid, mlen );
2289                 lutil_MD5Update( &MD5context,
2290                         value->bv_val, klen );
2291                 lutil_MD5Final( MD5digest, &MD5context );
2292
2293                 keys[nkeys++] = ber_bvdup( &digest );
2294         }
2295
2296         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2297                 ber_len_t i, j;
2298                 pre = SLAP_INDEX_SUBSTR_PREFIX;
2299                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2300
2301                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2302                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2303                                 continue;
2304                         }
2305
2306                         value = sa->sa_any[i];
2307
2308                         for(j=0;
2309                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2310                                 j += SLAP_INDEX_SUBSTR_STEP )
2311                         {
2312                                 lutil_MD5Init( &MD5context );
2313                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2314                                         lutil_MD5Update( &MD5context,
2315                                                 prefix->bv_val, prefix->bv_len );
2316                                 }
2317                                 lutil_MD5Update( &MD5context,
2318                                         &pre, sizeof( pre ) );
2319                                 lutil_MD5Update( &MD5context,
2320                                         syntax->ssyn_oid, slen );
2321                                 lutil_MD5Update( &MD5context,
2322                                         mr->smr_oid, mlen );
2323                                 lutil_MD5Update( &MD5context,
2324                                         &value->bv_val[j], klen ); 
2325                                 lutil_MD5Final( MD5digest, &MD5context );
2326
2327                                 keys[nkeys++] = ber_bvdup( &digest );
2328                         }
2329                 }
2330         }
2331
2332         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
2333                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2334         {
2335                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2336                 value = sa->sa_final;
2337
2338                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2339                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2340
2341                 lutil_MD5Init( &MD5context );
2342                 if( prefix != NULL && prefix->bv_len > 0 ) {
2343                         lutil_MD5Update( &MD5context,
2344                                 prefix->bv_val, prefix->bv_len );
2345                 }
2346                 lutil_MD5Update( &MD5context,
2347                         &pre, sizeof( pre ) );
2348                 lutil_MD5Update( &MD5context,
2349                         syntax->ssyn_oid, slen );
2350                 lutil_MD5Update( &MD5context,
2351                         mr->smr_oid, mlen );
2352                 lutil_MD5Update( &MD5context,
2353                         &value->bv_val[value->bv_len-klen], klen );
2354                 lutil_MD5Final( MD5digest, &MD5context );
2355
2356                 keys[nkeys++] = ber_bvdup( &digest );
2357         }
2358
2359         if( nkeys > 0 ) {
2360                 keys[nkeys] = NULL;
2361                 *keysp = keys;
2362         } else {
2363                 ch_free( keys );
2364                 *keysp = NULL;
2365         }
2366
2367         return LDAP_SUCCESS;
2368 }
2369         
2370 static int
2371 caseIgnoreIA5Match(
2372         int *matchp,
2373         slap_mask_t flags,
2374         Syntax *syntax,
2375         MatchingRule *mr,
2376         struct berval *value,
2377         void *assertedValue )
2378 {
2379         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2380
2381         if( match == 0 ) {
2382                 match = strncasecmp( value->bv_val,
2383                         ((struct berval *) assertedValue)->bv_val,
2384                         value->bv_len );
2385         }
2386
2387         *matchp = match;
2388         return LDAP_SUCCESS;
2389 }
2390
2391 static int
2392 caseIgnoreIA5SubstringsMatch(
2393         int *matchp,
2394         slap_mask_t flags,
2395         Syntax *syntax,
2396         MatchingRule *mr,
2397         struct berval *value,
2398         void *assertedValue )
2399 {
2400         int match = 0;
2401         SubstringsAssertion *sub = assertedValue;
2402         struct berval left = *value;
2403         int i;
2404         ber_len_t inlen=0;
2405
2406         /* Add up asserted input length */
2407         if( sub->sa_initial ) {
2408                 inlen += sub->sa_initial->bv_len;
2409         }
2410         if( sub->sa_any ) {
2411                 for(i=0; sub->sa_any[i] != NULL; i++) {
2412                         inlen += sub->sa_any[i]->bv_len;
2413                 }
2414         }
2415         if( sub->sa_final ) {
2416                 inlen += sub->sa_final->bv_len;
2417         }
2418
2419         if( sub->sa_initial ) {
2420                 if( inlen > left.bv_len ) {
2421                         match = 1;
2422                         goto done;
2423                 }
2424
2425                 match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
2426                         sub->sa_initial->bv_len );
2427
2428                 if( match != 0 ) {
2429                         goto done;
2430                 }
2431
2432                 left.bv_val += sub->sa_initial->bv_len;
2433                 left.bv_len -= sub->sa_initial->bv_len;
2434                 inlen -= sub->sa_initial->bv_len;
2435         }
2436
2437         if( sub->sa_final ) {
2438                 if( inlen > left.bv_len ) {
2439                         match = 1;
2440                         goto done;
2441                 }
2442
2443                 match = strncasecmp( sub->sa_final->bv_val,
2444                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
2445                         sub->sa_final->bv_len );
2446
2447                 if( match != 0 ) {
2448                         goto done;
2449                 }
2450
2451                 left.bv_len -= sub->sa_final->bv_len;
2452                 inlen -= sub->sa_final->bv_len;
2453         }
2454
2455         if( sub->sa_any ) {
2456                 for(i=0; sub->sa_any[i]; i++) {
2457                         ber_len_t idx;
2458                         char *p;
2459
2460 retry:
2461                         if( inlen > left.bv_len ) {
2462                                 /* not enough length */
2463                                 match = 1;
2464                                 goto done;
2465                         }
2466
2467                         if( sub->sa_any[i]->bv_len == 0 ) {
2468                                 continue;
2469                         }
2470
2471                         p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );
2472
2473                         if( p == NULL ) {
2474                                 match = 1;
2475                                 goto done;
2476                         }
2477
2478                         idx = p - left.bv_val;
2479                         assert( idx < left.bv_len );
2480
2481                         if( idx >= left.bv_len ) {
2482                                 /* this shouldn't happen */
2483                                 return LDAP_OTHER;
2484                         }
2485
2486                         left.bv_val = p;
2487                         left.bv_len -= idx;
2488
2489                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
2490                                 /* not enough left */
2491                                 match = 1;
2492                                 goto done;
2493                         }
2494
2495                         match = strncasecmp( left.bv_val,
2496                                 sub->sa_any[i]->bv_val,
2497                                 sub->sa_any[i]->bv_len );
2498
2499                         if( match != 0 ) {
2500                                 left.bv_val++;
2501                                 left.bv_len--;
2502
2503                                 goto retry;
2504                         }
2505
2506                         left.bv_val += sub->sa_any[i]->bv_len;
2507                         left.bv_len -= sub->sa_any[i]->bv_len;
2508                         inlen -= sub->sa_any[i]->bv_len;
2509                 }
2510         }
2511
2512 done:
2513         *matchp = match;
2514         return LDAP_SUCCESS;
2515 }
2516
2517 /* Index generation function */
2518 int caseIgnoreIA5Indexer(
2519         slap_mask_t use,
2520         slap_mask_t flags,
2521         Syntax *syntax,
2522         MatchingRule *mr,
2523         struct berval *prefix,
2524         struct berval **values,
2525         struct berval ***keysp )
2526 {
2527         int i;
2528         size_t slen, mlen;
2529         struct berval **keys;
2530         lutil_MD5_CTX   MD5context;
2531         unsigned char   MD5digest[16];
2532         struct berval digest;
2533         digest.bv_val = MD5digest;
2534         digest.bv_len = sizeof(MD5digest);
2535
2536         for( i=0; values[i] != NULL; i++ ) {
2537                 /* just count them */
2538         }
2539
2540         assert( i > 0 );
2541
2542         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
2543
2544         slen = strlen( syntax->ssyn_oid );
2545         mlen = strlen( mr->smr_oid );
2546
2547         for( i=0; values[i] != NULL; i++ ) {
2548                 struct berval *value = ber_bvdup( values[i] );
2549                 ldap_pvt_str2upper( value->bv_val );
2550
2551                 lutil_MD5Init( &MD5context );
2552                 if( prefix != NULL && prefix->bv_len > 0 ) {
2553                         lutil_MD5Update( &MD5context,
2554                                 prefix->bv_val, prefix->bv_len );
2555                 }
2556                 lutil_MD5Update( &MD5context,
2557                         syntax->ssyn_oid, slen );
2558                 lutil_MD5Update( &MD5context,
2559                         mr->smr_oid, mlen );
2560                 lutil_MD5Update( &MD5context,
2561                         value->bv_val, value->bv_len );
2562                 lutil_MD5Final( MD5digest, &MD5context );
2563
2564                 ber_bvfree( value );
2565
2566                 keys[i] = ber_bvdup( &digest );
2567         }
2568
2569         keys[i] = NULL;
2570         *keysp = keys;
2571         return LDAP_SUCCESS;
2572 }
2573
2574 /* Index generation function */
2575 int caseIgnoreIA5Filter(
2576         slap_mask_t use,
2577         slap_mask_t flags,
2578         Syntax *syntax,
2579         MatchingRule *mr,
2580         struct berval *prefix,
2581         void * assertValue,
2582         struct berval ***keysp )
2583 {
2584         size_t slen, mlen;
2585         struct berval **keys;
2586         lutil_MD5_CTX   MD5context;
2587         unsigned char   MD5digest[LUTIL_MD5_BYTES];
2588         struct berval *value;
2589         struct berval digest;
2590         digest.bv_val = MD5digest;
2591         digest.bv_len = sizeof(MD5digest);
2592
2593         slen = strlen( syntax->ssyn_oid );
2594         mlen = strlen( mr->smr_oid );
2595
2596         value = ber_bvdup( (struct berval *) assertValue );
2597         ldap_pvt_str2upper( value->bv_val );
2598
2599         keys = ch_malloc( sizeof( struct berval * ) * 2 );
2600
2601         lutil_MD5Init( &MD5context );
2602         if( prefix != NULL && prefix->bv_len > 0 ) {
2603                 lutil_MD5Update( &MD5context,
2604                         prefix->bv_val, prefix->bv_len );
2605         }
2606         lutil_MD5Update( &MD5context,
2607                 syntax->ssyn_oid, slen );
2608         lutil_MD5Update( &MD5context,
2609                 mr->smr_oid, mlen );
2610         lutil_MD5Update( &MD5context,
2611                 value->bv_val, value->bv_len );
2612         lutil_MD5Final( MD5digest, &MD5context );
2613
2614         keys[0] = ber_bvdup( &digest );
2615         keys[1] = NULL;
2616
2617         ber_bvfree( value );
2618
2619         *keysp = keys;
2620
2621         return LDAP_SUCCESS;
2622 }
2623
2624 /* Substrings Index generation function */
2625 int caseIgnoreIA5SubstringsIndexer(
2626         slap_mask_t use,
2627         slap_mask_t flags,
2628         Syntax *syntax,
2629         MatchingRule *mr,
2630         struct berval *prefix,
2631         struct berval **values,
2632         struct berval ***keysp )
2633 {
2634         ber_len_t i, nkeys;
2635         size_t slen, mlen;
2636         struct berval **keys;
2637         lutil_MD5_CTX   MD5context;
2638         unsigned char   MD5digest[16];
2639         struct berval digest;
2640         digest.bv_val = MD5digest;
2641         digest.bv_len = sizeof(MD5digest);
2642
2643         nkeys=0;
2644         for( i=0; values[i] != NULL; i++ ) {
2645                 /* count number of indices to generate */
2646                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2647                         continue;
2648                 }
2649
2650                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2651                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2652                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2653                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2654                         } else {
2655                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2656                         }
2657                 }
2658
2659                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2660                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2661                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2662                         }
2663                 }
2664
2665                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2666                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2667                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2668                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2669                         } else {
2670                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2671                         }
2672                 }
2673         }
2674         assert( i > 0 );
2675
2676         if( nkeys == 0 ) {
2677                 /* no keys to generate */
2678                 *keysp = NULL;
2679                 return LDAP_SUCCESS;
2680         }
2681
2682         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2683
2684         slen = strlen( syntax->ssyn_oid );
2685         mlen = strlen( mr->smr_oid );
2686
2687         nkeys=0;
2688         for( i=0; values[i] != NULL; i++ ) {
2689                 int j,max;
2690                 struct berval *value;
2691
2692                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2693
2694                 value = ber_bvdup( values[i] );
2695                 ldap_pvt_str2upper( value->bv_val );
2696
2697                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2698                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2699                 {
2700                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
2701                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2702
2703                         for( j=0; j<max; j++ ) {
2704                                 lutil_MD5Init( &MD5context );
2705                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2706                                         lutil_MD5Update( &MD5context,
2707                                                 prefix->bv_val, prefix->bv_len );
2708                                 }
2709                                 lutil_MD5Update( &MD5context,
2710                                         &pre, sizeof( pre ) );
2711                                 lutil_MD5Update( &MD5context,
2712                                         syntax->ssyn_oid, slen );
2713                                 lutil_MD5Update( &MD5context,
2714                                         mr->smr_oid, mlen );
2715                                 lutil_MD5Update( &MD5context,
2716                                         &value->bv_val[j],
2717                                         SLAP_INDEX_SUBSTR_MAXLEN );
2718                                 lutil_MD5Final( MD5digest, &MD5context );
2719
2720                                 keys[nkeys++] = ber_bvdup( &digest );
2721                         }
2722                 }
2723
2724                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2725                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2726
2727                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2728                         char pre;
2729
2730                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2731                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2732                                 lutil_MD5Init( &MD5context );
2733                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2734                                         lutil_MD5Update( &MD5context,
2735                                                 prefix->bv_val, prefix->bv_len );
2736                                 }
2737                                 lutil_MD5Update( &MD5context,
2738                                         &pre, sizeof( pre ) );
2739                                 lutil_MD5Update( &MD5context,
2740                                         syntax->ssyn_oid, slen );
2741                                 lutil_MD5Update( &MD5context,
2742                                         mr->smr_oid, mlen );
2743                                 lutil_MD5Update( &MD5context,
2744                                         value->bv_val, j );
2745                                 lutil_MD5Final( MD5digest, &MD5context );
2746
2747                                 keys[nkeys++] = ber_bvdup( &digest );
2748                         }
2749
2750                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2751                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2752                                 lutil_MD5Init( &MD5context );
2753                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2754                                         lutil_MD5Update( &MD5context,
2755                                                 prefix->bv_val, prefix->bv_len );
2756                                 }
2757                                 lutil_MD5Update( &MD5context,
2758                                         &pre, sizeof( pre ) );
2759                                 lutil_MD5Update( &MD5context,
2760                                         syntax->ssyn_oid, slen );
2761                                 lutil_MD5Update( &MD5context,
2762                                         mr->smr_oid, mlen );
2763                                 lutil_MD5Update( &MD5context,
2764                                         &value->bv_val[value->bv_len-j], j );
2765                                 lutil_MD5Final( MD5digest, &MD5context );
2766
2767                                 keys[nkeys++] = ber_bvdup( &digest );
2768                         }
2769
2770                 }
2771
2772                 ber_bvfree( value );
2773         }
2774
2775         if( nkeys > 0 ) {
2776                 keys[nkeys] = NULL;
2777                 *keysp = keys;
2778         } else {
2779                 ch_free( keys );
2780                 *keysp = NULL;
2781         }
2782
2783         return LDAP_SUCCESS;
2784 }
2785
2786 int caseIgnoreIA5SubstringsFilter(
2787         slap_mask_t use,
2788         slap_mask_t flags,
2789         Syntax *syntax,
2790         MatchingRule *mr,
2791         struct berval *prefix,
2792         void * assertValue,
2793         struct berval ***keysp )
2794 {
2795         SubstringsAssertion *sa = assertValue;
2796         char pre;
2797         ber_len_t nkeys = 0;
2798         size_t slen, mlen, klen;
2799         struct berval **keys;
2800         lutil_MD5_CTX   MD5context;
2801         unsigned char   MD5digest[LUTIL_MD5_BYTES];
2802         struct berval *value;
2803         struct berval digest;
2804
2805         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
2806                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2807         {
2808                 nkeys++;
2809         }
2810
2811         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
2812                 ber_len_t i;
2813                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2814                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2815                                 /* don't bother accounting for stepping */
2816                                 nkeys += sa->sa_any[i]->bv_len -
2817                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2818                         }
2819                 }
2820         }
2821
2822         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
2823                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2824         {
2825                 nkeys++;
2826         }
2827
2828         if( nkeys == 0 ) {
2829                 *keysp = NULL;
2830                 return LDAP_SUCCESS;
2831         }
2832
2833         digest.bv_val = MD5digest;
2834         digest.bv_len = sizeof(MD5digest);
2835
2836         slen = strlen( syntax->ssyn_oid );
2837         mlen = strlen( mr->smr_oid );
2838
2839         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2840         nkeys = 0;
2841
2842         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
2843                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2844         {
2845                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2846                 value = ber_bvdup( sa->sa_initial );
2847                 ldap_pvt_str2upper( value->bv_val );
2848
2849                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2850                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2851
2852                 lutil_MD5Init( &MD5context );
2853                 if( prefix != NULL && prefix->bv_len > 0 ) {
2854                         lutil_MD5Update( &MD5context,
2855                                 prefix->bv_val, prefix->bv_len );
2856                 }
2857                 lutil_MD5Update( &MD5context,
2858                         &pre, sizeof( pre ) );
2859                 lutil_MD5Update( &MD5context,
2860                         syntax->ssyn_oid, slen );
2861                 lutil_MD5Update( &MD5context,
2862                         mr->smr_oid, mlen );
2863                 lutil_MD5Update( &MD5context,
2864                         value->bv_val, klen );
2865                 lutil_MD5Final( MD5digest, &MD5context );
2866
2867                 ber_bvfree( value );
2868                 keys[nkeys++] = ber_bvdup( &digest );
2869         }
2870
2871         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
2872                 ber_len_t i, j;
2873                 pre = SLAP_INDEX_SUBSTR_PREFIX;
2874                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2875
2876                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2877                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2878                                 continue;
2879                         }
2880
2881                         value = ber_bvdup( sa->sa_any[i] );
2882                         ldap_pvt_str2upper( value->bv_val );
2883
2884                         for(j=0;
2885                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2886                                 j += SLAP_INDEX_SUBSTR_STEP )
2887                         {
2888                                 lutil_MD5Init( &MD5context );
2889                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2890                                         lutil_MD5Update( &MD5context,
2891                                                 prefix->bv_val, prefix->bv_len );
2892                                 }
2893                                 lutil_MD5Update( &MD5context,
2894                                         &pre, sizeof( pre ) );
2895                                 lutil_MD5Update( &MD5context,
2896                                         syntax->ssyn_oid, slen );
2897                                 lutil_MD5Update( &MD5context,
2898                                         mr->smr_oid, mlen );
2899                                 lutil_MD5Update( &MD5context,
2900                                         &value->bv_val[j], klen );
2901                                 lutil_MD5Final( MD5digest, &MD5context );
2902
2903                                 keys[nkeys++] = ber_bvdup( &digest );
2904                         }
2905
2906                         ber_bvfree( value );
2907                 }
2908         }
2909
2910         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
2911                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2912         {
2913                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2914                 value = ber_bvdup( sa->sa_final );
2915                 ldap_pvt_str2upper( value->bv_val );
2916
2917                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2918                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2919
2920                 lutil_MD5Init( &MD5context );
2921                 if( prefix != NULL && prefix->bv_len > 0 ) {
2922                         lutil_MD5Update( &MD5context,
2923                                 prefix->bv_val, prefix->bv_len );
2924                 }
2925                 lutil_MD5Update( &MD5context,
2926                         &pre, sizeof( pre ) );
2927                 lutil_MD5Update( &MD5context,
2928                         syntax->ssyn_oid, slen );
2929                 lutil_MD5Update( &MD5context,
2930                         mr->smr_oid, mlen );
2931                 lutil_MD5Update( &MD5context,
2932                         &value->bv_val[value->bv_len-klen], klen );
2933                 lutil_MD5Final( MD5digest, &MD5context );
2934
2935                 ber_bvfree( value );
2936                 keys[nkeys++] = ber_bvdup( &digest );
2937         }
2938
2939         if( nkeys > 0 ) {
2940                 keys[nkeys] = NULL;
2941                 *keysp = keys;
2942         } else {
2943                 ch_free( keys );
2944                 *keysp = NULL;
2945         }
2946
2947         return LDAP_SUCCESS;
2948 }
2949         
2950 static int
2951 numericStringNormalize(
2952         Syntax *syntax,
2953         struct berval *val,
2954         struct berval **normalized )
2955 {
2956         /* similiar to IA5StringNormalize except removes all spaces */
2957         struct berval *newval;
2958         char *p, *q;
2959
2960         newval = ch_malloc( sizeof( struct berval ) );
2961
2962         p = val->bv_val;
2963
2964         /* Ignore initial whitespace */
2965         while ( ASCII_SPACE( *p ) ) {
2966                 p++;
2967         }
2968
2969         if( *p == '\0' ) {
2970                 ch_free( newval );
2971                 return LDAP_INVALID_SYNTAX;
2972         }
2973
2974         newval->bv_val = ch_strdup( p );
2975         p = q = newval->bv_val;
2976
2977         while ( *p ) {
2978                 if ( ASCII_SPACE( *p ) ) {
2979                         /* Ignore whitespace */
2980                         p++;
2981                 } else {
2982                         *q++ = *p++;
2983                 }
2984         }
2985
2986         assert( *newval->bv_val );
2987         assert( newval->bv_val < p );
2988         assert( q <= p );
2989
2990         /* cannot start with a space */
2991         assert( !ASCII_SPACE(*newval->bv_val) );
2992
2993         /* cannot end with a space */
2994         assert( !ASCII_SPACE( q[-1] ) );
2995
2996         /* null terminate */
2997         *q = '\0';
2998
2999         newval->bv_len = q - newval->bv_val;
3000         *normalized = newval;
3001
3002         return LDAP_SUCCESS;
3003 }
3004
3005 static int
3006 objectIdentifierFirstComponentMatch(
3007         int *matchp,
3008         slap_mask_t flags,
3009         Syntax *syntax,
3010         MatchingRule *mr,
3011         struct berval *value,
3012         void *assertedValue )
3013 {
3014         int rc = LDAP_SUCCESS;
3015         int match;
3016         struct berval *asserted = (struct berval *) assertedValue;
3017         ber_len_t i;
3018         struct berval oid;
3019
3020         if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3021                 return LDAP_INVALID_SYNTAX;
3022         }
3023
3024         /* trim leading white space */
3025         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3026                 /* empty */
3027         }
3028
3029         /* grab next word */
3030         oid.bv_val = &value->bv_val[i];
3031         oid.bv_len = value->bv_len - i;
3032         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3033                 /* empty */
3034         }
3035         oid.bv_len = i;
3036
3037         /* insert attributeTypes, objectclass check here */
3038         if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3039                 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3040
3041         } else {
3042                 char *stored = ch_malloc( oid.bv_len + 1 );
3043                 AC_MEMCPY( stored, oid.bv_val, oid.bv_len );
3044                 stored[oid.bv_len] = '\0';
3045
3046                 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3047                         MatchingRule *asserted_mr = mr_find( asserted->bv_val );
3048                         MatchingRule *stored_mr = mr_find( stored );
3049
3050                         if( asserted_mr == NULL ) {
3051                                 rc = SLAPD_COMPARE_UNDEFINED;
3052                         } else {
3053                                 match = asserted_mr != stored_mr;
3054                         }
3055
3056                 } else if ( !strcmp( syntax->ssyn_oid,
3057                         SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3058                 {
3059                         AttributeType *asserted_at = at_find( asserted->bv_val );
3060                         AttributeType *stored_at = at_find( stored );
3061
3062                         if( asserted_at == NULL ) {
3063                                 rc = SLAPD_COMPARE_UNDEFINED;
3064                         } else {
3065                                 match = asserted_at != stored_at;
3066                         }
3067
3068                 } else if ( !strcmp( syntax->ssyn_oid,
3069                         SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3070                 {
3071                         ObjectClass *asserted_oc = oc_find( asserted->bv_val );
3072                         ObjectClass *stored_oc = oc_find( stored );
3073
3074                         if( asserted_oc == NULL ) {
3075                                 rc = SLAPD_COMPARE_UNDEFINED;
3076                         } else {
3077                                 match = asserted_oc != stored_oc;
3078                         }
3079                 }
3080
3081                 ch_free( stored );
3082         }
3083
3084         Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3085                 "%d\n\t\"%s\"\n\t\"%s\"\n",
3086             match, value->bv_val, asserted->bv_val );
3087
3088         if( rc == LDAP_SUCCESS ) *matchp = match;
3089         return rc;
3090 }
3091
3092 static int
3093 check_time_syntax (struct berval *val,
3094         int start,
3095         int *parts)
3096 {
3097         static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3098         static int mdays[2][12] = {
3099                 /* non-leap years */
3100                 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3101                 /* leap years */
3102                 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3103         };
3104         char *p, *e;
3105         int part, c, tzoffset, leapyear = 0 ;
3106
3107         if( val->bv_len == 0 ) {
3108                 return LDAP_INVALID_SYNTAX;
3109         }
3110
3111         p = (char *)val->bv_val;
3112         e = p + val->bv_len;
3113
3114         /* Ignore initial whitespace */
3115         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3116                 p++;
3117         }
3118
3119         if (e - p < 13 - (2 * start)) {
3120                 return LDAP_INVALID_SYNTAX;
3121         }
3122
3123         for (part = 0; part < 9; part++) {
3124                 parts[part] = 0;
3125         }
3126
3127         for (part = start; part < 7; part++) {
3128                 c = *p;
3129                 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3130                         part++;
3131                         break;
3132                 }
3133                 p++;
3134                 c -= '0';
3135                 if (p == e) {
3136                         return LDAP_INVALID_SYNTAX;
3137                 }
3138                 if (c < 0 || c > 9) {
3139                         return LDAP_INVALID_SYNTAX;
3140                 }
3141                 parts[part] = c;
3142
3143                 c = *p++ - '0';
3144                 if (p == e) {
3145                         return LDAP_INVALID_SYNTAX;
3146                 }
3147                 if (c < 0 || c > 9) {
3148                         return LDAP_INVALID_SYNTAX;
3149                 }
3150                 parts[part] *= 10;
3151                 parts[part] += c;
3152
3153                 if (part == 2 || part == 3) {
3154                         parts[part]--;
3155                 }
3156                 if (parts[part] < 0) {
3157                         return LDAP_INVALID_SYNTAX;
3158                 }
3159                 if (parts[part] > ceiling[part]) {
3160                         return LDAP_INVALID_SYNTAX;
3161                 }
3162         }
3163
3164         /* leapyear check for the Gregorian calendar (year>1581) */
3165         if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
3166                 ((parts[0] % 4 == 0) && (parts[1] == 0)))
3167         {
3168                 leapyear = 1;
3169         }
3170
3171         if (parts[3] > mdays[leapyear][parts[2]]) {
3172                 return LDAP_INVALID_SYNTAX;
3173         }
3174         
3175         c = *p++;
3176         if (c == 'Z') {
3177                 tzoffset = 0; /* UTC */
3178         } else if (c != '+' && c != '-') {
3179                 return LDAP_INVALID_SYNTAX;
3180         } else {
3181                 if (c == '-') {
3182                         tzoffset = -1;
3183                 } else /* c == '+' */ {
3184                         tzoffset = 1;
3185                 }
3186
3187                 if (p > e - 4) {
3188                         return LDAP_INVALID_SYNTAX;
3189                 }
3190
3191                 for (part = 7; part < 9; part++) {
3192                         c = *p++ - '0';
3193                         if (c < 0 || c > 9) {
3194                                 return LDAP_INVALID_SYNTAX;
3195                         }
3196                         parts[part] = c;
3197
3198                         c = *p++ - '0';
3199                         if (c < 0 || c > 9) {
3200                                 return LDAP_INVALID_SYNTAX;
3201                         }
3202                         parts[part] *= 10;
3203                         parts[part] += c;
3204                         if (parts[part] < 0 || parts[part] > ceiling[part]) {
3205                                 return LDAP_INVALID_SYNTAX;
3206                         }
3207                 }
3208         }
3209
3210         /* Ignore trailing whitespace */
3211         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3212                 p++;
3213         }
3214         if (p != e) {
3215                 return LDAP_INVALID_SYNTAX;
3216         }
3217
3218         switch ( tzoffset ) {
3219         case -1: /* negativ offset to UTC, ie west of Greenwich  */
3220                 parts[4] += parts[7];
3221                 parts[5] += parts[8];
3222                 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
3223                         if (part != 3) {
3224                                 c = ceiling[part];
3225                         } else {
3226                                 c = mdays[leapyear][parts[2]];
3227                         }
3228                         if (parts[part] > c) {
3229                                 parts[part] -= c + 1;
3230                                 parts[part - 1]++;
3231                         }
3232                 }
3233                 break;
3234         case 1: /* positive offset to UTC, ie east of Greenwich */
3235                 parts[4] -= parts[7];
3236                 parts[5] -= parts[8];
3237                 for (part = 6; --part > 0; ) {
3238                         if (part != 3) {
3239                                 c = ceiling[part];
3240                         } else {
3241                                 /* first arg to % needs to be non negativ */
3242                                 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3243                         }
3244                         if (parts[part] < 0) {
3245                                 parts[part] += c + 1;
3246                                 parts[part - 1]--;
3247                         }
3248                 }
3249                 break;
3250         case 0: /* already UTC */
3251                 break;
3252         }
3253
3254         return LDAP_SUCCESS;
3255 }
3256
3257 static int
3258 utcTimeNormalize(
3259         Syntax *syntax,
3260         struct berval *val,
3261         struct berval **normalized )
3262 {
3263         struct berval *out;
3264         int parts[9], rc;
3265
3266         rc = check_time_syntax(val, 1, parts);
3267         if (rc != LDAP_SUCCESS) {
3268                 return rc;
3269         }
3270
3271         *normalized = NULL;
3272         out = ch_malloc( sizeof(struct berval) );
3273         if( out == NULL ) {
3274                 return LBER_ERROR_MEMORY;
3275         }
3276
3277         out->bv_val = ch_malloc( 14 );
3278         if ( out->bv_val == NULL ) {
3279                 ch_free( out );
3280                 return LBER_ERROR_MEMORY;
3281         }
3282
3283         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ldZ",
3284                 parts[1], parts[2] + 1, parts[3] + 1,
3285                 parts[4], parts[5], parts[6] );
3286         out->bv_len = 13;
3287         *normalized = out;
3288
3289         return LDAP_SUCCESS;
3290 }
3291
3292 static int
3293 utcTimeValidate(
3294         Syntax *syntax,
3295         struct berval *in )
3296 {
3297         int parts[9];
3298
3299         return check_time_syntax(in, 1, parts);
3300 }
3301
3302 static int
3303 generalizedTimeValidate(
3304         Syntax *syntax,
3305         struct berval *in )
3306 {
3307         int parts[9];
3308
3309         return check_time_syntax(in, 0, parts);
3310 }
3311
3312 static int
3313 generalizedTimeNormalize(
3314         Syntax *syntax,
3315         struct berval *val,
3316         struct berval **normalized )
3317 {
3318         struct berval *out;
3319         int parts[9], rc;
3320
3321         rc = check_time_syntax(val, 0, parts);
3322         if (rc != LDAP_SUCCESS) {
3323                 return rc;
3324         }
3325
3326         *normalized = NULL;
3327         out = ch_malloc( sizeof(struct berval) );
3328         if( out == NULL ) {
3329                 return LBER_ERROR_MEMORY;
3330         }
3331
3332         out->bv_val = ch_malloc( 16 );
3333         if ( out->bv_val == NULL ) {
3334                 ch_free( out );
3335                 return LBER_ERROR_MEMORY;
3336         }
3337
3338         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ld%02ldZ",
3339                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3340                 parts[4], parts[5], parts[6] );
3341         out->bv_len = 15;
3342         *normalized = out;
3343
3344         return LDAP_SUCCESS;
3345 }
3346
3347 static int
3348 nisNetgroupTripleValidate(
3349         Syntax *syntax,
3350         struct berval *val )
3351 {
3352         char *p, *e;
3353         int commas = 0;
3354
3355         if ( val->bv_len == 0 ) {
3356                 return LDAP_INVALID_SYNTAX;
3357         }
3358
3359         p = (char *)val->bv_val;
3360         e = p + val->bv_len;
3361
3362 #if 0
3363         /* syntax does not allow leading white space */
3364         /* Ignore initial whitespace */
3365         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3366                 p++;
3367         }
3368 #endif
3369
3370         if ( *p != '(' /*')'*/ ) {
3371                 return LDAP_INVALID_SYNTAX;
3372         }
3373
3374         for ( p++; ( p < e ) && ( *p != ')' ); p++ ) {
3375                 if ( *p == ',' ) {
3376                         commas++;
3377                         if ( commas > 2 ) {
3378                                 return LDAP_INVALID_SYNTAX;
3379                         }
3380
3381                 } else if ( !ATTR_CHAR( *p ) ) {
3382                         return LDAP_INVALID_SYNTAX;
3383                 }
3384         }
3385
3386         if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
3387                 return LDAP_INVALID_SYNTAX;
3388         }
3389
3390         p++;
3391
3392 #if 0
3393         /* syntax does not allow trailing white space */
3394         /* Ignore trailing whitespace */
3395         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3396                 p++;
3397         }
3398 #endif
3399
3400         if (p != e) {
3401                 return LDAP_INVALID_SYNTAX;
3402         }
3403
3404         return LDAP_SUCCESS;
3405 }
3406
3407 static int
3408 bootParameterValidate(
3409         Syntax *syntax,
3410         struct berval *val )
3411 {
3412         char *p, *e;
3413
3414         if ( val->bv_len == 0 ) {
3415                 return LDAP_INVALID_SYNTAX;
3416         }
3417
3418         p = (char *)val->bv_val;
3419         e = p + val->bv_len;
3420
3421         /* key */
3422         for (; ( p < e ) && ( *p != '=' ); p++ ) {
3423                 if ( !ATTR_CHAR( *p ) ) {
3424                         return LDAP_INVALID_SYNTAX;
3425                 }
3426         }
3427
3428         if ( *p != '=' ) {
3429                 return LDAP_INVALID_SYNTAX;
3430         }
3431
3432         /* server */
3433         for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
3434                 if ( !ATTR_CHAR( *p ) ) {
3435                         return LDAP_INVALID_SYNTAX;
3436                 }
3437         }
3438
3439         if ( *p != ':' ) {
3440                 return LDAP_INVALID_SYNTAX;
3441         }
3442
3443         /* path */
3444         for ( p++; p < e; p++ ) {
3445                 if ( !ATTR_CHAR( *p ) ) {
3446                         return LDAP_INVALID_SYNTAX;
3447                 }
3448         }
3449
3450         return LDAP_SUCCESS;
3451 }
3452
3453 struct syntax_defs_rec {
3454         char *sd_desc;
3455         int sd_flags;
3456         slap_syntax_validate_func *sd_validate;
3457         slap_syntax_transform_func *sd_normalize;
3458         slap_syntax_transform_func *sd_pretty;
3459 #ifdef SLAPD_BINARY_CONVERSION
3460         slap_syntax_transform_func *sd_ber2str;
3461         slap_syntax_transform_func *sd_str2ber;
3462 #endif
3463 };
3464
3465 #define X_HIDE "X-HIDE 'TRUE' "
3466 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
3467 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
3468
3469 struct syntax_defs_rec syntax_defs[] = {
3470         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
3471                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
3472         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
3473                 0, NULL, NULL, NULL},
3474         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
3475                 0, NULL, NULL, NULL},
3476         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
3477                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
3478         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_BINARY X_NOT_H_R ")",
3479                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
3480         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
3481                 0, bitStringValidate, bitStringNormalize, NULL },
3482         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
3483                 0, booleanValidate, NULL, NULL},
3484         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
3485                 X_BINARY X_NOT_H_R ")",
3486                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
3487         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
3488                 X_BINARY X_NOT_H_R ")",
3489                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
3490         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
3491                 X_BINARY X_NOT_H_R ")",
3492                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
3493         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
3494                 0, NULL, NULL, NULL},
3495         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
3496                 0, dnValidate, dnNormalize, dnPretty},
3497         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
3498                 0, NULL, NULL, NULL},
3499         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
3500                 0, NULL, NULL, NULL},
3501         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
3502                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
3503         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
3504                 0, NULL, NULL, NULL},
3505         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
3506                 0, NULL, NULL, NULL},
3507         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
3508                 0, NULL, NULL, NULL},
3509         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
3510                 0, NULL, NULL, NULL},
3511         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
3512                 0, NULL, NULL, NULL},
3513         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
3514                 0, IA5StringValidate, faxNumberNormalize, NULL},
3515         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
3516                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
3517         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
3518                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
3519         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
3520                 0, NULL, NULL, NULL},
3521         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
3522                 0, IA5StringValidate, IA5StringNormalize, NULL},
3523         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
3524                 0, integerValidate, integerNormalize, integerPretty},
3525         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
3526                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
3527         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
3528                 0, NULL, NULL, NULL},
3529         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
3530                 0, NULL, NULL, NULL},
3531         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
3532                 0, NULL, NULL, NULL},
3533         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
3534                 0, NULL, NULL, NULL},
3535         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
3536                 0, NULL, NULL, NULL},
3537         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
3538                 0, nameUIDValidate, nameUIDNormalize, nameUIDPretty},
3539         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
3540                 0, NULL, NULL, NULL},
3541         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
3542                 0, IA5StringValidate, numericStringNormalize, NULL},
3543         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
3544                 0, NULL, NULL, NULL},
3545         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
3546                 0, oidValidate, NULL, NULL},
3547         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
3548                 0, NULL, NULL, NULL},
3549         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
3550                 0, blobValidate, NULL, NULL},
3551         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
3552                 0, blobValidate, NULL, NULL},
3553         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
3554                 0, NULL, NULL, NULL},
3555         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
3556                 0, NULL, NULL, NULL},
3557         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
3558                 0, printableStringValidate, NULL, NULL},
3559         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
3560                 X_BINARY X_NOT_H_R ")",
3561                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
3562         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
3563                 0, IA5StringValidate, phoneNumberNormalize, NULL},
3564         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
3565                 0, NULL, NULL, NULL},
3566         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
3567                 0, IA5StringValidate, telexNumberNormalize, NULL},
3568         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
3569                 0, utcTimeValidate, utcTimeNormalize, NULL},
3570         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
3571                 0, NULL, NULL, NULL},
3572         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
3573                 0, NULL, NULL, NULL},
3574         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
3575                 0, NULL, NULL, NULL},
3576         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
3577                 0, NULL, NULL, NULL},
3578         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
3579                 0, NULL, NULL, NULL},
3580
3581         /* RFC 2307 NIS Syntaxes */
3582         {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Triple' )",
3583                 0, nisNetgroupTripleValidate, NULL, NULL},
3584         {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
3585                 0, bootParameterValidate, NULL, NULL},
3586
3587         /* OpenLDAP Experimental Syntaxes */
3588         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
3589                 0, IA5StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
3590                 NULL, NULL},
3591         {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
3592                 0, NULL, NULL, NULL},
3593
3594         /* OpenLDAP Void Syntax */
3595         {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' " X_HIDE ")" ,
3596                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
3597         {NULL, 0, NULL, NULL, NULL}
3598 };
3599
3600 struct mrule_defs_rec {
3601         char *                                          mrd_desc;
3602         slap_mask_t                                     mrd_usage;
3603         slap_mr_convert_func *          mrd_convert;
3604         slap_mr_normalize_func *        mrd_normalize;
3605         slap_mr_match_func *            mrd_match;
3606         slap_mr_indexer_func *          mrd_indexer;
3607         slap_mr_filter_func *           mrd_filter;
3608
3609         char *                                          mrd_associated;
3610 };
3611
3612 /*
3613  * Other matching rules in X.520 that we do not use (yet):
3614  *
3615  * 2.5.13.9             numericStringOrderingMatch
3616  * 2.5.13.13    booleanMatch
3617  * 2.5.13.15    integerOrderingMatch
3618  * 2.5.13.18    octetStringOrderingMatch
3619  * 2.5.13.19    octetStringSubstringsMatch
3620  * 2.5.13.25    uTCTimeMatch
3621  * 2.5.13.26    uTCTimeOrderingMatch
3622  * 2.5.13.31    directoryStringFirstComponentMatch
3623  * 2.5.13.32    wordMatch
3624  * 2.5.13.33    keywordMatch
3625  * 2.5.13.34    certificateExactMatch
3626  * 2.5.13.35    certificateMatch
3627  * 2.5.13.36    certificatePairExactMatch
3628  * 2.5.13.37    certificatePairMatch
3629  * 2.5.13.38    certificateListExactMatch
3630  * 2.5.13.39    certificateListMatch
3631  * 2.5.13.40    algorithmIdentifierMatch
3632  * 2.5.13.41    storedPrefixMatch
3633  * 2.5.13.42    attributeCertificateMatch
3634  * 2.5.13.43    readerAndKeyIDMatch
3635  * 2.5.13.44    attributeIntegrityMatch
3636  */
3637
3638 struct mrule_defs_rec mrule_defs[] = {
3639         /*
3640          * EQUALITY matching rules must be listed after associated APPROX
3641          * matching rules.  So, we list all APPROX matching rules first.
3642          */
3643         {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
3644                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3645                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
3646                 NULL, NULL,
3647                 directoryStringApproxMatch, NULL, NULL,
3648                 NULL},
3649
3650         {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
3651                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3652                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
3653                 NULL, NULL,
3654                 IA5StringApproxMatch, NULL, NULL,
3655                 NULL},
3656
3657         /*
3658          * Other matching rules
3659          */
3660         
3661         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
3662                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3663                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3664                 NULL, NULL,
3665                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
3666                 NULL},
3667
3668         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
3669                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
3670                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3671                 NULL, NULL,
3672                 dnMatch, dnIndexer, dnFilter,
3673                 NULL},
3674
3675         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
3676                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3677                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3678                 NULL, NULL,
3679                 caseIgnoreMatch, caseIgnoreIndexer, caseIgnoreFilter,
3680                 directoryStringApproxMatchOID },
3681
3682         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
3683                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3684                 SLAP_MR_ORDERING,
3685                 NULL, NULL,
3686                 caseIgnoreOrderingMatch, NULL, NULL,
3687                 NULL},
3688
3689         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
3690                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3691                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
3692                 NULL, NULL,
3693                 caseIgnoreSubstringsMatch,
3694                 caseIgnoreSubstringsIndexer,
3695                 caseIgnoreSubstringsFilter,
3696                 NULL},
3697
3698         {"( 2.5.13.5 NAME 'caseExactMatch' "
3699                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3700                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3701                 NULL, NULL,
3702                 caseExactMatch, caseExactIndexer, caseExactFilter,
3703                 directoryStringApproxMatchOID },
3704
3705         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
3706                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
3707                 SLAP_MR_ORDERING,
3708                 NULL, NULL,
3709                 caseExactOrderingMatch, NULL, NULL,
3710                 NULL},
3711
3712         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
3713                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3714                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
3715                 NULL, NULL,
3716                 caseExactSubstringsMatch,
3717                 caseExactSubstringsIndexer,
3718                 caseExactSubstringsFilter,
3719                 NULL},
3720
3721         {"( 2.5.13.8 NAME 'numericStringMatch' "
3722                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
3723                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3724                 NULL, NULL,
3725                 caseIgnoreIA5Match, NULL, NULL,
3726                 NULL},
3727
3728         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
3729                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3730                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
3731                 NULL, NULL,
3732                 caseIgnoreIA5SubstringsMatch,
3733                 caseIgnoreIA5SubstringsIndexer,
3734                 caseIgnoreIA5SubstringsFilter,
3735                 NULL},
3736
3737         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
3738                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
3739                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3740                 NULL, NULL,
3741                 caseIgnoreListMatch, NULL, NULL,
3742                 NULL},
3743
3744         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
3745                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3746                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
3747                 NULL, NULL,
3748                 caseIgnoreListSubstringsMatch, NULL, NULL,
3749                 NULL},
3750
3751         {"( 2.5.13.13 NAME 'booleanMatch' "
3752                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
3753                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3754                 NULL, NULL,
3755                 booleanMatch, NULL, NULL,
3756                 NULL},
3757
3758         {"( 2.5.13.14 NAME 'integerMatch' "
3759                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3760                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3761                 NULL, NULL,
3762                 integerMatch, NULL, NULL,
3763                 NULL},
3764
3765         {"( 2.5.13.16 NAME 'bitStringMatch' "
3766                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
3767                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3768                 NULL, NULL,
3769                 bitStringMatch, NULL, NULL,
3770                 NULL},
3771
3772         {"( 2.5.13.17 NAME 'octetStringMatch' "
3773                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3774                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3775                 NULL, NULL,
3776                 octetStringMatch, octetStringIndexer, octetStringFilter,
3777                 NULL},
3778
3779         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3780                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3781                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3782                 NULL, NULL,
3783                 telephoneNumberMatch, NULL, NULL,
3784                 NULL},
3785
3786         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3787                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3788                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
3789                 NULL, NULL,
3790                 telephoneNumberSubstringsMatch, NULL, NULL,
3791                 NULL},
3792
3793         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3794                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3795                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3796                 NULL, NULL,
3797                 presentationAddressMatch, NULL, NULL,
3798                 NULL},
3799
3800         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3801                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3802                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3803                 NULL, NULL,
3804                 uniqueMemberMatch, NULL, NULL,
3805                 NULL},
3806
3807         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3808                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3809                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3810                 NULL, NULL,
3811                 protocolInformationMatch, NULL, NULL,
3812                 NULL},
3813
3814         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3815                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3816                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3817                 NULL, NULL,
3818                 generalizedTimeMatch, NULL, NULL,
3819                 NULL},
3820
3821         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3822                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3823                 SLAP_MR_ORDERING,
3824                 NULL, NULL,
3825                 generalizedTimeOrderingMatch, NULL, NULL,
3826                 NULL},
3827
3828         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3829                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3830                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3831                 NULL, NULL,
3832                 integerFirstComponentMatch, NULL, NULL,
3833                 NULL},
3834
3835         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3836                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3837                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3838                 NULL, NULL,
3839                 objectIdentifierFirstComponentMatch, NULL, NULL,
3840                 NULL},
3841
3842         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3843                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3844                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3845                 NULL, NULL,
3846                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
3847                 IA5StringApproxMatchOID },
3848
3849         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3850                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3851                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3852                 NULL, NULL,
3853                 caseIgnoreIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
3854                 IA5StringApproxMatchOID },
3855
3856         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3857                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3858                 SLAP_MR_SUBSTR,
3859                 NULL, NULL,
3860                 caseIgnoreIA5SubstringsMatch,
3861                 caseIgnoreIA5SubstringsIndexer,
3862                 caseIgnoreIA5SubstringsFilter,
3863                 NULL},
3864
3865         {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3866                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3867                 SLAP_MR_SUBSTR,
3868                 NULL, NULL,
3869                 caseExactIA5SubstringsMatch,
3870                 caseExactIA5SubstringsIndexer,
3871                 caseExactIA5SubstringsFilter,
3872                 NULL},
3873
3874         {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3875                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3876                 SLAP_MR_EQUALITY,
3877                 NULL, NULL,
3878                 authPasswordMatch, NULL, NULL,
3879                 NULL},
3880
3881         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3882                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3883                 SLAP_MR_EQUALITY,
3884                 NULL, NULL,
3885                 OpenLDAPaciMatch, NULL, NULL,
3886                 NULL},
3887
3888         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
3889 };
3890
3891 int
3892 schema_init( void )
3893 {
3894         int             res;
3895         int             i;
3896
3897         /* we should only be called once (from main) */
3898         assert( schema_init_done == 0 );
3899
3900         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3901                 res = register_syntax( syntax_defs[i].sd_desc,
3902                     syntax_defs[i].sd_flags,
3903                     syntax_defs[i].sd_validate,
3904                     syntax_defs[i].sd_normalize,
3905                         syntax_defs[i].sd_pretty
3906 #ifdef SLAPD_BINARY_CONVERSION
3907                         ,
3908                     syntax_defs[i].sd_ber2str,
3909                         syntax_defs[i].sd_str2ber
3910 #endif
3911                 );
3912
3913                 if ( res ) {
3914                         fprintf( stderr, "schema_init: Error registering syntax %s\n",
3915                                  syntax_defs[i].sd_desc );
3916                         return LDAP_OTHER;
3917                 }
3918         }
3919
3920         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3921                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
3922                         fprintf( stderr,
3923                                 "schema_init: Ingoring unusable matching rule %s\n",
3924                                  mrule_defs[i].mrd_desc );
3925                         continue;
3926                 }
3927
3928                 res = register_matching_rule(
3929                         mrule_defs[i].mrd_desc,
3930                         mrule_defs[i].mrd_usage,
3931                         mrule_defs[i].mrd_convert,
3932                         mrule_defs[i].mrd_normalize,
3933                     mrule_defs[i].mrd_match,
3934                         mrule_defs[i].mrd_indexer,
3935                         mrule_defs[i].mrd_filter,
3936                         mrule_defs[i].mrd_associated );
3937
3938                 if ( res ) {
3939                         fprintf( stderr,
3940                                 "schema_init: Error registering matching rule %s\n",
3941                                  mrule_defs[i].mrd_desc );
3942                         return LDAP_OTHER;
3943                 }
3944         }
3945         schema_init_done = 1;
3946         return LDAP_SUCCESS;
3947 }