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