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