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