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