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