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