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