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