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