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