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