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