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