]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
Add 'distinct' to sql search query to prevent duplicate entries in results (suggested...
[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( !isprint(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
2329         }
2330
2331         return LDAP_SUCCESS;
2332 }
2333
2334 static int
2335 IA5StringValidate(
2336         Syntax *syntax,
2337         struct berval *val )
2338 {
2339         ber_len_t i;
2340
2341         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2342
2343         for(i=0; i < val->bv_len; i++) {
2344                 if( !isascii(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
2345         }
2346
2347         return LDAP_SUCCESS;
2348 }
2349
2350 static int
2351 IA5StringNormalize(
2352         Syntax *syntax,
2353         struct berval *val,
2354         struct berval **normalized )
2355 {
2356         struct berval *newval;
2357         char *p, *q;
2358
2359         newval = ch_malloc( sizeof( struct berval ) );
2360
2361         p = val->bv_val;
2362
2363         /* Ignore initial whitespace */
2364         while ( ASCII_SPACE( *p ) ) {
2365                 p++;
2366         }
2367
2368         if( *p == '\0' ) {
2369                 ch_free( newval );
2370                 return LDAP_INVALID_SYNTAX;
2371         }
2372
2373         newval->bv_val = ch_strdup( p );
2374         p = q = newval->bv_val;
2375
2376         while ( *p ) {
2377                 if ( ASCII_SPACE( *p ) ) {
2378                         *q++ = *p++;
2379
2380                         /* Ignore the extra whitespace */
2381                         while ( ASCII_SPACE( *p ) ) {
2382                                 p++;
2383                         }
2384                 } else {
2385                         *q++ = *p++;
2386                 }
2387         }
2388
2389         assert( *newval->bv_val );
2390         assert( newval->bv_val < p );
2391         assert( q <= p );
2392
2393         /* cannot start with a space */
2394         assert( !ASCII_SPACE(*newval->bv_val) );
2395
2396         /*
2397          * If the string ended in space, backup the pointer one
2398          * position.  One is enough because the above loop collapsed
2399          * all whitespace to a single space.
2400          */
2401
2402         if ( ASCII_SPACE( q[-1] ) ) {
2403                 --q;
2404         }
2405
2406         /* cannot end with a space */
2407         assert( !ASCII_SPACE( q[-1] ) );
2408
2409         /* null terminate */
2410         *q = '\0';
2411
2412         newval->bv_len = q - newval->bv_val;
2413         *normalized = newval;
2414
2415         return LDAP_SUCCESS;
2416 }
2417
2418 static int
2419 caseExactIA5Match(
2420         int *matchp,
2421         slap_mask_t flags,
2422         Syntax *syntax,
2423         MatchingRule *mr,
2424         struct berval *value,
2425         void *assertedValue )
2426 {
2427         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2428
2429         if( match == 0 ) {
2430                 match = strncmp( value->bv_val,
2431                         ((struct berval *) assertedValue)->bv_val,
2432                         value->bv_len );
2433         }
2434
2435         *matchp = match;
2436         return LDAP_SUCCESS;
2437 }
2438
2439 static int
2440 caseExactIA5SubstringsMatch(
2441         int *matchp,
2442         slap_mask_t flags,
2443         Syntax *syntax,
2444         MatchingRule *mr,
2445         struct berval *value,
2446         void *assertedValue )
2447 {
2448         int match = 0;
2449         SubstringsAssertion *sub = assertedValue;
2450         struct berval left = *value;
2451         int i;
2452         ber_len_t inlen=0;
2453
2454         /* Add up asserted input length */
2455         if( sub->sa_initial ) {
2456                 inlen += sub->sa_initial->bv_len;
2457         }
2458         if( sub->sa_any ) {
2459                 for(i=0; sub->sa_any[i] != NULL; i++) {
2460                         inlen += sub->sa_any[i]->bv_len;
2461                 }
2462         }
2463         if( sub->sa_final ) {
2464                 inlen += sub->sa_final->bv_len;
2465         }
2466
2467         if( sub->sa_initial ) {
2468                 if( inlen > left.bv_len ) {
2469                         match = 1;
2470                         goto done;
2471                 }
2472
2473                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
2474                         sub->sa_initial->bv_len );
2475
2476                 if( match != 0 ) {
2477                         goto done;
2478                 }
2479
2480                 left.bv_val += sub->sa_initial->bv_len;
2481                 left.bv_len -= sub->sa_initial->bv_len;
2482                 inlen -= sub->sa_initial->bv_len;
2483         }
2484
2485         if( sub->sa_final ) {
2486                 if( inlen > left.bv_len ) {
2487                         match = 1;
2488                         goto done;
2489                 }
2490
2491                 match = strncmp( sub->sa_final->bv_val,
2492                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
2493                         sub->sa_final->bv_len );
2494
2495                 if( match != 0 ) {
2496                         goto done;
2497                 }
2498
2499                 left.bv_len -= sub->sa_final->bv_len;
2500                 inlen -= sub->sa_final->bv_len;
2501         }
2502
2503         if( sub->sa_any ) {
2504                 for(i=0; sub->sa_any[i]; i++) {
2505                         ber_len_t idx;
2506                         char *p;
2507
2508 retry:
2509                         if( inlen > left.bv_len ) {
2510                                 /* not enough length */
2511                                 match = 1;
2512                                 goto done;
2513                         }
2514
2515                         if( sub->sa_any[i]->bv_len == 0 ) {
2516                                 continue;
2517                         }
2518
2519                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
2520
2521                         if( p == NULL ) {
2522                                 match = 1;
2523                                 goto done;
2524                         }
2525
2526                         idx = p - left.bv_val;
2527                         assert( idx < left.bv_len );
2528
2529                         if( idx >= left.bv_len ) {
2530                                 /* this shouldn't happen */
2531                                 return LDAP_OTHER;
2532                         }
2533
2534                         left.bv_val = p;
2535                         left.bv_len -= idx;
2536
2537                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
2538                                 /* not enough left */
2539                                 match = 1;
2540                                 goto done;
2541                         }
2542
2543                         match = strncmp( left.bv_val,
2544                                 sub->sa_any[i]->bv_val,
2545                                 sub->sa_any[i]->bv_len );
2546
2547                         if( match != 0 ) {
2548                                 left.bv_val++;
2549                                 left.bv_len--;
2550                                 goto retry;
2551                         }
2552
2553                         left.bv_val += sub->sa_any[i]->bv_len;
2554                         left.bv_len -= sub->sa_any[i]->bv_len;
2555                         inlen -= sub->sa_any[i]->bv_len;
2556                 }
2557         }
2558
2559 done:
2560         *matchp = match;
2561         return LDAP_SUCCESS;
2562 }
2563
2564 /* Index generation function */
2565 int caseExactIA5Indexer(
2566         slap_mask_t use,
2567         slap_mask_t flags,
2568         Syntax *syntax,
2569         MatchingRule *mr,
2570         struct berval *prefix,
2571         struct berval **values,
2572         struct berval ***keysp )
2573 {
2574         int i;
2575         size_t slen, mlen;
2576         struct berval **keys;
2577         HASH_CONTEXT   HASHcontext;
2578         unsigned char   HASHdigest[HASH_BYTES];
2579         struct berval digest;
2580         digest.bv_val = HASHdigest;
2581         digest.bv_len = sizeof(HASHdigest);
2582
2583         /* we should have at least one value at this point */
2584         assert( values != NULL && values[0] != NULL );
2585
2586         for( i=0; values[i] != NULL; i++ ) {
2587                 /* just count them */
2588         }
2589
2590         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
2591
2592         slen = strlen( syntax->ssyn_oid );
2593         mlen = strlen( mr->smr_oid );
2594
2595         for( i=0; values[i] != NULL; i++ ) {
2596                 struct berval *value = values[i];
2597
2598                 HASH_Init( &HASHcontext );
2599                 if( prefix != NULL && prefix->bv_len > 0 ) {
2600                         HASH_Update( &HASHcontext,
2601                                 prefix->bv_val, prefix->bv_len );
2602                 }
2603                 HASH_Update( &HASHcontext,
2604                         syntax->ssyn_oid, slen );
2605                 HASH_Update( &HASHcontext,
2606                         mr->smr_oid, mlen );
2607                 HASH_Update( &HASHcontext,
2608                         value->bv_val, value->bv_len );
2609                 HASH_Final( HASHdigest, &HASHcontext );
2610
2611                 keys[i] = ber_bvdup( &digest );
2612         }
2613
2614         keys[i] = NULL;
2615         *keysp = keys;
2616         return LDAP_SUCCESS;
2617 }
2618
2619 /* Index generation function */
2620 int caseExactIA5Filter(
2621         slap_mask_t use,
2622         slap_mask_t flags,
2623         Syntax *syntax,
2624         MatchingRule *mr,
2625         struct berval *prefix,
2626         void * assertValue,
2627         struct berval ***keysp )
2628 {
2629         size_t slen, mlen;
2630         struct berval **keys;
2631         HASH_CONTEXT   HASHcontext;
2632         unsigned char   HASHdigest[HASH_BYTES];
2633         struct berval *value;
2634         struct berval digest;
2635         digest.bv_val = HASHdigest;
2636         digest.bv_len = sizeof(HASHdigest);
2637
2638         slen = strlen( syntax->ssyn_oid );
2639         mlen = strlen( mr->smr_oid );
2640
2641         value = (struct berval *) assertValue;
2642
2643         keys = ch_malloc( sizeof( struct berval * ) * 2 );
2644
2645         HASH_Init( &HASHcontext );
2646         if( prefix != NULL && prefix->bv_len > 0 ) {
2647                 HASH_Update( &HASHcontext,
2648                         prefix->bv_val, prefix->bv_len );
2649         }
2650         HASH_Update( &HASHcontext,
2651                 syntax->ssyn_oid, slen );
2652         HASH_Update( &HASHcontext,
2653                 mr->smr_oid, mlen );
2654         HASH_Update( &HASHcontext,
2655                 value->bv_val, value->bv_len );
2656         HASH_Final( HASHdigest, &HASHcontext );
2657
2658         keys[0] = ber_bvdup( &digest );
2659         keys[1] = NULL;
2660
2661         *keysp = keys;
2662         return LDAP_SUCCESS;
2663 }
2664
2665 /* Substrings Index generation function */
2666 int caseExactIA5SubstringsIndexer(
2667         slap_mask_t use,
2668         slap_mask_t flags,
2669         Syntax *syntax,
2670         MatchingRule *mr,
2671         struct berval *prefix,
2672         struct berval **values,
2673         struct berval ***keysp )
2674 {
2675         ber_len_t i, nkeys;
2676         size_t slen, mlen;
2677         struct berval **keys;
2678         HASH_CONTEXT   HASHcontext;
2679         unsigned char   HASHdigest[HASH_BYTES];
2680         struct berval digest;
2681         digest.bv_val = HASHdigest;
2682         digest.bv_len = sizeof(HASHdigest);
2683
2684         /* we should have at least one value at this point */
2685         assert( values != NULL && values[0] != NULL );
2686
2687         nkeys=0;
2688         for( i=0; values[i] != NULL; i++ ) {
2689                 /* count number of indices to generate */
2690                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2691                         continue;
2692                 }
2693
2694                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2695                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2696                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2697                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2698                         } else {
2699                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2700                         }
2701                 }
2702
2703                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2704                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2705                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2706                         }
2707                 }
2708
2709                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2710                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2711                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2712                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2713                         } else {
2714                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2715                         }
2716                 }
2717         }
2718
2719         if( nkeys == 0 ) {
2720                 /* no keys to generate */
2721                 *keysp = NULL;
2722                 return LDAP_SUCCESS;
2723         }
2724
2725         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2726
2727         slen = strlen( syntax->ssyn_oid );
2728         mlen = strlen( mr->smr_oid );
2729
2730         nkeys=0;
2731         for( i=0; values[i] != NULL; i++ ) {
2732                 ber_len_t j,max;
2733                 struct berval *value;
2734
2735                 value = values[i];
2736                 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2737
2738                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2739                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2740                 {
2741                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
2742                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2743
2744                         for( j=0; j<max; j++ ) {
2745                                 HASH_Init( &HASHcontext );
2746                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2747                                         HASH_Update( &HASHcontext,
2748                                                 prefix->bv_val, prefix->bv_len );
2749                                 }
2750
2751                                 HASH_Update( &HASHcontext,
2752                                         &pre, sizeof( pre ) );
2753                                 HASH_Update( &HASHcontext,
2754                                         syntax->ssyn_oid, slen );
2755                                 HASH_Update( &HASHcontext,
2756                                         mr->smr_oid, mlen );
2757                                 HASH_Update( &HASHcontext,
2758                                         &value->bv_val[j],
2759                                         SLAP_INDEX_SUBSTR_MAXLEN );
2760                                 HASH_Final( HASHdigest, &HASHcontext );
2761
2762                                 keys[nkeys++] = ber_bvdup( &digest );
2763                         }
2764                 }
2765
2766                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2767                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2768
2769                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2770                         char pre;
2771
2772                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2773                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2774                                 HASH_Init( &HASHcontext );
2775                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2776                                         HASH_Update( &HASHcontext,
2777                                                 prefix->bv_val, prefix->bv_len );
2778                                 }
2779                                 HASH_Update( &HASHcontext,
2780                                         &pre, sizeof( pre ) );
2781                                 HASH_Update( &HASHcontext,
2782                                         syntax->ssyn_oid, slen );
2783                                 HASH_Update( &HASHcontext,
2784                                         mr->smr_oid, mlen );
2785                                 HASH_Update( &HASHcontext,
2786                                         value->bv_val, j );
2787                                 HASH_Final( HASHdigest, &HASHcontext );
2788
2789                                 keys[nkeys++] = ber_bvdup( &digest );
2790                         }
2791
2792                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2793                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2794                                 HASH_Init( &HASHcontext );
2795                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2796                                         HASH_Update( &HASHcontext,
2797                                                 prefix->bv_val, prefix->bv_len );
2798                                 }
2799                                 HASH_Update( &HASHcontext,
2800                                         &pre, sizeof( pre ) );
2801                                 HASH_Update( &HASHcontext,
2802                                         syntax->ssyn_oid, slen );
2803                                 HASH_Update( &HASHcontext,
2804                                         mr->smr_oid, mlen );
2805                                 HASH_Update( &HASHcontext,
2806                                         &value->bv_val[value->bv_len-j], j );
2807                                 HASH_Final( HASHdigest, &HASHcontext );
2808
2809                                 keys[nkeys++] = ber_bvdup( &digest );
2810                         }
2811
2812                 }
2813         }
2814
2815         if( nkeys > 0 ) {
2816                 keys[nkeys] = NULL;
2817                 *keysp = keys;
2818         } else {
2819                 ch_free( keys );
2820                 *keysp = NULL;
2821         }
2822
2823         return LDAP_SUCCESS;
2824 }
2825
2826 int caseExactIA5SubstringsFilter(
2827         slap_mask_t use,
2828         slap_mask_t flags,
2829         Syntax *syntax,
2830         MatchingRule *mr,
2831         struct berval *prefix,
2832         void * assertValue,
2833         struct berval ***keysp )
2834 {
2835         SubstringsAssertion *sa = assertValue;
2836         char pre;
2837         ber_len_t nkeys = 0;
2838         size_t slen, mlen, klen;
2839         struct berval **keys;
2840         HASH_CONTEXT   HASHcontext;
2841         unsigned char   HASHdigest[HASH_BYTES];
2842         struct berval *value;
2843         struct berval digest;
2844
2845         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
2846                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2847         {
2848                 nkeys++;
2849         }
2850
2851         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2852                 ber_len_t i;
2853                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2854                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2855                                 /* don't bother accounting for stepping */
2856                                 nkeys += sa->sa_any[i]->bv_len -
2857                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2858                         }
2859                 }
2860         }
2861
2862         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
2863                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2864         {
2865                 nkeys++;
2866         }
2867
2868         if( nkeys == 0 ) {
2869                 *keysp = NULL;
2870                 return LDAP_SUCCESS;
2871         }
2872
2873         digest.bv_val = HASHdigest;
2874         digest.bv_len = sizeof(HASHdigest);
2875
2876         slen = strlen( syntax->ssyn_oid );
2877         mlen = strlen( mr->smr_oid );
2878
2879         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2880         nkeys = 0;
2881
2882         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
2883                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2884         {
2885                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2886                 value = sa->sa_initial;
2887
2888                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2889                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2890
2891                 HASH_Init( &HASHcontext );
2892                 if( prefix != NULL && prefix->bv_len > 0 ) {
2893                         HASH_Update( &HASHcontext,
2894                                 prefix->bv_val, prefix->bv_len );
2895                 }
2896                 HASH_Update( &HASHcontext,
2897                         &pre, sizeof( pre ) );
2898                 HASH_Update( &HASHcontext,
2899                         syntax->ssyn_oid, slen );
2900                 HASH_Update( &HASHcontext,
2901                         mr->smr_oid, mlen );
2902                 HASH_Update( &HASHcontext,
2903                         value->bv_val, klen );
2904                 HASH_Final( HASHdigest, &HASHcontext );
2905
2906                 keys[nkeys++] = ber_bvdup( &digest );
2907         }
2908
2909         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2910                 ber_len_t i, j;
2911                 pre = SLAP_INDEX_SUBSTR_PREFIX;
2912                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2913
2914                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2915                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2916                                 continue;
2917                         }
2918
2919                         value = sa->sa_any[i];
2920
2921                         for(j=0;
2922                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2923                                 j += SLAP_INDEX_SUBSTR_STEP )
2924                         {
2925                                 HASH_Init( &HASHcontext );
2926                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2927                                         HASH_Update( &HASHcontext,
2928                                                 prefix->bv_val, prefix->bv_len );
2929                                 }
2930                                 HASH_Update( &HASHcontext,
2931                                         &pre, sizeof( pre ) );
2932                                 HASH_Update( &HASHcontext,
2933                                         syntax->ssyn_oid, slen );
2934                                 HASH_Update( &HASHcontext,
2935                                         mr->smr_oid, mlen );
2936                                 HASH_Update( &HASHcontext,
2937                                         &value->bv_val[j], klen ); 
2938                                 HASH_Final( HASHdigest, &HASHcontext );
2939
2940                                 keys[nkeys++] = ber_bvdup( &digest );
2941                         }
2942                 }
2943         }
2944
2945         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
2946                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2947         {
2948                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2949                 value = sa->sa_final;
2950
2951                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2952                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2953
2954                 HASH_Init( &HASHcontext );
2955                 if( prefix != NULL && prefix->bv_len > 0 ) {
2956                         HASH_Update( &HASHcontext,
2957                                 prefix->bv_val, prefix->bv_len );
2958                 }
2959                 HASH_Update( &HASHcontext,
2960                         &pre, sizeof( pre ) );
2961                 HASH_Update( &HASHcontext,
2962                         syntax->ssyn_oid, slen );
2963                 HASH_Update( &HASHcontext,
2964                         mr->smr_oid, mlen );
2965                 HASH_Update( &HASHcontext,
2966                         &value->bv_val[value->bv_len-klen], klen );
2967                 HASH_Final( HASHdigest, &HASHcontext );
2968
2969                 keys[nkeys++] = ber_bvdup( &digest );
2970         }
2971
2972         if( nkeys > 0 ) {
2973                 keys[nkeys] = NULL;
2974                 *keysp = keys;
2975         } else {
2976                 ch_free( keys );
2977                 *keysp = NULL;
2978         }
2979
2980         return LDAP_SUCCESS;
2981 }
2982         
2983 static int
2984 caseIgnoreIA5Match(
2985         int *matchp,
2986         slap_mask_t flags,
2987         Syntax *syntax,
2988         MatchingRule *mr,
2989         struct berval *value,
2990         void *assertedValue )
2991 {
2992         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2993
2994         if( match == 0 ) {
2995                 match = strncasecmp( value->bv_val,
2996                         ((struct berval *) assertedValue)->bv_val,
2997                         value->bv_len );
2998         }
2999
3000         *matchp = match;
3001         return LDAP_SUCCESS;
3002 }
3003
3004 static int
3005 caseIgnoreIA5SubstringsMatch(
3006         int *matchp,
3007         slap_mask_t flags,
3008         Syntax *syntax,
3009         MatchingRule *mr,
3010         struct berval *value,
3011         void *assertedValue )
3012 {
3013         int match = 0;
3014         SubstringsAssertion *sub = assertedValue;
3015         struct berval left = *value;
3016         int i;
3017         ber_len_t inlen=0;
3018
3019         /* Add up asserted input length */
3020         if( sub->sa_initial ) {
3021                 inlen += sub->sa_initial->bv_len;
3022         }
3023         if( sub->sa_any ) {
3024                 for(i=0; sub->sa_any[i] != NULL; i++) {
3025                         inlen += sub->sa_any[i]->bv_len;
3026                 }
3027         }
3028         if( sub->sa_final ) {
3029                 inlen += sub->sa_final->bv_len;
3030         }
3031
3032         if( sub->sa_initial ) {
3033                 if( inlen > left.bv_len ) {
3034                         match = 1;
3035                         goto done;
3036                 }
3037
3038                 match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
3039                         sub->sa_initial->bv_len );
3040
3041                 if( match != 0 ) {
3042                         goto done;
3043                 }
3044
3045                 left.bv_val += sub->sa_initial->bv_len;
3046                 left.bv_len -= sub->sa_initial->bv_len;
3047                 inlen -= sub->sa_initial->bv_len;
3048         }
3049
3050         if( sub->sa_final ) {
3051                 if( inlen > left.bv_len ) {
3052                         match = 1;
3053                         goto done;
3054                 }
3055
3056                 match = strncasecmp( sub->sa_final->bv_val,
3057                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
3058                         sub->sa_final->bv_len );
3059
3060                 if( match != 0 ) {
3061                         goto done;
3062                 }
3063
3064                 left.bv_len -= sub->sa_final->bv_len;
3065                 inlen -= sub->sa_final->bv_len;
3066         }
3067
3068         if( sub->sa_any ) {
3069                 for(i=0; sub->sa_any[i]; i++) {
3070                         ber_len_t idx;
3071                         char *p;
3072
3073 retry:
3074                         if( inlen > left.bv_len ) {
3075                                 /* not enough length */
3076                                 match = 1;
3077                                 goto done;
3078                         }
3079
3080                         if( sub->sa_any[i]->bv_len == 0 ) {
3081                                 continue;
3082                         }
3083
3084                         p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );
3085
3086                         if( p == NULL ) {
3087                                 match = 1;
3088                                 goto done;
3089                         }
3090
3091                         idx = p - left.bv_val;
3092                         assert( idx < left.bv_len );
3093
3094                         if( idx >= left.bv_len ) {
3095                                 /* this shouldn't happen */
3096                                 return LDAP_OTHER;
3097                         }
3098
3099                         left.bv_val = p;
3100                         left.bv_len -= idx;
3101
3102                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
3103                                 /* not enough left */
3104                                 match = 1;
3105                                 goto done;
3106                         }
3107
3108                         match = strncasecmp( left.bv_val,
3109                                 sub->sa_any[i]->bv_val,
3110                                 sub->sa_any[i]->bv_len );
3111
3112                         if( match != 0 ) {
3113                                 left.bv_val++;
3114                                 left.bv_len--;
3115
3116                                 goto retry;
3117                         }
3118
3119                         left.bv_val += sub->sa_any[i]->bv_len;
3120                         left.bv_len -= sub->sa_any[i]->bv_len;
3121                         inlen -= sub->sa_any[i]->bv_len;
3122                 }
3123         }
3124
3125 done:
3126         *matchp = match;
3127         return LDAP_SUCCESS;
3128 }
3129
3130 /* Index generation function */
3131 int caseIgnoreIA5Indexer(
3132         slap_mask_t use,
3133         slap_mask_t flags,
3134         Syntax *syntax,
3135         MatchingRule *mr,
3136         struct berval *prefix,
3137         struct berval **values,
3138         struct berval ***keysp )
3139 {
3140         int i;
3141         size_t slen, mlen;
3142         struct berval **keys;
3143         HASH_CONTEXT   HASHcontext;
3144         unsigned char   HASHdigest[HASH_BYTES];
3145         struct berval digest;
3146         digest.bv_val = HASHdigest;
3147         digest.bv_len = sizeof(HASHdigest);
3148
3149         /* we should have at least one value at this point */
3150         assert( values != NULL && values[0] != NULL );
3151
3152         for( i=0; values[i] != NULL; i++ ) {
3153                 /* just count them */
3154         }
3155
3156         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
3157
3158         slen = strlen( syntax->ssyn_oid );
3159         mlen = strlen( mr->smr_oid );
3160
3161         for( i=0; values[i] != NULL; i++ ) {
3162                 struct berval *value = ber_bvdup( values[i] );
3163                 ldap_pvt_str2upper( value->bv_val );
3164
3165                 HASH_Init( &HASHcontext );
3166                 if( prefix != NULL && prefix->bv_len > 0 ) {
3167                         HASH_Update( &HASHcontext,
3168                                 prefix->bv_val, prefix->bv_len );
3169                 }
3170                 HASH_Update( &HASHcontext,
3171                         syntax->ssyn_oid, slen );
3172                 HASH_Update( &HASHcontext,
3173                         mr->smr_oid, mlen );
3174                 HASH_Update( &HASHcontext,
3175                         value->bv_val, value->bv_len );
3176                 HASH_Final( HASHdigest, &HASHcontext );
3177
3178                 ber_bvfree( value );
3179
3180                 keys[i] = ber_bvdup( &digest );
3181         }
3182
3183         keys[i] = NULL;
3184         *keysp = keys;
3185         return LDAP_SUCCESS;
3186 }
3187
3188 /* Index generation function */
3189 int caseIgnoreIA5Filter(
3190         slap_mask_t use,
3191         slap_mask_t flags,
3192         Syntax *syntax,
3193         MatchingRule *mr,
3194         struct berval *prefix,
3195         void * assertValue,
3196         struct berval ***keysp )
3197 {
3198         size_t slen, mlen;
3199         struct berval **keys;
3200         HASH_CONTEXT   HASHcontext;
3201         unsigned char   HASHdigest[HASH_BYTES];
3202         struct berval *value;
3203         struct berval digest;
3204         digest.bv_val = HASHdigest;
3205         digest.bv_len = sizeof(HASHdigest);
3206
3207         slen = strlen( syntax->ssyn_oid );
3208         mlen = strlen( mr->smr_oid );
3209
3210         value = ber_bvdup( (struct berval *) assertValue );
3211         ldap_pvt_str2upper( value->bv_val );
3212
3213         keys = ch_malloc( sizeof( struct berval * ) * 2 );
3214
3215         HASH_Init( &HASHcontext );
3216         if( prefix != NULL && prefix->bv_len > 0 ) {
3217                 HASH_Update( &HASHcontext,
3218                         prefix->bv_val, prefix->bv_len );
3219         }
3220         HASH_Update( &HASHcontext,
3221                 syntax->ssyn_oid, slen );
3222         HASH_Update( &HASHcontext,
3223                 mr->smr_oid, mlen );
3224         HASH_Update( &HASHcontext,
3225                 value->bv_val, value->bv_len );
3226         HASH_Final( HASHdigest, &HASHcontext );
3227
3228         keys[0] = ber_bvdup( &digest );
3229         keys[1] = NULL;
3230
3231         ber_bvfree( value );
3232
3233         *keysp = keys;
3234
3235         return LDAP_SUCCESS;
3236 }
3237
3238 /* Substrings Index generation function */
3239 int caseIgnoreIA5SubstringsIndexer(
3240         slap_mask_t use,
3241         slap_mask_t flags,
3242         Syntax *syntax,
3243         MatchingRule *mr,
3244         struct berval *prefix,
3245         struct berval **values,
3246         struct berval ***keysp )
3247 {
3248         ber_len_t i, nkeys;
3249         size_t slen, mlen;
3250         struct berval **keys;
3251         HASH_CONTEXT   HASHcontext;
3252         unsigned char   HASHdigest[HASH_BYTES];
3253         struct berval digest;
3254         digest.bv_val = HASHdigest;
3255         digest.bv_len = sizeof(HASHdigest);
3256
3257         /* we should have at least one value at this point */
3258         assert( values != NULL && values[0] != NULL );
3259
3260         nkeys=0;
3261         for( i=0; values[i] != NULL; i++ ) {
3262                 /* count number of indices to generate */
3263                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3264                         continue;
3265                 }
3266
3267                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3268                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3269                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3270                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3271                         } else {
3272                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3273                         }
3274                 }
3275
3276                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3277                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3278                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3279                         }
3280                 }
3281
3282                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3283                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3284                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3285                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3286                         } else {
3287                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3288                         }
3289                 }
3290         }
3291
3292         if( nkeys == 0 ) {
3293                 /* no keys to generate */
3294                 *keysp = NULL;
3295                 return LDAP_SUCCESS;
3296         }
3297
3298         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
3299
3300         slen = strlen( syntax->ssyn_oid );
3301         mlen = strlen( mr->smr_oid );
3302
3303         nkeys=0;
3304         for( i=0; values[i] != NULL; i++ ) {
3305                 int j,max;
3306                 struct berval *value;
3307
3308                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3309
3310                 value = ber_bvdup( values[i] );
3311                 ldap_pvt_str2upper( value->bv_val );
3312
3313                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3314                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3315                 {
3316                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
3317                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3318
3319                         for( j=0; j<max; j++ ) {
3320                                 HASH_Init( &HASHcontext );
3321                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3322                                         HASH_Update( &HASHcontext,
3323                                                 prefix->bv_val, prefix->bv_len );
3324                                 }
3325
3326                                 HASH_Update( &HASHcontext,
3327                                         &pre, sizeof( pre ) );
3328                                 HASH_Update( &HASHcontext,
3329                                         syntax->ssyn_oid, slen );
3330                                 HASH_Update( &HASHcontext,
3331                                         mr->smr_oid, mlen );
3332                                 HASH_Update( &HASHcontext,
3333                                         &value->bv_val[j],
3334                                         SLAP_INDEX_SUBSTR_MAXLEN );
3335                                 HASH_Final( HASHdigest, &HASHcontext );
3336
3337                                 keys[nkeys++] = ber_bvdup( &digest );
3338                         }
3339                 }
3340
3341                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3342                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3343
3344                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3345                         char pre;
3346
3347                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3348                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3349                                 HASH_Init( &HASHcontext );
3350                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3351                                         HASH_Update( &HASHcontext,
3352                                                 prefix->bv_val, prefix->bv_len );
3353                                 }
3354                                 HASH_Update( &HASHcontext,
3355                                         &pre, sizeof( pre ) );
3356                                 HASH_Update( &HASHcontext,
3357                                         syntax->ssyn_oid, slen );
3358                                 HASH_Update( &HASHcontext,
3359                                         mr->smr_oid, mlen );
3360                                 HASH_Update( &HASHcontext,
3361                                         value->bv_val, j );
3362                                 HASH_Final( HASHdigest, &HASHcontext );
3363
3364                                 keys[nkeys++] = ber_bvdup( &digest );
3365                         }
3366
3367                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3368                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3369                                 HASH_Init( &HASHcontext );
3370                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3371                                         HASH_Update( &HASHcontext,
3372                                                 prefix->bv_val, prefix->bv_len );
3373                                 }
3374                                 HASH_Update( &HASHcontext,
3375                                         &pre, sizeof( pre ) );
3376                                 HASH_Update( &HASHcontext,
3377                                         syntax->ssyn_oid, slen );
3378                                 HASH_Update( &HASHcontext,
3379                                         mr->smr_oid, mlen );
3380                                 HASH_Update( &HASHcontext,
3381                                         &value->bv_val[value->bv_len-j], j );
3382                                 HASH_Final( HASHdigest, &HASHcontext );
3383
3384                                 keys[nkeys++] = ber_bvdup( &digest );
3385                         }
3386
3387                 }
3388
3389                 ber_bvfree( value );
3390         }
3391
3392         if( nkeys > 0 ) {
3393                 keys[nkeys] = NULL;
3394                 *keysp = keys;
3395         } else {
3396                 ch_free( keys );
3397                 *keysp = NULL;
3398         }
3399
3400         return LDAP_SUCCESS;
3401 }
3402
3403 int caseIgnoreIA5SubstringsFilter(
3404         slap_mask_t use,
3405         slap_mask_t flags,
3406         Syntax *syntax,
3407         MatchingRule *mr,
3408         struct berval *prefix,
3409         void * assertValue,
3410         struct berval ***keysp )
3411 {
3412         SubstringsAssertion *sa = assertValue;
3413         char pre;
3414         ber_len_t nkeys = 0;
3415         size_t slen, mlen, klen;
3416         struct berval **keys;
3417         HASH_CONTEXT   HASHcontext;
3418         unsigned char   HASHdigest[HASH_BYTES];
3419         struct berval *value;
3420         struct berval digest;
3421
3422         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
3423                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3424         {
3425                 nkeys++;
3426         }
3427
3428         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3429                 ber_len_t i;
3430                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3431                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3432                                 /* don't bother accounting for stepping */
3433                                 nkeys += sa->sa_any[i]->bv_len -
3434                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3435                         }
3436                 }
3437         }
3438
3439         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
3440                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3441         {
3442                 nkeys++;
3443         }
3444
3445         if( nkeys == 0 ) {
3446                 *keysp = NULL;
3447                 return LDAP_SUCCESS;
3448         }
3449
3450         digest.bv_val = HASHdigest;
3451         digest.bv_len = sizeof(HASHdigest);
3452
3453         slen = strlen( syntax->ssyn_oid );
3454         mlen = strlen( mr->smr_oid );
3455
3456         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
3457         nkeys = 0;
3458
3459         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
3460                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3461         {
3462                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3463                 value = ber_bvdup( sa->sa_initial );
3464                 ldap_pvt_str2upper( value->bv_val );
3465
3466                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3467                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3468
3469                 HASH_Init( &HASHcontext );
3470                 if( prefix != NULL && prefix->bv_len > 0 ) {
3471                         HASH_Update( &HASHcontext,
3472                                 prefix->bv_val, prefix->bv_len );
3473                 }
3474                 HASH_Update( &HASHcontext,
3475                         &pre, sizeof( pre ) );
3476                 HASH_Update( &HASHcontext,
3477                         syntax->ssyn_oid, slen );
3478                 HASH_Update( &HASHcontext,
3479                         mr->smr_oid, mlen );
3480                 HASH_Update( &HASHcontext,
3481                         value->bv_val, klen );
3482                 HASH_Final( HASHdigest, &HASHcontext );
3483
3484                 ber_bvfree( value );
3485                 keys[nkeys++] = ber_bvdup( &digest );
3486         }
3487
3488         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3489                 ber_len_t i, j;
3490                 pre = SLAP_INDEX_SUBSTR_PREFIX;
3491                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3492
3493                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3494                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3495                                 continue;
3496                         }
3497
3498                         value = ber_bvdup( sa->sa_any[i] );
3499                         ldap_pvt_str2upper( value->bv_val );
3500
3501                         for(j=0;
3502                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3503                                 j += SLAP_INDEX_SUBSTR_STEP )
3504                         {
3505                                 HASH_Init( &HASHcontext );
3506                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3507                                         HASH_Update( &HASHcontext,
3508                                                 prefix->bv_val, prefix->bv_len );
3509                                 }
3510                                 HASH_Update( &HASHcontext,
3511                                         &pre, sizeof( pre ) );
3512                                 HASH_Update( &HASHcontext,
3513                                         syntax->ssyn_oid, slen );
3514                                 HASH_Update( &HASHcontext,
3515                                         mr->smr_oid, mlen );
3516                                 HASH_Update( &HASHcontext,
3517                                         &value->bv_val[j], klen );
3518                                 HASH_Final( HASHdigest, &HASHcontext );
3519
3520                                 keys[nkeys++] = ber_bvdup( &digest );
3521                         }
3522
3523                         ber_bvfree( value );
3524                 }
3525         }
3526
3527         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
3528                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3529         {
3530                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3531                 value = ber_bvdup( sa->sa_final );
3532                 ldap_pvt_str2upper( value->bv_val );
3533
3534                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3535                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3536
3537                 HASH_Init( &HASHcontext );
3538                 if( prefix != NULL && prefix->bv_len > 0 ) {
3539                         HASH_Update( &HASHcontext,
3540                                 prefix->bv_val, prefix->bv_len );
3541                 }
3542                 HASH_Update( &HASHcontext,
3543                         &pre, sizeof( pre ) );
3544                 HASH_Update( &HASHcontext,
3545                         syntax->ssyn_oid, slen );
3546                 HASH_Update( &HASHcontext,
3547                         mr->smr_oid, mlen );
3548                 HASH_Update( &HASHcontext,
3549                         &value->bv_val[value->bv_len-klen], klen );
3550                 HASH_Final( HASHdigest, &HASHcontext );
3551
3552                 ber_bvfree( value );
3553                 keys[nkeys++] = ber_bvdup( &digest );
3554         }
3555
3556         if( nkeys > 0 ) {
3557                 keys[nkeys] = NULL;
3558                 *keysp = keys;
3559         } else {
3560                 ch_free( keys );
3561                 *keysp = NULL;
3562         }
3563
3564         return LDAP_SUCCESS;
3565 }
3566         
3567 static int
3568 numericStringNormalize(
3569         Syntax *syntax,
3570         struct berval *val,
3571         struct berval **normalized )
3572 {
3573         /* similiar to IA5StringNormalize except removes all spaces */
3574         struct berval *newval;
3575         char *p, *q;
3576
3577         newval = ch_malloc( sizeof( struct berval ) );
3578
3579         p = val->bv_val;
3580
3581         /* Ignore initial whitespace */
3582         while ( ASCII_SPACE( *p ) ) {
3583                 p++;
3584         }
3585
3586         if( *p == '\0' ) {
3587                 ch_free( newval );
3588                 return LDAP_INVALID_SYNTAX;
3589         }
3590
3591         newval->bv_val = ch_strdup( p );
3592         p = q = newval->bv_val;
3593
3594         while ( *p ) {
3595                 if ( ASCII_SPACE( *p ) ) {
3596                         /* Ignore whitespace */
3597                         p++;
3598                 } else {
3599                         *q++ = *p++;
3600                 }
3601         }
3602
3603         assert( *newval->bv_val );
3604         assert( newval->bv_val < p );
3605         assert( q <= p );
3606
3607         /* cannot start with a space */
3608         assert( !ASCII_SPACE(*newval->bv_val) );
3609
3610         /* cannot end with a space */
3611         assert( !ASCII_SPACE( q[-1] ) );
3612
3613         /* null terminate */
3614         *q = '\0';
3615
3616         newval->bv_len = q - newval->bv_val;
3617         *normalized = newval;
3618
3619         return LDAP_SUCCESS;
3620 }
3621
3622 static int
3623 objectIdentifierFirstComponentMatch(
3624         int *matchp,
3625         slap_mask_t flags,
3626         Syntax *syntax,
3627         MatchingRule *mr,
3628         struct berval *value,
3629         void *assertedValue )
3630 {
3631         int rc = LDAP_SUCCESS;
3632         int match;
3633         struct berval *asserted = (struct berval *) assertedValue;
3634         ber_len_t i;
3635         struct berval oid;
3636
3637         if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3638                 return LDAP_INVALID_SYNTAX;
3639         }
3640
3641         /* trim leading white space */
3642         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3643                 /* empty */
3644         }
3645
3646         /* grab next word */
3647         oid.bv_val = &value->bv_val[i];
3648         oid.bv_len = value->bv_len - i;
3649         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3650                 /* empty */
3651         }
3652         oid.bv_len = i;
3653
3654         /* insert attributeTypes, objectclass check here */
3655         if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3656                 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3657
3658         } else {
3659                 char *stored = ch_malloc( oid.bv_len + 1 );
3660                 AC_MEMCPY( stored, oid.bv_val, oid.bv_len );
3661                 stored[oid.bv_len] = '\0';
3662
3663                 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3664                         MatchingRule *asserted_mr = mr_find( asserted->bv_val );
3665                         MatchingRule *stored_mr = mr_find( stored );
3666
3667                         if( asserted_mr == NULL ) {
3668                                 rc = SLAPD_COMPARE_UNDEFINED;
3669                         } else {
3670                                 match = asserted_mr != stored_mr;
3671                         }
3672
3673                 } else if ( !strcmp( syntax->ssyn_oid,
3674                         SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3675                 {
3676                         AttributeType *asserted_at = at_find( asserted->bv_val );
3677                         AttributeType *stored_at = at_find( stored );
3678
3679                         if( asserted_at == NULL ) {
3680                                 rc = SLAPD_COMPARE_UNDEFINED;
3681                         } else {
3682                                 match = asserted_at != stored_at;
3683                         }
3684
3685                 } else if ( !strcmp( syntax->ssyn_oid,
3686                         SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3687                 {
3688                         ObjectClass *asserted_oc = oc_find( asserted->bv_val );
3689                         ObjectClass *stored_oc = oc_find( stored );
3690
3691                         if( asserted_oc == NULL ) {
3692                                 rc = SLAPD_COMPARE_UNDEFINED;
3693                         } else {
3694                                 match = asserted_oc != stored_oc;
3695                         }
3696                 }
3697
3698                 ch_free( stored );
3699         }
3700
3701         Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3702                 "%d\n\t\"%s\"\n\t\"%s\"\n",
3703             match, value->bv_val, asserted->bv_val );
3704
3705         if( rc == LDAP_SUCCESS ) *matchp = match;
3706         return rc;
3707 }
3708
3709 static int
3710 check_time_syntax (struct berval *val,
3711         int start,
3712         int *parts)
3713 {
3714         static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3715         static int mdays[2][12] = {
3716                 /* non-leap years */
3717                 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3718                 /* leap years */
3719                 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3720         };
3721         char *p, *e;
3722         int part, c, tzoffset, leapyear = 0 ;
3723
3724         if( val->bv_len == 0 ) {
3725                 return LDAP_INVALID_SYNTAX;
3726         }
3727
3728         p = (char *)val->bv_val;
3729         e = p + val->bv_len;
3730
3731         /* Ignore initial whitespace */
3732         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3733                 p++;
3734         }
3735
3736         if (e - p < 13 - (2 * start)) {
3737                 return LDAP_INVALID_SYNTAX;
3738         }
3739
3740         for (part = 0; part < 9; part++) {
3741                 parts[part] = 0;
3742         }
3743
3744         for (part = start; part < 7; part++) {
3745                 c = *p;
3746                 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3747                         part++;
3748                         break;
3749                 }
3750                 p++;
3751                 c -= '0';
3752                 if (p == e) {
3753                         return LDAP_INVALID_SYNTAX;
3754                 }
3755                 if (c < 0 || c > 9) {
3756                         return LDAP_INVALID_SYNTAX;
3757                 }
3758                 parts[part] = c;
3759
3760                 c = *p++ - '0';
3761                 if (p == e) {
3762                         return LDAP_INVALID_SYNTAX;
3763                 }
3764                 if (c < 0 || c > 9) {
3765                         return LDAP_INVALID_SYNTAX;
3766                 }
3767                 parts[part] *= 10;
3768                 parts[part] += c;
3769
3770                 if (part == 2 || part == 3) {
3771                         parts[part]--;
3772                 }
3773                 if (parts[part] < 0) {
3774                         return LDAP_INVALID_SYNTAX;
3775                 }
3776                 if (parts[part] > ceiling[part]) {
3777                         return LDAP_INVALID_SYNTAX;
3778                 }
3779         }
3780
3781         /* leapyear check for the Gregorian calendar (year>1581) */
3782         if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
3783                 ((parts[0] % 4 == 0) && (parts[1] == 0)))
3784         {
3785                 leapyear = 1;
3786         }
3787
3788         if (parts[3] > mdays[leapyear][parts[2]]) {
3789                 return LDAP_INVALID_SYNTAX;
3790         }
3791         
3792         c = *p++;
3793         if (c == 'Z') {
3794                 tzoffset = 0; /* UTC */
3795         } else if (c != '+' && c != '-') {
3796                 return LDAP_INVALID_SYNTAX;
3797         } else {
3798                 if (c == '-') {
3799                         tzoffset = -1;
3800                 } else /* c == '+' */ {
3801                         tzoffset = 1;
3802                 }
3803
3804                 if (p > e - 4) {
3805                         return LDAP_INVALID_SYNTAX;
3806                 }
3807
3808                 for (part = 7; part < 9; part++) {
3809                         c = *p++ - '0';
3810                         if (c < 0 || c > 9) {
3811                                 return LDAP_INVALID_SYNTAX;
3812                         }
3813                         parts[part] = c;
3814
3815                         c = *p++ - '0';
3816                         if (c < 0 || c > 9) {
3817                                 return LDAP_INVALID_SYNTAX;
3818                         }
3819                         parts[part] *= 10;
3820                         parts[part] += c;
3821                         if (parts[part] < 0 || parts[part] > ceiling[part]) {
3822                                 return LDAP_INVALID_SYNTAX;
3823                         }
3824                 }
3825         }
3826
3827         /* Ignore trailing whitespace */
3828         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3829                 p++;
3830         }
3831         if (p != e) {
3832                 return LDAP_INVALID_SYNTAX;
3833         }
3834
3835         switch ( tzoffset ) {
3836         case -1: /* negativ offset to UTC, ie west of Greenwich  */
3837                 parts[4] += parts[7];
3838                 parts[5] += parts[8];
3839                 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
3840                         if (part != 3) {
3841                                 c = ceiling[part];
3842                         } else {
3843                                 c = mdays[leapyear][parts[2]];
3844                         }
3845                         if (parts[part] > c) {
3846                                 parts[part] -= c + 1;
3847                                 parts[part - 1]++;
3848                         }
3849                 }
3850                 break;
3851         case 1: /* positive offset to UTC, ie east of Greenwich */
3852                 parts[4] -= parts[7];
3853                 parts[5] -= parts[8];
3854                 for (part = 6; --part > 0; ) {
3855                         if (part != 3) {
3856                                 c = ceiling[part];
3857                         } else {
3858                                 /* first arg to % needs to be non negativ */
3859                                 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3860                         }
3861                         if (parts[part] < 0) {
3862                                 parts[part] += c + 1;
3863                                 parts[part - 1]--;
3864                         }
3865                 }
3866                 break;
3867         case 0: /* already UTC */
3868                 break;
3869         }
3870
3871         return LDAP_SUCCESS;
3872 }
3873
3874 static int
3875 utcTimeNormalize(
3876         Syntax *syntax,
3877         struct berval *val,
3878         struct berval **normalized )
3879 {
3880         struct berval *out;
3881         int parts[9], rc;
3882
3883         rc = check_time_syntax(val, 1, parts);
3884         if (rc != LDAP_SUCCESS) {
3885                 return rc;
3886         }
3887
3888         *normalized = NULL;
3889         out = ch_malloc( sizeof(struct berval) );
3890         if( out == NULL ) {
3891                 return LBER_ERROR_MEMORY;
3892         }
3893
3894         out->bv_val = ch_malloc( 14 );
3895         if ( out->bv_val == NULL ) {
3896                 ch_free( out );
3897                 return LBER_ERROR_MEMORY;
3898         }
3899
3900         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ldZ",
3901                 parts[1], parts[2] + 1, parts[3] + 1,
3902                 parts[4], parts[5], parts[6] );
3903         out->bv_len = 13;
3904         *normalized = out;
3905
3906         return LDAP_SUCCESS;
3907 }
3908
3909 static int
3910 utcTimeValidate(
3911         Syntax *syntax,
3912         struct berval *in )
3913 {
3914         int parts[9];
3915
3916         return check_time_syntax(in, 1, parts);
3917 }
3918
3919 static int
3920 generalizedTimeValidate(
3921         Syntax *syntax,
3922         struct berval *in )
3923 {
3924         int parts[9];
3925
3926         return check_time_syntax(in, 0, parts);
3927 }
3928
3929 static int
3930 generalizedTimeNormalize(
3931         Syntax *syntax,
3932         struct berval *val,
3933         struct berval **normalized )
3934 {
3935         struct berval *out;
3936         int parts[9], rc;
3937
3938         rc = check_time_syntax(val, 0, parts);
3939         if (rc != LDAP_SUCCESS) {
3940                 return rc;
3941         }
3942
3943         *normalized = NULL;
3944         out = ch_malloc( sizeof(struct berval) );
3945         if( out == NULL ) {
3946                 return LBER_ERROR_MEMORY;
3947         }
3948
3949         out->bv_val = ch_malloc( 16 );
3950         if ( out->bv_val == NULL ) {
3951                 ch_free( out );
3952                 return LBER_ERROR_MEMORY;
3953         }
3954
3955         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ld%02ldZ",
3956                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3957                 parts[4], parts[5], parts[6] );
3958         out->bv_len = 15;
3959         *normalized = out;
3960
3961         return LDAP_SUCCESS;
3962 }
3963
3964 static int
3965 nisNetgroupTripleValidate(
3966         Syntax *syntax,
3967         struct berval *val )
3968 {
3969         char *p, *e;
3970         int commas = 0;
3971
3972         if ( val->bv_len == 0 ) {
3973                 return LDAP_INVALID_SYNTAX;
3974         }
3975
3976         p = (char *)val->bv_val;
3977         e = p + val->bv_len;
3978
3979 #if 0
3980         /* syntax does not allow leading white space */
3981         /* Ignore initial whitespace */
3982         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3983                 p++;
3984         }
3985 #endif
3986
3987         if ( *p != '(' /*')'*/ ) {
3988                 return LDAP_INVALID_SYNTAX;
3989         }
3990
3991         for ( p++; ( p < e ) && ( *p != ')' ); p++ ) {
3992                 if ( *p == ',' ) {
3993                         commas++;
3994                         if ( commas > 2 ) {
3995                                 return LDAP_INVALID_SYNTAX;
3996                         }
3997
3998                 } else if ( !ATTR_CHAR( *p ) ) {
3999                         return LDAP_INVALID_SYNTAX;
4000                 }
4001         }
4002
4003         if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4004                 return LDAP_INVALID_SYNTAX;
4005         }
4006
4007         p++;
4008
4009 #if 0
4010         /* syntax does not allow trailing white space */
4011         /* Ignore trailing whitespace */
4012         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4013                 p++;
4014         }
4015 #endif
4016
4017         if (p != e) {
4018                 return LDAP_INVALID_SYNTAX;
4019         }
4020
4021         return LDAP_SUCCESS;
4022 }
4023
4024 static int
4025 bootParameterValidate(
4026         Syntax *syntax,
4027         struct berval *val )
4028 {
4029         char *p, *e;
4030
4031         if ( val->bv_len == 0 ) {
4032                 return LDAP_INVALID_SYNTAX;
4033         }
4034
4035         p = (char *)val->bv_val;
4036         e = p + val->bv_len;
4037
4038         /* key */
4039         for (; ( p < e ) && ( *p != '=' ); p++ ) {
4040                 if ( !ATTR_CHAR( *p ) ) {
4041                         return LDAP_INVALID_SYNTAX;
4042                 }
4043         }
4044
4045         if ( *p != '=' ) {
4046                 return LDAP_INVALID_SYNTAX;
4047         }
4048
4049         /* server */
4050         for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4051                 if ( !ATTR_CHAR( *p ) ) {
4052                         return LDAP_INVALID_SYNTAX;
4053                 }
4054         }
4055
4056         if ( *p != ':' ) {
4057                 return LDAP_INVALID_SYNTAX;
4058         }
4059
4060         /* path */
4061         for ( p++; p < e; p++ ) {
4062                 if ( !ATTR_CHAR( *p ) ) {
4063                         return LDAP_INVALID_SYNTAX;
4064                 }
4065         }
4066
4067         return LDAP_SUCCESS;
4068 }
4069
4070 struct syntax_defs_rec {
4071         char *sd_desc;
4072         int sd_flags;
4073         slap_syntax_validate_func *sd_validate;
4074         slap_syntax_transform_func *sd_normalize;
4075         slap_syntax_transform_func *sd_pretty;
4076 #ifdef SLAPD_BINARY_CONVERSION
4077         slap_syntax_transform_func *sd_ber2str;
4078         slap_syntax_transform_func *sd_str2ber;
4079 #endif
4080 };
4081
4082 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4083 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4084
4085 struct syntax_defs_rec syntax_defs[] = {
4086         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
4087                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4088         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4089                 0, NULL, NULL, NULL},
4090         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4091                 0, NULL, NULL, NULL},
4092         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
4093                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4094         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_NOT_H_R ")",
4095                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4096         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4097                 0, bitStringValidate, NULL, NULL },
4098         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4099                 0, booleanValidate, NULL, NULL},
4100         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4101                 X_BINARY X_NOT_H_R ")",
4102                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4103         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4104                 X_BINARY X_NOT_H_R ")",
4105                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4106         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4107                 X_BINARY X_NOT_H_R ")",
4108                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4109         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4110                 0, NULL, NULL, NULL},
4111         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4112                 0, dnValidate, dnNormalize, dnPretty},
4113         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4114                 0, NULL, NULL, NULL},
4115         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4116                 0, NULL, NULL, NULL},
4117         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4118                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4119         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4120                 0, NULL, NULL, NULL},
4121         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4122                 0, NULL, NULL, NULL},
4123         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4124                 0, NULL, NULL, NULL},
4125         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4126                 0, NULL, NULL, NULL},
4127         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4128                 0, NULL, NULL, NULL},
4129         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4130                 0, IA5StringValidate, faxNumberNormalize, NULL},
4131         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4132                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4133         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4134                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4135         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4136                 0, NULL, NULL, NULL},
4137         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4138                 0, IA5StringValidate, IA5StringNormalize, NULL},
4139         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4140                 0, integerValidate, integerNormalize, integerPretty},
4141         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4142                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4143         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4144                 0, NULL, NULL, NULL},
4145         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4146                 0, NULL, NULL, NULL},
4147         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4148                 0, NULL, NULL, NULL},
4149         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4150                 0, NULL, NULL, NULL},
4151         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4152                 0, NULL, NULL, NULL},
4153         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4154                 0, nameUIDValidate, nameUIDNormalize, NULL},
4155         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4156                 0, NULL, NULL, NULL},
4157         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4158                 0, IA5StringValidate, numericStringNormalize, NULL},
4159         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4160                 0, NULL, NULL, NULL},
4161         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4162                 0, oidValidate, NULL, NULL},
4163         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4164                 0, NULL, NULL, NULL},
4165         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4166                 0, blobValidate, NULL, NULL},
4167         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4168                 0, blobValidate, NULL, NULL},
4169         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4170                 0, NULL, NULL, NULL},
4171         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4172                 0, NULL, NULL, NULL},
4173         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4174                 0, printableStringValidate, NULL, NULL},
4175         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4176                 X_BINARY X_NOT_H_R ")",
4177                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4178         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4179                 0, IA5StringValidate, phoneNumberNormalize, NULL},
4180         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4181                 0, NULL, NULL, NULL},
4182         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4183                 0, IA5StringValidate, telexNumberNormalize, NULL},
4184         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4185                 0, utcTimeValidate, utcTimeNormalize, NULL},
4186         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4187                 0, NULL, NULL, NULL},
4188         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4189                 0, NULL, NULL, NULL},
4190         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4191                 0, NULL, NULL, NULL},
4192         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4193                 0, NULL, NULL, NULL},
4194         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4195                 0, NULL, NULL, NULL},
4196
4197         /* RFC 2307 NIS Syntaxes */
4198         {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Netgroup Triple' )",
4199                 0, nisNetgroupTripleValidate, NULL, NULL},
4200         {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
4201                 0, bootParameterValidate, NULL, NULL},
4202
4203         /* OpenLDAP Experimental Syntaxes */
4204         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4205                 0, IA5StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4206                 NULL, NULL},
4207         {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4208                 0, NULL, NULL, NULL},
4209
4210         /* OpenLDAP Void Syntax */
4211         {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4212                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4213         {NULL, 0, NULL, NULL, NULL}
4214 };
4215
4216 struct mrule_defs_rec {
4217         char *                                          mrd_desc;
4218         slap_mask_t                                     mrd_usage;
4219         slap_mr_convert_func *          mrd_convert;
4220         slap_mr_normalize_func *        mrd_normalize;
4221         slap_mr_match_func *            mrd_match;
4222         slap_mr_indexer_func *          mrd_indexer;
4223         slap_mr_filter_func *           mrd_filter;
4224
4225         char *                                          mrd_associated;
4226 };
4227
4228 /*
4229  * Other matching rules in X.520 that we do not use (yet):
4230  *
4231  * 2.5.13.9             numericStringOrderingMatch
4232  * 2.5.13.15    integerOrderingMatch
4233  * 2.5.13.18    octetStringOrderingMatch
4234  * 2.5.13.19    octetStringSubstringsMatch
4235  * 2.5.13.25    uTCTimeMatch
4236  * 2.5.13.26    uTCTimeOrderingMatch
4237  * 2.5.13.31    directoryStringFirstComponentMatch
4238  * 2.5.13.32    wordMatch
4239  * 2.5.13.33    keywordMatch
4240  * 2.5.13.34    certificateExactMatch
4241  * 2.5.13.35    certificateMatch
4242  * 2.5.13.36    certificatePairExactMatch
4243  * 2.5.13.37    certificatePairMatch
4244  * 2.5.13.38    certificateListExactMatch
4245  * 2.5.13.39    certificateListMatch
4246  * 2.5.13.40    algorithmIdentifierMatch
4247  * 2.5.13.41    storedPrefixMatch
4248  * 2.5.13.42    attributeCertificateMatch
4249  * 2.5.13.43    readerAndKeyIDMatch
4250  * 2.5.13.44    attributeIntegrityMatch
4251  */
4252
4253 struct mrule_defs_rec mrule_defs[] = {
4254         /*
4255          * EQUALITY matching rules must be listed after associated APPROX
4256          * matching rules.  So, we list all APPROX matching rules first.
4257          */
4258         {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4259                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4260                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4261                 NULL, NULL,
4262                 directoryStringApproxMatch, directoryStringApproxIndexer, 
4263                 directoryStringApproxFilter,
4264                 NULL},
4265
4266         {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4267                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4268                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4269                 NULL, NULL,
4270                 IA5StringApproxMatch, IA5StringApproxIndexer, 
4271                 IA5StringApproxFilter,
4272                 NULL},
4273
4274         /*
4275          * Other matching rules
4276          */
4277         
4278         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4279                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4280                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4281                 NULL, NULL,
4282                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4283                 NULL},
4284
4285         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4286                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4287                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4288                 NULL, NULL,
4289                 dnMatch, dnIndexer, dnFilter,
4290                 NULL},
4291
4292         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4293                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4294                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4295                 NULL, NULL,
4296                 caseIgnoreMatch, caseIgnoreIndexer, caseIgnoreFilter,
4297                 directoryStringApproxMatchOID },
4298
4299         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4300                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4301                 SLAP_MR_ORDERING,
4302                 NULL, NULL,
4303                 caseIgnoreOrderingMatch, NULL, NULL,
4304                 NULL},
4305
4306         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4307                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4308                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4309                 NULL, NULL,
4310                 caseIgnoreSubstringsMatch,
4311                 caseIgnoreSubstringsIndexer,
4312                 caseIgnoreSubstringsFilter,
4313                 NULL},
4314
4315         {"( 2.5.13.5 NAME 'caseExactMatch' "
4316                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4317                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4318                 NULL, NULL,
4319                 caseExactMatch, caseExactIndexer, caseExactFilter,
4320                 directoryStringApproxMatchOID },
4321
4322         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4323                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4324                 SLAP_MR_ORDERING,
4325                 NULL, NULL,
4326                 caseExactOrderingMatch, NULL, NULL,
4327                 NULL},
4328
4329         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4330                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4331                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4332                 NULL, NULL,
4333                 caseExactSubstringsMatch,
4334                 caseExactSubstringsIndexer,
4335                 caseExactSubstringsFilter,
4336                 NULL},
4337
4338         {"( 2.5.13.8 NAME 'numericStringMatch' "
4339                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4340                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4341                 NULL, NULL,
4342                 caseIgnoreIA5Match,
4343                 caseIgnoreIA5Indexer,
4344                 caseIgnoreIA5Filter,
4345                 NULL},
4346
4347         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4348                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4349                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4350                 NULL, NULL,
4351                 caseIgnoreIA5SubstringsMatch,
4352                 caseIgnoreIA5SubstringsIndexer,
4353                 caseIgnoreIA5SubstringsFilter,
4354                 NULL},
4355
4356         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4357                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4358                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4359                 NULL, NULL,
4360                 caseIgnoreListMatch, NULL, NULL,
4361                 NULL},
4362
4363         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4364                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4365                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4366                 NULL, NULL,
4367                 caseIgnoreListSubstringsMatch, NULL, NULL,
4368                 NULL},
4369
4370         {"( 2.5.13.13 NAME 'booleanMatch' "
4371                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4372                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4373                 NULL, NULL,
4374                 booleanMatch, NULL, NULL,
4375                 NULL},
4376
4377         {"( 2.5.13.14 NAME 'integerMatch' "
4378                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4379                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4380                 NULL, NULL,
4381                 integerMatch, integerIndexer, integerFilter,
4382                 NULL},
4383
4384         {"( 2.5.13.16 NAME 'bitStringMatch' "
4385                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4386                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4387                 NULL, NULL,
4388                 bitStringMatch, NULL, NULL,
4389                 NULL},
4390
4391         {"( 2.5.13.17 NAME 'octetStringMatch' "
4392                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4393                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4394                 NULL, NULL,
4395                 octetStringMatch, octetStringIndexer, octetStringFilter,
4396                 NULL},
4397
4398         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4399                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4400                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4401                 NULL, NULL,
4402                 telephoneNumberMatch, NULL, NULL,
4403                 NULL},
4404
4405         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4406                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4407                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4408                 NULL, NULL,
4409                 telephoneNumberSubstringsMatch, NULL, NULL,
4410                 NULL},
4411
4412         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4413                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4414                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4415                 NULL, NULL,
4416                 presentationAddressMatch, NULL, NULL,
4417                 NULL},
4418
4419         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4420                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4421                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4422                 NULL, NULL,
4423                 uniqueMemberMatch, NULL, NULL,
4424                 NULL},
4425
4426         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4427                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4428                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4429                 NULL, NULL,
4430                 protocolInformationMatch, NULL, NULL,
4431                 NULL},
4432
4433         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4434                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4435                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4436                 NULL, NULL,
4437                 generalizedTimeMatch, NULL, NULL,
4438                 NULL},
4439
4440         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4441                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4442                 SLAP_MR_ORDERING,
4443                 NULL, NULL,
4444                 generalizedTimeOrderingMatch, NULL, NULL,
4445                 NULL},
4446
4447         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4448                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4449                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4450                 NULL, NULL,
4451                 integerFirstComponentMatch, NULL, NULL,
4452                 NULL},
4453
4454         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4455                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4456                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4457                 NULL, NULL,
4458                 objectIdentifierFirstComponentMatch, NULL, NULL,
4459                 NULL},
4460
4461         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4462                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4463                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4464                 NULL, NULL,
4465                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4466                 IA5StringApproxMatchOID },
4467
4468         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4469                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4470                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4471                 NULL, NULL,
4472                 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4473                 IA5StringApproxMatchOID },
4474
4475         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4476                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4477                 SLAP_MR_SUBSTR,
4478                 NULL, NULL,
4479                 caseIgnoreIA5SubstringsMatch,
4480                 caseIgnoreIA5SubstringsIndexer,
4481                 caseIgnoreIA5SubstringsFilter,
4482                 NULL},
4483
4484         {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4485                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4486                 SLAP_MR_SUBSTR,
4487                 NULL, NULL,
4488                 caseExactIA5SubstringsMatch,
4489                 caseExactIA5SubstringsIndexer,
4490                 caseExactIA5SubstringsFilter,
4491                 NULL},
4492
4493         {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4494                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4495                 SLAP_MR_EQUALITY,
4496                 NULL, NULL,
4497                 authPasswordMatch, NULL, NULL,
4498                 NULL},
4499
4500         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4501                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4502                 SLAP_MR_EQUALITY,
4503                 NULL, NULL,
4504                 OpenLDAPaciMatch, NULL, NULL,
4505                 NULL},
4506
4507         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4508 };
4509
4510 int
4511 schema_init( void )
4512 {
4513         int             res;
4514         int             i;
4515
4516         /* we should only be called once (from main) */
4517         assert( schema_init_done == 0 );
4518
4519         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4520                 res = register_syntax( syntax_defs[i].sd_desc,
4521                     syntax_defs[i].sd_flags,
4522                     syntax_defs[i].sd_validate,
4523                     syntax_defs[i].sd_normalize,
4524                         syntax_defs[i].sd_pretty
4525 #ifdef SLAPD_BINARY_CONVERSION
4526                         ,
4527                     syntax_defs[i].sd_ber2str,
4528                         syntax_defs[i].sd_str2ber
4529 #endif
4530                 );
4531
4532                 if ( res ) {
4533                         fprintf( stderr, "schema_init: Error registering syntax %s\n",
4534                                  syntax_defs[i].sd_desc );
4535                         return LDAP_OTHER;
4536                 }
4537         }
4538
4539         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4540                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4541                         fprintf( stderr,
4542                                 "schema_init: Ingoring unusable matching rule %s\n",
4543                                  mrule_defs[i].mrd_desc );
4544                         continue;
4545                 }
4546
4547                 res = register_matching_rule(
4548                         mrule_defs[i].mrd_desc,
4549                         mrule_defs[i].mrd_usage,
4550                         mrule_defs[i].mrd_convert,
4551                         mrule_defs[i].mrd_normalize,
4552                     mrule_defs[i].mrd_match,
4553                         mrule_defs[i].mrd_indexer,
4554                         mrule_defs[i].mrd_filter,
4555                         mrule_defs[i].mrd_associated );
4556
4557                 if ( res ) {
4558                         fprintf( stderr,
4559                                 "schema_init: Error registering matching rule %s\n",
4560                                  mrule_defs[i].mrd_desc );
4561                         return LDAP_OTHER;
4562                 }
4563         }
4564         schema_init_done = 1;
4565         return LDAP_SUCCESS;
4566 }