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