]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
bdf64138ba2418a78db7f9b08eabe7c02f999429
[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 /* unimplemented validators */
24 #define bitStringValidate                               NULL
25
26 /* recycled normalization routines */
27 #define faxNumberNormalize                              numericStringNormalize
28 #define phoneNumberNormalize                    numericStringNormalize
29 #define telexNumberNormalize                    numericStringNormalize
30 #define integerNormalize                                numericStringNormalize
31
32 /* unimplemented normalizers */
33 #define bitStringNormalize                              NULL
34
35 /* unimplemented pretters */
36 #define dnPretty                                                NULL
37 #define integerPretty                                   NULL
38
39 /* recycled matching routines */
40 #define caseIgnoreMatch                                 caseIgnoreIA5Match
41 #define caseIgnoreOrderingMatch                 caseIgnoreMatch
42 #define caseIgnoreSubstringsMatch               caseIgnoreIA5SubstringsMatch
43
44 #define caseExactMatch                                  caseExactIA5Match
45 #define caseExactOrderingMatch                  caseExactMatch
46 #define caseExactSubstringsMatch                caseExactIA5SubstringsMatch
47
48 #define numericStringMatch                              caseIgnoreMatch
49 #define objectIdentifierMatch                   numericStringMatch
50 #define integerMatch                                    numericStringMatch
51 #define telephoneNumberMatch                    numericStringMatch
52 #define telephoneNumberSubstringsMatch  caseIgnoreIA5SubstringsMatch
53 #define generalizedTimeMatch                    numericStringMatch
54 #define generalizedTimeOrderingMatch    numericStringMatch
55
56 /* approx matching rules */
57 #define directoryStringApproxMatchOID   "1.3.6.1.4.1.4203.666.4.4"
58 #define directoryStringApproxMatch              NULL
59 #define IA5StringApproxMatchOID                 "1.3.6.1.4.1.4203.666.4.5"
60 #define IA5StringApproxMatch                    NULL
61
62 /* unimplemented matching routines */
63 #define caseIgnoreListMatch                             NULL
64 #define caseIgnoreListSubstringsMatch   NULL
65 #define bitStringMatch                                  NULL
66 #define presentationAddressMatch                NULL
67 #define uniqueMemberMatch                               NULL
68 #define protocolInformationMatch                NULL
69 #define integerFirstComponentMatch              NULL
70
71 #define OpenLDAPaciMatch                                NULL
72 #define authPasswordMatch                               NULL
73
74 /* recycled indexing/filtering routines */
75 #define caseIgnoreIndexer                               caseIgnoreIA5Indexer
76 #define caseIgnoreFilter                                caseIgnoreIA5Filter
77 #define caseExactIndexer                                caseExactIA5Indexer
78 #define caseExactFilter                                 caseExactIA5Filter
79 #define dnIndexer                                               caseIgnoreIndexer
80 #define dnFilter                                                caseIgnoreFilter
81
82 #define caseIgnoreSubstringsIndexer             caseIgnoreIA5SubstringsIndexer
83 #define caseIgnoreSubstringsFilter              caseIgnoreIA5SubstringsFilter
84 #define caseExactSubstringsIndexer              caseExactIA5SubstringsIndexer
85 #define caseExactSubstringsFilter               caseExactIA5SubstringsFilter
86
87
88 static int
89 octetStringMatch(
90         int *matchp,
91         unsigned flags,
92         Syntax *syntax,
93         MatchingRule *mr,
94         struct berval *value,
95         void *assertedValue )
96 {
97         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
98
99         if( match == 0 ) {
100                 match = memcmp( value->bv_val,
101                         ((struct berval *) assertedValue)->bv_val,
102                         value->bv_len );
103         }
104
105         *matchp = match;
106         return LDAP_SUCCESS;
107 }
108
109 /* Index generation function */
110 int octetStringIndexer(
111         unsigned flags,
112         Syntax *syntax,
113         MatchingRule *mr,
114         struct berval *prefix,
115         struct berval **values,
116         struct berval ***keysp )
117 {
118         int i;
119         size_t slen, mlen;
120         struct berval **keys;
121         lutil_MD5_CTX   MD5context;
122         unsigned char   MD5digest[16];
123         struct berval digest;
124         digest.bv_val = MD5digest;
125         digest.bv_len = sizeof(MD5digest);
126
127         for( i=0; values[i] != NULL; i++ ) {
128                 /* just count them */
129         }
130
131         assert( i > 0 );
132
133         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
134
135         slen = strlen( syntax->ssyn_oid );
136         mlen = strlen( mr->smr_oid );
137
138         for( i=0; values[i] != NULL; i++ ) {
139                 lutil_MD5Init( &MD5context );
140                 if( prefix != NULL && prefix->bv_len > 0 ) {
141                         lutil_MD5Update( &MD5context,
142                                 prefix->bv_val, prefix->bv_len );
143                 }
144                 lutil_MD5Update( &MD5context,
145                         syntax->ssyn_oid, slen );
146                 lutil_MD5Update( &MD5context,
147                         mr->smr_oid, mlen );
148                 lutil_MD5Update( &MD5context,
149                         values[i]->bv_val, values[i]->bv_len );
150                 lutil_MD5Final( MD5digest, &MD5context );
151
152                 keys[i] = ber_bvdup( &digest );
153         }
154
155         keys[i] = NULL;
156
157         *keysp = keys;
158
159         return LDAP_SUCCESS;
160 }
161
162 /* Index generation function */
163 int octetStringFilter(
164         unsigned flags,
165         Syntax *syntax,
166         MatchingRule *mr,
167         struct berval *prefix,
168         void * assertValue,
169         struct berval ***keysp )
170 {
171         size_t slen, mlen;
172         struct berval **keys;
173         lutil_MD5_CTX   MD5context;
174         unsigned char   MD5digest[LUTIL_MD5_BYTES];
175         struct berval *value = (struct berval *) assertValue;
176         struct berval digest;
177         digest.bv_val = MD5digest;
178         digest.bv_len = sizeof(MD5digest);
179
180         slen = strlen( syntax->ssyn_oid );
181         mlen = strlen( mr->smr_oid );
182
183         keys = ch_malloc( sizeof( struct berval * ) * 2 );
184
185         lutil_MD5Init( &MD5context );
186         if( prefix != NULL && prefix->bv_len > 0 ) {
187                 lutil_MD5Update( &MD5context,
188                         prefix->bv_val, prefix->bv_len );
189         }
190         lutil_MD5Update( &MD5context,
191                 syntax->ssyn_oid, slen );
192         lutil_MD5Update( &MD5context,
193                 mr->smr_oid, mlen );
194         lutil_MD5Update( &MD5context,
195                 value->bv_val, value->bv_len );
196         lutil_MD5Final( MD5digest, &MD5context );
197
198         keys[0] = ber_bvdup( &digest );
199         keys[1] = NULL;
200
201         *keysp = keys;
202
203         return LDAP_SUCCESS;
204 }
205
206 static int
207 dnValidate(
208         Syntax *syntax,
209         struct berval *in )
210 {
211         int rc;
212         char *dn;
213
214         if( in->bv_len == 0 ) return LDAP_SUCCESS;
215
216         dn = ch_strdup( in->bv_val );
217
218         rc = dn_validate( dn ) == NULL
219                 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
220
221         ch_free( dn );
222         return rc;
223 }
224
225 static int
226 dnNormalize(
227         Syntax *syntax,
228         struct berval *val,
229         struct berval **normalized )
230 {
231         struct berval *out = ber_bvdup( val );
232
233         if( out->bv_len != 0 ) {
234                 char *dn;
235 #ifdef USE_DN_NORMALIZE
236                 dn = dn_normalize( out->bv_val );
237 #else
238                 dn = dn_validate( out->bv_val );
239 #endif
240
241                 if( dn == NULL ) {
242                         ber_bvfree( out );
243                         return LDAP_INVALID_SYNTAX;
244                 }
245
246                 out->bv_val = dn;
247                 out->bv_len = strlen( dn );
248         }
249
250         *normalized = out;
251         return LDAP_SUCCESS;
252 }
253
254 static int
255 dnMatch(
256         int *matchp,
257         unsigned flags,
258         Syntax *syntax,
259         MatchingRule *mr,
260         struct berval *value,
261         void *assertedValue )
262 {
263         int match;
264         struct berval *asserted = (struct berval *) assertedValue;
265         
266         match = value->bv_len - asserted->bv_len;
267
268         if( match == 0 ) {
269 #ifdef USE_DN_NORMALIZE
270                 match = strcmp( value->bv_val, asserted->bv_val );
271 #else
272                 match = strcasecmp( value->bv_val, asserted->bv_val );
273 #endif
274         }
275
276         Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
277             match, value->bv_val, asserted->bv_val );
278
279         *matchp = match;
280         return LDAP_SUCCESS;
281 }
282
283 static int
284 inValidate(
285         Syntax *syntax,
286         struct berval *in )
287 {
288         /* any value allowed */
289         return LDAP_OTHER;
290 }
291
292 static int
293 blobValidate(
294         Syntax *syntax,
295         struct berval *in )
296 {
297         /* any value allowed */
298         return LDAP_SUCCESS;
299 }
300
301 /*
302  * Handling boolean syntax and matching is quite rigid.
303  * A more flexible approach would be to allow a variety
304  * of strings to be normalized and prettied into TRUE
305  * and FALSE.
306  */
307 static int
308 booleanValidate(
309         Syntax *syntax,
310         struct berval *in )
311 {
312         /* very unforgiving validation, requires no normalization
313          * before simplistic matching
314          */
315
316         if( in->bv_len == 4 ) {
317                 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
318                         return LDAP_SUCCESS;
319                 }
320         } else if( in->bv_len == 5 ) {
321                 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
322                         return LDAP_SUCCESS;
323                 }
324         }
325
326         return LDAP_INVALID_SYNTAX;
327 }
328
329 static int
330 booleanMatch(
331         int *matchp,
332         unsigned flags,
333         Syntax *syntax,
334         MatchingRule *mr,
335         struct berval *value,
336         void *assertedValue )
337 {
338         /* simplistic matching allowed by rigid validation */
339         struct berval *asserted = (struct berval *) assertedValue;
340         *matchp = value->bv_len != asserted->bv_len;
341         return LDAP_SUCCESS;
342 }
343
344 static int
345 UTF8StringValidate(
346         Syntax *syntax,
347         struct berval *in )
348 {
349         ber_len_t count;
350         int len;
351         unsigned char *u = in->bv_val;
352
353         if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
354
355         for( count = in->bv_len; count > 0; count-=len, u+=len ) {
356                 /* get the length indicated by the first byte */
357                 len = LDAP_UTF8_CHARLEN( u );
358
359                 /* should not be zero */
360                 if( len == 0 ) return LDAP_INVALID_SYNTAX;
361
362                 /* make sure len corresponds with the offset
363                         to the next character */
364                 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
365         }
366
367         if( count != 0 ) return LDAP_INVALID_SYNTAX;
368
369         return LDAP_SUCCESS;
370 }
371
372 static int
373 UTF8StringNormalize(
374         Syntax *syntax,
375         struct berval *val,
376         struct berval **normalized )
377 {
378         struct berval *newval;
379         char *p, *q, *s;
380
381         newval = ch_malloc( sizeof( struct berval ) );
382
383         p = val->bv_val;
384
385         /* Ignore initial whitespace */
386         while ( ldap_utf8_isspace( p ) ) {
387                 LDAP_UTF8_INCR( p );
388         }
389
390         if( *p == '\0' ) {
391                 ch_free( newval );
392                 return LDAP_INVALID_SYNTAX;
393         }
394
395         newval->bv_val = ch_strdup( p );
396         p = q = newval->bv_val;
397         s = NULL;
398
399         while ( *p ) {
400                 int len;
401
402                 if ( ldap_utf8_isspace( p ) ) {
403                         len = LDAP_UTF8_COPY(q,p);
404                         s=q;
405                         p+=len;
406                         q+=len;
407
408                         /* Ignore the extra whitespace */
409                         while ( ldap_utf8_isspace( p ) ) {
410                                 LDAP_UTF8_INCR( p );
411                         }
412                 } else {
413                         len = LDAP_UTF8_COPY(q,p);
414                         s=NULL;
415                         p+=len;
416                         q+=len;
417                 }
418         }
419
420         assert( *newval->bv_val );
421         assert( newval->bv_val < p );
422         assert( p >= q );
423
424         /* cannot start with a space */
425         assert( !ldap_utf8_isspace(newval->bv_val) );
426
427         /*
428          * If the string ended in space, backup the pointer one
429          * position.  One is enough because the above loop collapsed
430          * all whitespace to a single space.
431          */
432
433         if ( s != NULL ) {
434                 q = s;
435         }
436
437         /* cannot end with a space */
438         assert( !ldap_utf8_isspace( LDAP_UTF8_PREV(q) ) );
439
440         /* null terminate */
441         *q = '\0';
442
443         newval->bv_len = q - newval->bv_val;
444         *normalized = newval;
445
446         return LDAP_SUCCESS;
447 }
448
449 static int
450 oidValidate(
451         Syntax *syntax,
452         struct berval *val )
453 {
454         ber_len_t i;
455
456         if( val->bv_len == 0 ) return 0;
457
458         if( OID_LEADCHAR(val->bv_val[0]) ) {
459                 int dot = 0;
460                 for(i=1; i < val->bv_len; i++) {
461                         if( OID_SEPARATOR( val->bv_val[i] ) ) {
462                                 if( dot++ ) return 1;
463                         } else if ( OID_CHAR( val->bv_val[i] ) ) {
464                                 dot = 0;
465                         } else {
466                                 return LDAP_INVALID_SYNTAX;
467                         }
468                 }
469
470                 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
471
472         } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
473                 for(i=1; i < val->bv_len; i++) {
474                         if( !DESC_CHAR(val->bv_val[i] ) ) {
475                                 return LDAP_INVALID_SYNTAX;
476                         }
477                 }
478
479                 return LDAP_SUCCESS;
480         }
481         
482         return LDAP_INVALID_SYNTAX;
483 }
484
485 static int
486 integerValidate(
487         Syntax *syntax,
488         struct berval *val )
489 {
490         ber_len_t i;
491
492         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
493
494         for(i=0; i < val->bv_len; i++) {
495                 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
496         }
497
498         return LDAP_SUCCESS;
499 }
500
501 static int
502 printableStringValidate(
503         Syntax *syntax,
504         struct berval *val )
505 {
506         ber_len_t i;
507
508         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
509
510         for(i=0; i < val->bv_len; i++) {
511                 if( !isprint(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
512         }
513
514         return LDAP_SUCCESS;
515 }
516
517 static int
518 IA5StringValidate(
519         Syntax *syntax,
520         struct berval *val )
521 {
522         ber_len_t i;
523
524         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
525
526         for(i=0; i < val->bv_len; i++) {
527                 if( !isascii(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
528         }
529
530         return LDAP_SUCCESS;
531 }
532
533 static int
534 IA5StringConvert(
535         Syntax *syntax,
536         struct berval *in,
537         struct berval **out )
538 {
539         ldap_unicode_t *u;
540         ber_len_t i, len = in->bv_len;
541         struct berval *bv = ch_malloc( sizeof(struct berval) );
542
543         bv->bv_len = len * sizeof( ldap_unicode_t );
544         u = (ldap_unicode_t *) ch_malloc( bv->bv_len + sizeof(ldap_unicode_t) );
545         bv->bv_val = (char *) u;
546
547         for(i=0; i < len; i++ ) {
548                 /*
549                  * IA5StringValidate should have been called to ensure
550                  * input is limited to IA5.
551                  */
552                 u[i] = in->bv_val[i];
553         }
554         u[i] = 0;
555
556         *out = bv;
557         return LDAP_SUCCESS;
558 }
559
560 static int
561 IA5StringNormalize(
562         Syntax *syntax,
563         struct berval *val,
564         struct berval **normalized )
565 {
566         struct berval *newval;
567         char *p, *q;
568
569         newval = ch_malloc( sizeof( struct berval ) );
570
571         p = val->bv_val;
572
573         /* Ignore initial whitespace */
574         while ( ASCII_SPACE( *p ) ) {
575                 p++;
576         }
577
578         if( *p == '\0' ) {
579                 ch_free( newval );
580                 return LDAP_INVALID_SYNTAX;
581         }
582
583         newval->bv_val = ch_strdup( p );
584         p = q = newval->bv_val;
585
586         while ( *p ) {
587                 if ( ASCII_SPACE( *p ) ) {
588                         *q++ = *p++;
589
590                         /* Ignore the extra whitespace */
591                         while ( ASCII_SPACE( *p ) ) {
592                                 p++;
593                         }
594                 } else {
595                         *q++ = *p++;
596                 }
597         }
598
599         assert( *newval->bv_val );
600         assert( newval->bv_val < p );
601         assert( p <= q );
602
603         /* cannot start with a space */
604         assert( !ASCII_SPACE(*newval->bv_val) );
605
606         /*
607          * If the string ended in space, backup the pointer one
608          * position.  One is enough because the above loop collapsed
609          * all whitespace to a single space.
610          */
611
612         if ( ASCII_SPACE( q[-1] ) ) {
613                 --q;
614         }
615
616         /* cannot end with a space */
617         assert( !ASCII_SPACE( q[-1] ) );
618
619         /* null terminate */
620         *q = '\0';
621
622         newval->bv_len = q - newval->bv_val;
623         *normalized = newval;
624
625         return LDAP_SUCCESS;
626 }
627
628 static int
629 caseExactIA5Match(
630         int *matchp,
631         unsigned flags,
632         Syntax *syntax,
633         MatchingRule *mr,
634         struct berval *value,
635         void *assertedValue )
636 {
637         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
638
639         if( match == 0 ) {
640                 match = strncmp( value->bv_val,
641                         ((struct berval *) assertedValue)->bv_val,
642                         value->bv_len );
643         }
644
645         *matchp = match;
646         return LDAP_SUCCESS;
647 }
648
649 static int
650 caseExactIA5SubstringsMatch(
651         int *matchp,
652         unsigned flags,
653         Syntax *syntax,
654         MatchingRule *mr,
655         struct berval *value,
656         void *assertedValue )
657 {
658         int match = 0;
659         SubstringsAssertion *sub = assertedValue;
660         struct berval left = *value;
661         int i;
662         ber_len_t inlen=0;
663
664         /* Add up asserted input length */
665         if( sub->sa_initial ) {
666                 inlen += sub->sa_initial->bv_len;
667         }
668         if( sub->sa_any ) {
669                 for(i=0; sub->sa_any[i] != NULL; i++) {
670                         inlen += sub->sa_any[i]->bv_len;
671                 }
672         }
673         if( sub->sa_final ) {
674                 inlen += sub->sa_final->bv_len;
675         }
676
677         if( sub->sa_initial ) {
678                 if( inlen > left.bv_len ) {
679                         match = 1;
680                         goto done;
681                 }
682
683                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
684                         sub->sa_initial->bv_len );
685
686                 if( match != 0 ) {
687                         goto done;
688                 }
689
690                 left.bv_val += sub->sa_initial->bv_len;
691                 left.bv_len -= sub->sa_initial->bv_len;
692                 inlen -= sub->sa_initial->bv_len;
693         }
694
695         if( sub->sa_final ) {
696                 if( inlen > left.bv_len ) {
697                         match = 1;
698                         goto done;
699                 }
700
701                 match = strncmp( sub->sa_final->bv_val,
702                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
703                         sub->sa_final->bv_len );
704
705                 if( match != 0 ) {
706                         goto done;
707                 }
708
709                 left.bv_len -= sub->sa_final->bv_len;
710                 inlen -= sub->sa_final->bv_len;
711         }
712
713         if( sub->sa_any ) {
714                 for(i=0; sub->sa_any[i]; i++) {
715                         ber_len_t idx;
716                         char *p;
717
718 retry:
719                         if( inlen > left.bv_len ) {
720                                 /* not enough length */
721                                 match = 1;
722                                 goto done;
723                         }
724
725                         if( sub->sa_any[i]->bv_len == 0 ) {
726                                 continue;
727                         }
728
729                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
730
731                         if( p == NULL ) {
732                                 match = 1;
733                                 goto done;
734                         }
735
736                         idx = p - left.bv_val;
737                         assert( idx < left.bv_len );
738
739                         if( idx >= left.bv_len ) {
740                                 /* this shouldn't happen */
741                                 return LDAP_OTHER;
742                         }
743
744                         left.bv_val = p;
745                         left.bv_len -= idx;
746
747                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
748                                 /* not enough left */
749                                 match = 1;
750                                 goto done;
751                         }
752
753                         match = strncmp( left.bv_val,
754                                 sub->sa_any[i]->bv_val,
755                                 sub->sa_any[i]->bv_len );
756
757                         if( match != 0 ) {
758                                 left.bv_val++;
759                                 left.bv_len--;
760                                 goto retry;
761                         }
762
763                         left.bv_val += sub->sa_any[i]->bv_len;
764                         left.bv_len -= sub->sa_any[i]->bv_len;
765                         inlen -= sub->sa_any[i]->bv_len;
766                 }
767         }
768
769 done:
770         *matchp = match;
771         return LDAP_SUCCESS;
772 }
773
774 /* Index generation function */
775 int caseExactIA5Indexer(
776         unsigned flags,
777         Syntax *syntax,
778         MatchingRule *mr,
779         struct berval *prefix,
780         struct berval **values,
781         struct berval ***keysp )
782 {
783         int i;
784         size_t slen, mlen;
785         struct berval **keys;
786         lutil_MD5_CTX   MD5context;
787         unsigned char   MD5digest[16];
788         struct berval digest;
789         digest.bv_val = MD5digest;
790         digest.bv_len = sizeof(MD5digest);
791
792         for( i=0; values[i] != NULL; i++ ) {
793                 /* just count them */
794         }
795
796         assert( i > 0 );
797
798         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
799
800         slen = strlen( syntax->ssyn_oid );
801         mlen = strlen( mr->smr_oid );
802
803         for( i=0; values[i] != NULL; i++ ) {
804                 struct berval *value = values[i];
805
806                 lutil_MD5Init( &MD5context );
807                 if( prefix != NULL && prefix->bv_len > 0 ) {
808                         lutil_MD5Update( &MD5context,
809                                 prefix->bv_val, prefix->bv_len );
810                 }
811                 lutil_MD5Update( &MD5context,
812                         syntax->ssyn_oid, slen );
813                 lutil_MD5Update( &MD5context,
814                         mr->smr_oid, mlen );
815                 lutil_MD5Update( &MD5context,
816                         value->bv_val, value->bv_len );
817                 lutil_MD5Final( MD5digest, &MD5context );
818
819                 keys[i] = ber_bvdup( &digest );
820         }
821
822         keys[i] = NULL;
823         *keysp = keys;
824         return LDAP_SUCCESS;
825 }
826
827 /* Index generation function */
828 int caseExactIA5Filter(
829         unsigned flags,
830         Syntax *syntax,
831         MatchingRule *mr,
832         struct berval *prefix,
833         void * assertValue,
834         struct berval ***keysp )
835 {
836         size_t slen, mlen;
837         struct berval **keys;
838         lutil_MD5_CTX   MD5context;
839         unsigned char   MD5digest[LUTIL_MD5_BYTES];
840         struct berval *value;
841         struct berval digest;
842         digest.bv_val = MD5digest;
843         digest.bv_len = sizeof(MD5digest);
844
845         slen = strlen( syntax->ssyn_oid );
846         mlen = strlen( mr->smr_oid );
847
848         value = (struct berval *) assertValue;
849
850         keys = ch_malloc( sizeof( struct berval * ) * 2 );
851
852         lutil_MD5Init( &MD5context );
853         if( prefix != NULL && prefix->bv_len > 0 ) {
854                 lutil_MD5Update( &MD5context,
855                         prefix->bv_val, prefix->bv_len );
856         }
857         lutil_MD5Update( &MD5context,
858                 syntax->ssyn_oid, slen );
859         lutil_MD5Update( &MD5context,
860                 mr->smr_oid, mlen );
861         lutil_MD5Update( &MD5context,
862                 value->bv_val, value->bv_len );
863         lutil_MD5Final( MD5digest, &MD5context );
864
865         keys[0] = ber_bvdup( &digest );
866         keys[1] = NULL;
867
868         *keysp = keys;
869         return LDAP_SUCCESS;
870 }
871
872 /* Substrings Index generation function */
873 int caseExactIA5SubstringsIndexer(
874         unsigned flags,
875         Syntax *syntax,
876         MatchingRule *mr,
877         struct berval *prefix,
878         struct berval **values,
879         struct berval ***keysp )
880 {
881         ber_len_t i, nkeys;
882         size_t slen, mlen;
883         struct berval **keys;
884         lutil_MD5_CTX   MD5context;
885         unsigned char   MD5digest[16];
886         struct berval digest;
887         digest.bv_val = MD5digest;
888         digest.bv_len = sizeof(MD5digest);
889
890         nkeys=0;
891         for( i=0; values[i] != NULL; i++ ) {
892                 /* count number of indices to generate */
893                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
894                         continue;
895                 }
896
897                 if( flags & SLAP_MR_SUBSTR_INITIAL ) {
898                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
899                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
900                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
901                         } else {
902                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
903                         }
904                 }
905
906                 if( flags & SLAP_MR_SUBSTR_ANY ) {
907                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
908                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
909                         }
910                 }
911
912                 if( flags & SLAP_MR_SUBSTR_FINAL ) {
913                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
914                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
915                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
916                         } else {
917                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
918                         }
919                 }
920         }
921         assert( i > 0 );
922
923         if( nkeys == 0 ) {
924                 /* no keys to generate */
925                 *keysp = NULL;
926                 return LDAP_SUCCESS;
927         }
928
929         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
930
931         slen = strlen( syntax->ssyn_oid );
932         mlen = strlen( mr->smr_oid );
933
934         nkeys=0;
935         for( i=0; values[i] != NULL; i++ ) {
936                 ber_len_t j,max;
937                 struct berval *value;
938
939                 value = values[i];
940                 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
941
942                 if( ( flags & SLAP_MR_SUBSTR_ANY ) &&
943                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
944                 {
945                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
946                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
947
948                         for( j=0; j<max; j++ ) {
949                                 lutil_MD5Init( &MD5context );
950                                 if( prefix != NULL && prefix->bv_len > 0 ) {
951                                         lutil_MD5Update( &MD5context,
952                                                 prefix->bv_val, prefix->bv_len );
953                                 }
954
955                                 lutil_MD5Update( &MD5context,
956                                         &pre, sizeof( pre ) );
957                                 lutil_MD5Update( &MD5context,
958                                         syntax->ssyn_oid, slen );
959                                 lutil_MD5Update( &MD5context,
960                                         mr->smr_oid, mlen );
961                                 lutil_MD5Update( &MD5context,
962                                         &value->bv_val[j],
963                                         SLAP_INDEX_SUBSTR_MAXLEN );
964                                 lutil_MD5Final( MD5digest, &MD5context );
965
966                                 keys[nkeys++] = ber_bvdup( &digest );
967                         }
968                 }
969
970                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
971                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
972
973                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
974                         char pre;
975
976                         if( flags & SLAP_MR_SUBSTR_INITIAL ) {
977                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
978                                 lutil_MD5Init( &MD5context );
979                                 if( prefix != NULL && prefix->bv_len > 0 ) {
980                                         lutil_MD5Update( &MD5context,
981                                                 prefix->bv_val, prefix->bv_len );
982                                 }
983                                 lutil_MD5Update( &MD5context,
984                                         &pre, sizeof( pre ) );
985                                 lutil_MD5Update( &MD5context,
986                                         syntax->ssyn_oid, slen );
987                                 lutil_MD5Update( &MD5context,
988                                         mr->smr_oid, mlen );
989                                 lutil_MD5Update( &MD5context,
990                                         value->bv_val, j );
991                                 lutil_MD5Final( MD5digest, &MD5context );
992
993                                 keys[nkeys++] = ber_bvdup( &digest );
994                         }
995
996                         if( flags & SLAP_MR_SUBSTR_FINAL ) {
997                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
998                                 lutil_MD5Init( &MD5context );
999                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1000                                         lutil_MD5Update( &MD5context,
1001                                                 prefix->bv_val, prefix->bv_len );
1002                                 }
1003                                 lutil_MD5Update( &MD5context,
1004                                         &pre, sizeof( pre ) );
1005                                 lutil_MD5Update( &MD5context,
1006                                         syntax->ssyn_oid, slen );
1007                                 lutil_MD5Update( &MD5context,
1008                                         mr->smr_oid, mlen );
1009                                 lutil_MD5Update( &MD5context,
1010                                         &value->bv_val[value->bv_len-j], j );
1011                                 lutil_MD5Final( MD5digest, &MD5context );
1012
1013                                 keys[nkeys++] = ber_bvdup( &digest );
1014                         }
1015
1016                 }
1017         }
1018
1019         keys[nkeys] = NULL;
1020         *keysp = keys;
1021         return LDAP_SUCCESS;
1022 }
1023
1024 int caseExactIA5SubstringsFilter(
1025         unsigned flags,
1026         Syntax *syntax,
1027         MatchingRule *mr,
1028         struct berval *prefix,
1029         void * assertValue,
1030         struct berval ***keysp )
1031 {
1032         SubstringsAssertion *sa = assertValue;
1033         char pre;
1034         ber_len_t nkeys = 0;
1035         size_t slen, mlen, klen;
1036         struct berval **keys;
1037         lutil_MD5_CTX   MD5context;
1038         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1039         struct berval *value;
1040         struct berval digest;
1041
1042         if( sa->sa_initial != NULL &&
1043                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1044         {
1045                 nkeys++;
1046         }
1047
1048         if( sa->sa_any ) {
1049                 ber_len_t i;
1050                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1051                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1052                                 /* don't bother accounting for stepping */
1053                                 nkeys += sa->sa_any[i]->bv_len -
1054                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1055                         }
1056                 }
1057         }
1058
1059         if( sa->sa_final != NULL &&
1060                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1061         {
1062                 nkeys++;
1063         }
1064
1065         if( nkeys == 0 ) {
1066                 *keysp = NULL;
1067                 return LDAP_SUCCESS;
1068         }
1069
1070         digest.bv_val = MD5digest;
1071         digest.bv_len = sizeof(MD5digest);
1072
1073         slen = strlen( syntax->ssyn_oid );
1074         mlen = strlen( mr->smr_oid );
1075
1076         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1077         nkeys = 0;
1078
1079         if( sa->sa_initial != NULL &&
1080                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1081         {
1082                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1083                 value = sa->sa_initial;
1084
1085                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1086                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1087
1088                 lutil_MD5Init( &MD5context );
1089                 if( prefix != NULL && prefix->bv_len > 0 ) {
1090                         lutil_MD5Update( &MD5context,
1091                                 prefix->bv_val, prefix->bv_len );
1092                 }
1093                 lutil_MD5Update( &MD5context,
1094                         &pre, sizeof( pre ) );
1095                 lutil_MD5Update( &MD5context,
1096                         syntax->ssyn_oid, slen );
1097                 lutil_MD5Update( &MD5context,
1098                         mr->smr_oid, mlen );
1099                 lutil_MD5Update( &MD5context,
1100                         value->bv_val, klen );
1101                 lutil_MD5Final( MD5digest, &MD5context );
1102
1103                 keys[nkeys++] = ber_bvdup( &digest );
1104         }
1105
1106         if( sa->sa_any ) {
1107                 ber_len_t i, j;
1108                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1109                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1110
1111                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1112                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1113                                 continue;
1114                         }
1115
1116                         value = sa->sa_any[i];
1117
1118                         for(j=0; j<sa->sa_any[i]->bv_len; j+= SLAP_INDEX_SUBSTR_STEP ) {
1119
1120                                 lutil_MD5Init( &MD5context );
1121                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1122                                         lutil_MD5Update( &MD5context,
1123                                                 prefix->bv_val, prefix->bv_len );
1124                                 }
1125                                 lutil_MD5Update( &MD5context,
1126                                         &pre, sizeof( pre ) );
1127                                 lutil_MD5Update( &MD5context,
1128                                         syntax->ssyn_oid, slen );
1129                                 lutil_MD5Update( &MD5context,
1130                                         mr->smr_oid, mlen );
1131                                 lutil_MD5Update( &MD5context,
1132                                         &value->bv_val[j], klen ); 
1133                                 lutil_MD5Final( MD5digest, &MD5context );
1134
1135                                 keys[nkeys++] = ber_bvdup( &digest );
1136                         }
1137                 }
1138         }
1139
1140         if( sa->sa_final != NULL &&
1141                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1142         {
1143                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1144                 value = sa->sa_final;
1145
1146                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1147                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1148
1149                 lutil_MD5Init( &MD5context );
1150                 if( prefix != NULL && prefix->bv_len > 0 ) {
1151                         lutil_MD5Update( &MD5context,
1152                                 prefix->bv_val, prefix->bv_len );
1153                 }
1154                 lutil_MD5Update( &MD5context,
1155                         &pre, sizeof( pre ) );
1156                 lutil_MD5Update( &MD5context,
1157                         syntax->ssyn_oid, slen );
1158                 lutil_MD5Update( &MD5context,
1159                         mr->smr_oid, mlen );
1160                 lutil_MD5Update( &MD5context,
1161                         &value->bv_val[value->bv_len-klen], klen );
1162                 lutil_MD5Final( MD5digest, &MD5context );
1163
1164                 keys[nkeys++] = ber_bvdup( &digest );
1165         }
1166
1167         keys[nkeys] = NULL;
1168
1169         *keysp = keys;
1170         return LDAP_SUCCESS;
1171 }
1172         
1173 static int
1174 caseIgnoreIA5Match(
1175         int *matchp,
1176         unsigned flags,
1177         Syntax *syntax,
1178         MatchingRule *mr,
1179         struct berval *value,
1180         void *assertedValue )
1181 {
1182         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
1183
1184         if( match == 0 ) {
1185                 match = strncasecmp( value->bv_val,
1186                         ((struct berval *) assertedValue)->bv_val,
1187                         value->bv_len );
1188         }
1189
1190         *matchp = match;
1191         return LDAP_SUCCESS;
1192 }
1193
1194 static char *strcasechr( const char *str, int c )
1195 {
1196         char *lower = strchr( str, TOLOWER(c) );
1197         char *upper = strchr( str, TOUPPER(c) );
1198
1199         if( lower && upper ) {
1200                 return lower < upper ? lower : upper;
1201         } else if ( lower ) {
1202                 return lower;
1203         } else {
1204                 return upper;
1205         }
1206 }
1207
1208 static int
1209 caseIgnoreIA5SubstringsMatch(
1210         int *matchp,
1211         unsigned flags,
1212         Syntax *syntax,
1213         MatchingRule *mr,
1214         struct berval *value,
1215         void *assertedValue )
1216 {
1217         int match = 0;
1218         SubstringsAssertion *sub = assertedValue;
1219         struct berval left = *value;
1220         int i;
1221         ber_len_t inlen=0;
1222
1223         /* Add up asserted input length */
1224         if( sub->sa_initial ) {
1225                 inlen += sub->sa_initial->bv_len;
1226         }
1227         if( sub->sa_any ) {
1228                 for(i=0; sub->sa_any[i] != NULL; i++) {
1229                         inlen += sub->sa_any[i]->bv_len;
1230                 }
1231         }
1232         if( sub->sa_final ) {
1233                 inlen += sub->sa_final->bv_len;
1234         }
1235
1236         if( sub->sa_initial ) {
1237                 if( inlen > left.bv_len ) {
1238                         match = 1;
1239                         goto done;
1240                 }
1241
1242                 match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
1243                         sub->sa_initial->bv_len );
1244
1245                 if( match != 0 ) {
1246                         goto done;
1247                 }
1248
1249                 left.bv_val += sub->sa_initial->bv_len;
1250                 left.bv_len -= sub->sa_initial->bv_len;
1251                 inlen -= sub->sa_initial->bv_len;
1252         }
1253
1254         if( sub->sa_final ) {
1255                 if( inlen > left.bv_len ) {
1256                         match = 1;
1257                         goto done;
1258                 }
1259
1260                 match = strncasecmp( sub->sa_final->bv_val,
1261                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1262                         sub->sa_final->bv_len );
1263
1264                 if( match != 0 ) {
1265                         goto done;
1266                 }
1267
1268                 left.bv_len -= sub->sa_final->bv_len;
1269                 inlen -= sub->sa_final->bv_len;
1270         }
1271
1272         if( sub->sa_any ) {
1273                 for(i=0; sub->sa_any[i]; i++) {
1274                         ber_len_t idx;
1275                         char *p;
1276
1277 retry:
1278                         if( inlen > left.bv_len ) {
1279                                 /* not enough length */
1280                                 match = 1;
1281                                 goto done;
1282                         }
1283
1284                         if( sub->sa_any[i]->bv_len == 0 ) {
1285                                 continue;
1286                         }
1287
1288                         p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );
1289
1290                         if( p == NULL ) {
1291                                 match = 1;
1292                                 goto done;
1293                         }
1294
1295                         idx = p - left.bv_val;
1296                         assert( idx < left.bv_len );
1297
1298                         if( idx >= left.bv_len ) {
1299                                 /* this shouldn't happen */
1300                                 return LDAP_OTHER;
1301                         }
1302
1303                         left.bv_val = p;
1304                         left.bv_len -= idx;
1305
1306                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
1307                                 /* not enough left */
1308                                 match = 1;
1309                                 goto done;
1310                         }
1311
1312                         match = strncasecmp( left.bv_val,
1313                                 sub->sa_any[i]->bv_val,
1314                                 sub->sa_any[i]->bv_len );
1315
1316                         if( match != 0 ) {
1317                                 left.bv_val++;
1318                                 left.bv_len--;
1319
1320                                 goto retry;
1321                         }
1322
1323                         left.bv_val += sub->sa_any[i]->bv_len;
1324                         left.bv_len -= sub->sa_any[i]->bv_len;
1325                         inlen -= sub->sa_any[i]->bv_len;
1326                 }
1327         }
1328
1329 done:
1330         *matchp = match;
1331         return LDAP_SUCCESS;
1332 }
1333
1334 /* Index generation function */
1335 int caseIgnoreIA5Indexer(
1336         unsigned flags,
1337         Syntax *syntax,
1338         MatchingRule *mr,
1339         struct berval *prefix,
1340         struct berval **values,
1341         struct berval ***keysp )
1342 {
1343         int i;
1344         size_t slen, mlen;
1345         struct berval **keys;
1346         lutil_MD5_CTX   MD5context;
1347         unsigned char   MD5digest[16];
1348         struct berval digest;
1349         digest.bv_val = MD5digest;
1350         digest.bv_len = sizeof(MD5digest);
1351
1352         for( i=0; values[i] != NULL; i++ ) {
1353                 /* just count them */
1354         }
1355
1356         assert( i > 0 );
1357
1358         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
1359
1360         slen = strlen( syntax->ssyn_oid );
1361         mlen = strlen( mr->smr_oid );
1362
1363         for( i=0; values[i] != NULL; i++ ) {
1364                 struct berval *value = ber_bvdup( values[i] );
1365                 ldap_pvt_str2upper( value->bv_val );
1366
1367                 lutil_MD5Init( &MD5context );
1368                 if( prefix != NULL && prefix->bv_len > 0 ) {
1369                         lutil_MD5Update( &MD5context,
1370                                 prefix->bv_val, prefix->bv_len );
1371                 }
1372                 lutil_MD5Update( &MD5context,
1373                         syntax->ssyn_oid, slen );
1374                 lutil_MD5Update( &MD5context,
1375                         mr->smr_oid, mlen );
1376                 lutil_MD5Update( &MD5context,
1377                         value->bv_val, value->bv_len );
1378                 lutil_MD5Final( MD5digest, &MD5context );
1379
1380                 ber_bvfree( value );
1381
1382                 keys[i] = ber_bvdup( &digest );
1383         }
1384
1385         keys[i] = NULL;
1386         *keysp = keys;
1387         return LDAP_SUCCESS;
1388 }
1389
1390 /* Index generation function */
1391 int caseIgnoreIA5Filter(
1392         unsigned flags,
1393         Syntax *syntax,
1394         MatchingRule *mr,
1395         struct berval *prefix,
1396         void * assertValue,
1397         struct berval ***keysp )
1398 {
1399         size_t slen, mlen;
1400         struct berval **keys;
1401         lutil_MD5_CTX   MD5context;
1402         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1403         struct berval *value;
1404         struct berval digest;
1405         digest.bv_val = MD5digest;
1406         digest.bv_len = sizeof(MD5digest);
1407
1408         slen = strlen( syntax->ssyn_oid );
1409         mlen = strlen( mr->smr_oid );
1410
1411         value = ber_bvdup( (struct berval *) assertValue );
1412         ldap_pvt_str2upper( value->bv_val );
1413
1414         keys = ch_malloc( sizeof( struct berval * ) * 2 );
1415
1416         lutil_MD5Init( &MD5context );
1417         if( prefix != NULL && prefix->bv_len > 0 ) {
1418                 lutil_MD5Update( &MD5context,
1419                         prefix->bv_val, prefix->bv_len );
1420         }
1421         lutil_MD5Update( &MD5context,
1422                 syntax->ssyn_oid, slen );
1423         lutil_MD5Update( &MD5context,
1424                 mr->smr_oid, mlen );
1425         lutil_MD5Update( &MD5context,
1426                 value->bv_val, value->bv_len );
1427         lutil_MD5Final( MD5digest, &MD5context );
1428
1429         keys[0] = ber_bvdup( &digest );
1430         keys[1] = NULL;
1431
1432         ber_bvfree( value );
1433
1434         *keysp = keys;
1435         return LDAP_SUCCESS;
1436 }
1437
1438 /* Substrings Index generation function */
1439 int caseIgnoreIA5SubstringsIndexer(
1440         unsigned flags,
1441         Syntax *syntax,
1442         MatchingRule *mr,
1443         struct berval *prefix,
1444         struct berval **values,
1445         struct berval ***keysp )
1446 {
1447         ber_len_t i, nkeys;
1448         size_t slen, mlen;
1449         struct berval **keys;
1450         lutil_MD5_CTX   MD5context;
1451         unsigned char   MD5digest[16];
1452         struct berval digest;
1453         digest.bv_val = MD5digest;
1454         digest.bv_len = sizeof(MD5digest);
1455
1456         nkeys=0;
1457         for( i=0; values[i] != NULL; i++ ) {
1458                 /* count number of indices to generate */
1459                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1460                         continue;
1461                 }
1462
1463                 if( flags & SLAP_MR_SUBSTR_INITIAL ) {
1464                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1465                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1466                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1467                         } else {
1468                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1469                         }
1470                 }
1471
1472                 if( flags & SLAP_MR_SUBSTR_ANY ) {
1473                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1474                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1475                         }
1476                 }
1477
1478                 if( flags & SLAP_MR_SUBSTR_FINAL ) {
1479                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1480                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1481                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1482                         } else {
1483                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1484                         }
1485                 }
1486         }
1487         assert( i > 0 );
1488
1489         if( nkeys == 0 ) {
1490                 /* no keys to generate */
1491                 *keysp = NULL;
1492                 return LDAP_SUCCESS;
1493         }
1494
1495         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1496
1497         slen = strlen( syntax->ssyn_oid );
1498         mlen = strlen( mr->smr_oid );
1499
1500         nkeys=0;
1501         for( i=0; values[i] != NULL; i++ ) {
1502                 int j,max;
1503                 struct berval *value;
1504
1505                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1506
1507                 value = ber_bvdup( values[i] );
1508                 ldap_pvt_str2upper( value->bv_val );
1509
1510                 if( ( flags & SLAP_MR_SUBSTR_ANY ) &&
1511                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1512                 {
1513                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
1514                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1515
1516                         for( j=0; j<max; j++ ) {
1517                                 lutil_MD5Init( &MD5context );
1518                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1519                                         lutil_MD5Update( &MD5context,
1520                                                 prefix->bv_val, prefix->bv_len );
1521                                 }
1522
1523                                 lutil_MD5Update( &MD5context,
1524                                         &pre, sizeof( pre ) );
1525                                 lutil_MD5Update( &MD5context,
1526                                         syntax->ssyn_oid, slen );
1527                                 lutil_MD5Update( &MD5context,
1528                                         mr->smr_oid, mlen );
1529                                 lutil_MD5Update( &MD5context,
1530                                         &value->bv_val[j],
1531                                         SLAP_INDEX_SUBSTR_MAXLEN );
1532                                 lutil_MD5Final( MD5digest, &MD5context );
1533
1534                                 keys[nkeys++] = ber_bvdup( &digest );
1535                         }
1536                 }
1537
1538                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1539                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1540
1541                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1542                         char pre;
1543
1544                         if( flags & SLAP_MR_SUBSTR_INITIAL ) {
1545                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1546                                 lutil_MD5Init( &MD5context );
1547                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1548                                         lutil_MD5Update( &MD5context,
1549                                                 prefix->bv_val, prefix->bv_len );
1550                                 }
1551                                 lutil_MD5Update( &MD5context,
1552                                         &pre, sizeof( pre ) );
1553                                 lutil_MD5Update( &MD5context,
1554                                         syntax->ssyn_oid, slen );
1555                                 lutil_MD5Update( &MD5context,
1556                                         mr->smr_oid, mlen );
1557                                 lutil_MD5Update( &MD5context,
1558                                         value->bv_val, j );
1559                                 lutil_MD5Final( MD5digest, &MD5context );
1560
1561                                 keys[nkeys++] = ber_bvdup( &digest );
1562                         }
1563
1564                         if( flags & SLAP_MR_SUBSTR_FINAL ) {
1565                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1566                                 lutil_MD5Init( &MD5context );
1567                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1568                                         lutil_MD5Update( &MD5context,
1569                                                 prefix->bv_val, prefix->bv_len );
1570                                 }
1571                                 lutil_MD5Update( &MD5context,
1572                                         &pre, sizeof( pre ) );
1573                                 lutil_MD5Update( &MD5context,
1574                                         syntax->ssyn_oid, slen );
1575                                 lutil_MD5Update( &MD5context,
1576                                         mr->smr_oid, mlen );
1577                                 lutil_MD5Update( &MD5context,
1578                                         &value->bv_val[value->bv_len-j], j );
1579                                 lutil_MD5Final( MD5digest, &MD5context );
1580
1581                                 keys[nkeys++] = ber_bvdup( &digest );
1582                         }
1583
1584                 }
1585
1586                 ber_bvfree( value );
1587         }
1588
1589         keys[nkeys] = NULL;
1590         *keysp = keys;
1591         return LDAP_SUCCESS;
1592 }
1593
1594 int caseIgnoreIA5SubstringsFilter(
1595         unsigned flags,
1596         Syntax *syntax,
1597         MatchingRule *mr,
1598         struct berval *prefix,
1599         void * assertValue,
1600         struct berval ***keysp )
1601 {
1602         SubstringsAssertion *sa = assertValue;
1603         char pre;
1604         ber_len_t nkeys = 0;
1605         size_t slen, mlen, klen;
1606         struct berval **keys;
1607         lutil_MD5_CTX   MD5context;
1608         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1609         struct berval *value;
1610         struct berval digest;
1611
1612         if( sa->sa_initial != NULL &&
1613                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1614         {
1615                 nkeys++;
1616         }
1617
1618         if( sa->sa_any ) {
1619                 ber_len_t i;
1620                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1621                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1622                                 /* don't bother accounting for stepping */
1623                                 nkeys += sa->sa_any[i]->bv_len -
1624                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1625                         }
1626                 }
1627         }
1628
1629         if( sa->sa_final != NULL &&
1630                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1631         {
1632                 nkeys++;
1633         }
1634
1635         if( nkeys == 0 ) {
1636                 *keysp = NULL;
1637                 return LDAP_SUCCESS;
1638         }
1639
1640         digest.bv_val = MD5digest;
1641         digest.bv_len = sizeof(MD5digest);
1642
1643         slen = strlen( syntax->ssyn_oid );
1644         mlen = strlen( mr->smr_oid );
1645
1646         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1647         nkeys = 0;
1648
1649         if( sa->sa_initial != NULL &&
1650                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1651         {
1652                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1653                 value = ber_bvdup( sa->sa_initial );
1654                 ldap_pvt_str2upper( value->bv_val );
1655
1656                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1657                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1658
1659                 lutil_MD5Init( &MD5context );
1660                 if( prefix != NULL && prefix->bv_len > 0 ) {
1661                         lutil_MD5Update( &MD5context,
1662                                 prefix->bv_val, prefix->bv_len );
1663                 }
1664                 lutil_MD5Update( &MD5context,
1665                         &pre, sizeof( pre ) );
1666                 lutil_MD5Update( &MD5context,
1667                         syntax->ssyn_oid, slen );
1668                 lutil_MD5Update( &MD5context,
1669                         mr->smr_oid, mlen );
1670                 lutil_MD5Update( &MD5context,
1671                         value->bv_val, klen );
1672                 lutil_MD5Final( MD5digest, &MD5context );
1673
1674                 ber_bvfree( value );
1675                 keys[nkeys++] = ber_bvdup( &digest );
1676         }
1677
1678         if( sa->sa_any ) {
1679                 ber_len_t i, j;
1680                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1681                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1682
1683                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1684                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1685                                 continue;
1686                         }
1687
1688                         value = ber_bvdup( sa->sa_any[i] );
1689                         ldap_pvt_str2upper( value->bv_val );
1690
1691                         for(j=0; j<sa->sa_any[i]->bv_len; j+= SLAP_INDEX_SUBSTR_STEP ) {
1692                                 lutil_MD5Init( &MD5context );
1693                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1694                                         lutil_MD5Update( &MD5context,
1695                                                 prefix->bv_val, prefix->bv_len );
1696                                 }
1697                                 lutil_MD5Update( &MD5context,
1698                                         &pre, sizeof( pre ) );
1699                                 lutil_MD5Update( &MD5context,
1700                                         syntax->ssyn_oid, slen );
1701                                 lutil_MD5Update( &MD5context,
1702                                         mr->smr_oid, mlen );
1703                                 lutil_MD5Update( &MD5context,
1704                                         &value->bv_val[j], klen );
1705                                 lutil_MD5Final( MD5digest, &MD5context );
1706
1707                                 keys[nkeys++] = ber_bvdup( &digest );
1708                         }
1709
1710                         ber_bvfree( value );
1711                 }
1712         }
1713
1714         if( sa->sa_final != NULL &&
1715                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1716         {
1717                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1718                 value = ber_bvdup( sa->sa_final );
1719                 ldap_pvt_str2upper( value->bv_val );
1720
1721                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1722                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1723
1724                 lutil_MD5Init( &MD5context );
1725                 if( prefix != NULL && prefix->bv_len > 0 ) {
1726                         lutil_MD5Update( &MD5context,
1727                                 prefix->bv_val, prefix->bv_len );
1728                 }
1729                 lutil_MD5Update( &MD5context,
1730                         &pre, sizeof( pre ) );
1731                 lutil_MD5Update( &MD5context,
1732                         syntax->ssyn_oid, slen );
1733                 lutil_MD5Update( &MD5context,
1734                         mr->smr_oid, mlen );
1735                 lutil_MD5Update( &MD5context,
1736                         &value->bv_val[value->bv_len-klen], klen );
1737                 lutil_MD5Final( MD5digest, &MD5context );
1738
1739                 ber_bvfree( value );
1740                 keys[nkeys++] = ber_bvdup( &digest );
1741         }
1742
1743         keys[nkeys] = NULL;
1744
1745         *keysp = keys;
1746         return LDAP_SUCCESS;
1747 }
1748         
1749 static int
1750 numericStringNormalize(
1751         Syntax *syntax,
1752         struct berval *val,
1753         struct berval **normalized )
1754 {
1755         /* similiar to IA5StringNormalize except removes all spaces */
1756         struct berval *newval;
1757         char *p, *q;
1758
1759         newval = ch_malloc( sizeof( struct berval ) );
1760
1761         p = val->bv_val;
1762
1763         /* Ignore initial whitespace */
1764         while ( ASCII_SPACE( *p ) ) {
1765                 p++;
1766         }
1767
1768         if( *p == '\0' ) {
1769                 ch_free( newval );
1770                 return LDAP_INVALID_SYNTAX;
1771         }
1772
1773         newval->bv_val = ch_strdup( p );
1774         p = q = newval->bv_val;
1775
1776         while ( *p ) {
1777                 if ( ASCII_SPACE( *p ) ) {
1778                         /* Ignore whitespace */
1779                         p++;
1780                 } else {
1781                         *q++ = *p++;
1782                 }
1783         }
1784
1785         assert( *newval->bv_val );
1786         assert( newval->bv_val < p );
1787         assert( q <= p );
1788
1789         /* cannot start with a space */
1790         assert( !ASCII_SPACE(*newval->bv_val) );
1791
1792         /* cannot end with a space */
1793         assert( !ASCII_SPACE( q[-1] ) );
1794
1795         /* null terminate */
1796         *q = '\0';
1797
1798         newval->bv_len = q - newval->bv_val;
1799         *normalized = newval;
1800
1801         return LDAP_SUCCESS;
1802 }
1803
1804 static int
1805 objectIdentifierFirstComponentMatch(
1806         int *matchp,
1807         unsigned flags,
1808         Syntax *syntax,
1809         MatchingRule *mr,
1810         struct berval *value,
1811         void *assertedValue )
1812 {
1813         int rc = LDAP_SUCCESS;
1814         int match;
1815         struct berval *asserted = (struct berval *) assertedValue;
1816         ber_len_t i;
1817         struct berval oid;
1818
1819         if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1820                 return LDAP_INVALID_SYNTAX;
1821         }
1822
1823         /* trim leading white space */
1824         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1825                 /* empty */
1826         }
1827
1828         /* grab next word */
1829         oid.bv_val = &value->bv_val[i];
1830         oid.bv_len = value->bv_len - i;
1831         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
1832                 /* empty */
1833         }
1834         oid.bv_len = i;
1835
1836         /* insert attributeTypes, objectclass check here */
1837         if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1838                 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1839
1840         } else {
1841                 char *stored = ch_malloc( oid.bv_len + 1 );
1842                 AC_MEMCPY( stored, oid.bv_val, oid.bv_len );
1843                 stored[oid.bv_len] = '\0';
1844
1845                 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1846                         MatchingRule *asserted_mr = mr_find( asserted->bv_val );
1847                         MatchingRule *stored_mr = mr_find( stored );
1848
1849                         if( asserted_mr == NULL ) {
1850                                 rc = SLAPD_COMPARE_UNDEFINED;
1851                         } else {
1852                                 match = asserted_mr != stored_mr;
1853                         }
1854
1855                 } else if ( !strcmp( syntax->ssyn_oid,
1856                         SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1857                 {
1858                         AttributeType *asserted_at = at_find( asserted->bv_val );
1859                         AttributeType *stored_at = at_find( stored );
1860
1861                         if( asserted_at == NULL ) {
1862                                 rc = SLAPD_COMPARE_UNDEFINED;
1863                         } else {
1864                                 match = asserted_at != stored_at;
1865                         }
1866
1867                 } else if ( !strcmp( syntax->ssyn_oid,
1868                         SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1869                 {
1870                         ObjectClass *asserted_oc = oc_find( asserted->bv_val );
1871                         ObjectClass *stored_oc = oc_find( stored );
1872
1873                         if( asserted_oc == NULL ) {
1874                                 rc = SLAPD_COMPARE_UNDEFINED;
1875                         } else {
1876                                 match = asserted_oc != stored_oc;
1877                         }
1878                 }
1879
1880                 ch_free( stored );
1881         }
1882
1883         Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1884                 "%d\n\t\"%s\"\n\t\"%s\"\n",
1885             match, value->bv_val, asserted->bv_val );
1886
1887         if( rc == LDAP_SUCCESS ) *matchp = match;
1888         return rc;
1889 }
1890
1891 static int
1892 check_time_syntax (struct berval *val,
1893         int start,
1894         int *parts)
1895 {
1896         static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
1897         static int mdays[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1898         char *p, *e;
1899         int part, c, neg = 0;
1900
1901         if( val->bv_len == 0 )
1902                 return LDAP_INVALID_SYNTAX;
1903
1904         p = (char *)val->bv_val;
1905         e = p + val->bv_len;
1906
1907         /* Ignore initial whitespace */
1908         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
1909                 p++;
1910         }
1911
1912         if (e - p < 13 - (2 * start))
1913                 return LDAP_INVALID_SYNTAX;
1914
1915         for (part = 0; part < 9; part++)
1916                 parts[part] = 0;
1917
1918         for (part = start; part < 7; part++) {
1919                 c = *p;
1920                 if ((part == 6)
1921                         && (c == 'Z'
1922                                 || c == '+'
1923                                 || c == '-'))
1924                 {
1925                         part++;
1926                         break;
1927                 }
1928                 p++;
1929                 c -= '0';
1930                 if (p == e)
1931                         return LDAP_INVALID_SYNTAX;
1932                 if (c < 0 || c > 9)
1933                         return LDAP_INVALID_SYNTAX;
1934                 parts[part] = c;
1935
1936                 c = *p++ - '0';
1937                 if (p == e)
1938                         return LDAP_INVALID_SYNTAX;
1939                 if (c < 0 || c > 9)
1940                         return LDAP_INVALID_SYNTAX;
1941                 parts[part] *= 10;
1942                 parts[part] += c;
1943
1944                 if (part == 2 || part == 3)
1945                         parts[part]--;
1946                 if (parts[part] < 0)
1947                         return LDAP_INVALID_SYNTAX;
1948                 if (parts[part] > ceiling[part])
1949                         return LDAP_INVALID_SYNTAX;
1950         }
1951         if (parts[2] == 1) {
1952                 if (parts[3] > mdays[parts[2]])
1953                         return LDAP_INVALID_SYNTAX;
1954                 if (parts[1] & 0x03) {
1955                         /* FIXME:  This is an incomplete leap-year
1956                          * check that fails in 2100, 2200, 2300,
1957                          * 2500, 2600, 2700, ...
1958                          */
1959                         if (parts[3] > mdays[parts[2]] - 1)
1960                                 return LDAP_INVALID_SYNTAX;
1961                 }
1962         }
1963         c = *p++;
1964         if (c == 'Z') {
1965                 /* all done */
1966         } else if (c != '+' && c != '-') {
1967                 return LDAP_INVALID_SYNTAX;
1968         } else {
1969                 if (c == '-')
1970                         neg = 1;
1971                 if (p > e - 4)
1972                         return LDAP_INVALID_SYNTAX;
1973                 for (part = 7; part < 9; part++) {
1974                         c = *p++ - '0';
1975                         if (c < 0 || c > 9)
1976                                 return LDAP_INVALID_SYNTAX;
1977                         parts[part] = c;
1978
1979                         c = *p++ - '0';
1980                         if (c < 0 || c > 9)
1981                                 return LDAP_INVALID_SYNTAX;
1982                         parts[part] *= 10;
1983                         parts[part] += c;
1984                         if (parts[part] < 0 || parts[part] > ceiling[part])
1985                                 return LDAP_INVALID_SYNTAX;
1986                 }
1987         }
1988
1989         /* Ignore trailing whitespace */
1990         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
1991                 p++;
1992         }
1993         if (p != e)
1994                 return LDAP_INVALID_SYNTAX;
1995
1996         if (neg == 0) {
1997                 parts[4] += parts[7];
1998                 parts[5] += parts[8];
1999                 for (part = 7; --part > 0; ) {
2000                         if (part != 3)
2001                                 c = ceiling[part];
2002                         else {
2003                                 /* FIXME:  This is an incomplete leap-year
2004                                  * check that fails in 2100, 2200, 2300,
2005                                  * 2500, 2600, 2700, ...
2006                                  */
2007                                 c = mdays[parts[2]];
2008                                 if (parts[2] == 1)
2009                                         c--;
2010                         }
2011                         if (parts[part] > c) {
2012                                 parts[part] -= c + 1;
2013                                 parts[part - 1]++;
2014                         }
2015                 }
2016         } else {
2017                 parts[4] -= parts[7];
2018                 parts[5] -= parts[8];
2019                 for (part = 7; --part > 0; ) {
2020                         if (part != 3)
2021                                 c = ceiling[part];
2022                         else {
2023                                 /* FIXME:  This is an incomplete leap-year
2024                                  * check that fails in 2100, 2200, 2300,
2025                                  * 2500, 2600, 2700, ...
2026                                  */
2027                                 c = mdays[(parts[2] - 1) % 12];
2028                                 if (parts[2] == 2)
2029                                         c--;
2030                         }
2031                         if (parts[part] < 0) {
2032                                 parts[part] += c + 1;
2033                                 parts[part - 1]--;
2034                         }
2035                 }
2036         }
2037
2038         return LDAP_SUCCESS;
2039 }
2040
2041 static int
2042 utcTimeNormalize(
2043         Syntax *syntax,
2044         struct berval *val,
2045         struct berval **normalized )
2046 {
2047         struct berval *out;
2048         int parts[9], rc;
2049
2050         rc = check_time_syntax(val, 1, parts);
2051         if (rc != LDAP_SUCCESS) {
2052                 return rc;
2053         }
2054
2055         *normalized = NULL;
2056         out = ch_malloc( sizeof(struct berval) );
2057         if( out == NULL )
2058                 return LBER_ERROR_MEMORY;
2059
2060         out->bv_val = ch_malloc( 14 );
2061         if ( out->bv_val == NULL ) {
2062                 ch_free( out );
2063                 return LBER_ERROR_MEMORY;
2064         }
2065
2066         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ldZ",
2067                                 parts[1], parts[2] + 1, parts[3] + 1,
2068                                 parts[4], parts[5], parts[6] );
2069         out->bv_len = 13;
2070         *normalized = out;
2071
2072         return LDAP_SUCCESS;
2073 }
2074
2075 static int
2076 utcTimeValidate(
2077         Syntax *syntax,
2078         struct berval *in )
2079 {
2080         int parts[9];
2081
2082         return check_time_syntax(in, 1, parts);
2083 }
2084
2085 static int
2086 generalizedTimeValidate(
2087         Syntax *syntax,
2088         struct berval *in )
2089 {
2090         int parts[9];
2091
2092         return check_time_syntax(in, 0, parts);
2093 }
2094
2095 static int
2096 generalizedTimeNormalize(
2097         Syntax *syntax,
2098         struct berval *val,
2099         struct berval **normalized )
2100 {
2101         struct berval *out;
2102         int parts[9], rc;
2103
2104         rc = check_time_syntax(val, 0, parts);
2105         if (rc != LDAP_SUCCESS) {
2106                 return rc;
2107         }
2108
2109         *normalized = NULL;
2110         out = ch_malloc( sizeof(struct berval) );
2111         if( out == NULL )
2112                 return LBER_ERROR_MEMORY;
2113
2114         out->bv_val = ch_malloc( 16 );
2115         if ( out->bv_val == NULL ) {
2116                 ch_free( out );
2117                 return LBER_ERROR_MEMORY;
2118         }
2119
2120         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ld%02ldZ",
2121                                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2122                                 parts[4], parts[5], parts[6] );
2123         out->bv_len = 15;
2124         *normalized = out;
2125
2126         return LDAP_SUCCESS;
2127 }
2128
2129 struct syntax_defs_rec {
2130         char *sd_desc;
2131         int sd_flags;
2132         slap_syntax_validate_func *sd_validate;
2133         slap_syntax_transform_func *sd_normalize;
2134         slap_syntax_transform_func *sd_pretty;
2135 #ifdef SLAPD_BINARY_CONVERSION
2136         slap_syntax_transform_func *sd_ber2str;
2137         slap_syntax_transform_func *sd_str2ber;
2138 #endif
2139 };
2140
2141 #define X_HIDE "X-HIDE 'TRUE' "
2142 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2143 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2144
2145 struct syntax_defs_rec syntax_defs[] = {
2146         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
2147                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
2148         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2149                 0, NULL, NULL, NULL},
2150         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2151                 0, NULL, NULL, NULL},
2152         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
2153                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
2154         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_BINARY X_NOT_H_R ")",
2155                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2156         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2157                 0, bitStringValidate, bitStringNormalize, NULL },
2158         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2159                 0, booleanValidate, NULL, NULL},
2160         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2161                 X_BINARY X_NOT_H_R ")",
2162                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2163         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2164                 X_BINARY X_NOT_H_R ")",
2165                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2166         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2167                 X_BINARY X_NOT_H_R ")",
2168                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2169         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2170                 0, NULL, NULL, NULL},
2171         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2172                 0, dnValidate, dnNormalize, dnPretty},
2173         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2174                 0, NULL, NULL, NULL},
2175         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2176                 0, NULL, NULL, NULL},
2177         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2178                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
2179         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2180                 0, NULL, NULL, NULL},
2181         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2182                 0, NULL, NULL, NULL},
2183         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2184                 0, NULL, NULL, NULL},
2185         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2186                 0, NULL, NULL, NULL},
2187         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2188                 0, NULL, NULL, NULL},
2189         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2190                 0, IA5StringValidate, faxNumberNormalize, NULL},
2191         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2192                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
2193         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2194                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
2195         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2196                 0, NULL, NULL, NULL},
2197         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2198                 0, IA5StringValidate, IA5StringNormalize, NULL},
2199         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2200                 0, integerValidate, integerNormalize, integerPretty},
2201         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2202                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
2203         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2204                 0, NULL, NULL, NULL},
2205         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2206                 0, NULL, NULL, NULL},
2207         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2208                 0, NULL, NULL, NULL},
2209         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2210                 0, NULL, NULL, NULL},
2211         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2212                 0, NULL, NULL, NULL},
2213         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2214                 0, NULL, NULL, NULL},
2215         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2216                 0, NULL, NULL, NULL},
2217         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2218                 0, IA5StringValidate, numericStringNormalize, NULL},
2219         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2220                 0, NULL, NULL, NULL},
2221         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2222                 0, oidValidate, NULL, NULL},
2223         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2224                 0, NULL, NULL, NULL},
2225         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2226                 0, blobValidate, NULL, NULL},
2227         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2228                 0, blobValidate, NULL, NULL},
2229         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2230                 0, NULL, NULL, NULL},
2231         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2232                 0, NULL, NULL, NULL},
2233         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2234                 0, printableStringValidate, NULL, NULL},
2235         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2236                 X_BINARY X_NOT_H_R ")",
2237                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2238         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2239                 0, IA5StringValidate, phoneNumberNormalize, NULL},
2240         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2241                 0, NULL, NULL, NULL},
2242         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2243                 0, IA5StringValidate, telexNumberNormalize, NULL},
2244         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2245                 0, utcTimeValidate, utcTimeNormalize, NULL},
2246         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2247                 0, NULL, NULL, NULL},
2248         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2249                 0, NULL, NULL, NULL},
2250         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2251                 0, NULL, NULL, NULL},
2252         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2253                 0, NULL, NULL, NULL},
2254         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2255                 0, NULL, NULL, NULL},
2256
2257         /* OpenLDAP Experimental Syntaxes */
2258         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2259                 0, IA5StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */, NULL, NULL},
2260         {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2261                 0, NULL, NULL, NULL},
2262         {"( 1.3.6.1.4.1.4203.666.2.3 DESC 'OpenLDAP void' " X_HIDE ")" ,
2263                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
2264 #if 0 /* not needed */
2265         {"( 1.3.6.1.4.1.4203.666.2.4 DESC 'OpenLDAP DN' " X_HIDE ")" ,
2266                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
2267 #endif
2268
2269         {NULL, 0, NULL, NULL, NULL}
2270 };
2271
2272 struct mrule_defs_rec {
2273         char *                                          mrd_desc;
2274         unsigned                                        mrd_usage;
2275         slap_mr_convert_func *          mrd_convert;
2276         slap_mr_normalize_func *        mrd_normalize;
2277         slap_mr_match_func *            mrd_match;
2278         slap_mr_indexer_func *          mrd_indexer;
2279         slap_mr_filter_func *           mrd_filter;
2280
2281         char *                                          mrd_associated;
2282 };
2283
2284 /*
2285  * Other matching rules in X.520 that we do not use (yet):
2286  *
2287  * 2.5.13.9             numericStringOrderingMatch
2288  * 2.5.13.13    booleanMatch
2289  * 2.5.13.15    integerOrderingMatch
2290  * 2.5.13.18    octetStringOrderingMatch
2291  * 2.5.13.19    octetStringSubstringsMatch
2292  * 2.5.13.25    uTCTimeMatch
2293  * 2.5.13.26    uTCTimeOrderingMatch
2294  * 2.5.13.31    directoryStringFirstComponentMatch
2295  * 2.5.13.32    wordMatch
2296  * 2.5.13.33    keywordMatch
2297  * 2.5.13.34    certificateExactMatch
2298  * 2.5.13.35    certificateMatch
2299  * 2.5.13.36    certificatePairExactMatch
2300  * 2.5.13.37    certificatePairMatch
2301  * 2.5.13.38    certificateListExactMatch
2302  * 2.5.13.39    certificateListMatch
2303  * 2.5.13.40    algorithmIdentifierMatch
2304  * 2.5.13.41    storedPrefixMatch
2305  * 2.5.13.42    attributeCertificateMatch
2306  * 2.5.13.43    readerAndKeyIDMatch
2307  * 2.5.13.44    attributeIntegrityMatch
2308  */
2309
2310 struct mrule_defs_rec mrule_defs[] = {
2311         /*
2312          * EQUALITY matching rules must be listed after associated APPROX
2313          * matching rules.  So, we list all APPROX matching rules first.
2314          */
2315         {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2316                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2317                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
2318                 NULL, NULL,
2319                 directoryStringApproxMatch, NULL, NULL,
2320                 NULL},
2321
2322         {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2323                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2324                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
2325                 NULL, NULL,
2326                 IA5StringApproxMatch, NULL, NULL,
2327                 NULL},
2328
2329         /*
2330          * Other matching rules
2331          */
2332         
2333         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2334                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2335                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2336                 NULL, NULL,
2337                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
2338                 NULL},
2339
2340         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2341                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2342                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2343                 NULL, NULL,
2344                 dnMatch, dnIndexer, dnFilter,
2345                 NULL},
2346
2347         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2348                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2349                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2350                 NULL, NULL,
2351                 caseIgnoreMatch, caseIgnoreIndexer, caseIgnoreFilter,
2352                 directoryStringApproxMatchOID },
2353
2354         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2355                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2356                 SLAP_MR_ORDERING,
2357                 NULL, NULL,
2358                 caseIgnoreOrderingMatch, NULL, NULL,
2359                 NULL},
2360
2361         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2362                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2363                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2364                 NULL, NULL,
2365                 caseIgnoreSubstringsMatch,
2366                 caseIgnoreSubstringsIndexer,
2367                 caseIgnoreSubstringsFilter,
2368                 NULL},
2369
2370         {"( 2.5.13.5 NAME 'caseExactMatch' "
2371                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2372                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2373                 NULL, NULL,
2374                 caseExactMatch, caseExactIndexer, caseExactFilter,
2375                 directoryStringApproxMatchOID },
2376
2377         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2378                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2379                 SLAP_MR_ORDERING,
2380                 NULL, NULL,
2381                 caseExactOrderingMatch, NULL, NULL,
2382                 NULL},
2383
2384         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2385                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2386                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2387                 NULL, NULL,
2388                 caseExactSubstringsMatch,
2389                 caseExactSubstringsIndexer,
2390                 caseExactSubstringsFilter,
2391                 NULL},
2392
2393         {"( 2.5.13.8 NAME 'numericStringMatch' "
2394                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2395                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2396                 NULL, NULL,
2397                 caseIgnoreIA5Match, NULL, NULL,
2398                 NULL},
2399
2400         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2401                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2402                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2403                 NULL, NULL,
2404                 caseIgnoreIA5SubstringsMatch,
2405                 caseIgnoreIA5SubstringsIndexer,
2406                 caseIgnoreIA5SubstringsFilter,
2407                 NULL},
2408
2409         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2410                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2411                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2412                 NULL, NULL,
2413                 caseIgnoreListMatch, NULL, NULL,
2414                 NULL},
2415
2416         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2417                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2418                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2419                 NULL, NULL,
2420                 caseIgnoreListSubstringsMatch, NULL, NULL,
2421                 NULL},
2422
2423         {"( 2.5.13.13 NAME 'booleanMatch' "
2424                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2425                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2426                 NULL, NULL,
2427                 booleanMatch, NULL, NULL,
2428                 NULL},
2429
2430         {"( 2.5.13.14 NAME 'integerMatch' "
2431                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2432                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2433                 NULL, NULL,
2434                 integerMatch, NULL, NULL,
2435                 NULL},
2436
2437         {"( 2.5.13.16 NAME 'bitStringMatch' "
2438                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2439                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2440                 NULL, NULL,
2441                 bitStringMatch, NULL, NULL,
2442                 NULL},
2443
2444         {"( 2.5.13.17 NAME 'octetStringMatch' "
2445                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2446                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2447                 NULL, NULL,
2448                 octetStringMatch, octetStringIndexer, octetStringFilter,
2449                 NULL},
2450
2451         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2452                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2453                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2454                 NULL, NULL,
2455                 telephoneNumberMatch, NULL, NULL,
2456                 NULL},
2457
2458         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2459                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2460                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2461                 NULL, NULL,
2462                 telephoneNumberSubstringsMatch, NULL, NULL,
2463                 NULL},
2464
2465         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2466                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2467                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2468                 NULL, NULL,
2469                 presentationAddressMatch, NULL, NULL,
2470                 NULL},
2471
2472         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2473                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2474                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2475                 NULL, NULL,
2476                 uniqueMemberMatch, NULL, NULL,
2477                 NULL},
2478
2479         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2480                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2481                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2482                 NULL, NULL,
2483                 protocolInformationMatch, NULL, NULL,
2484                 NULL},
2485
2486         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2487                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2488                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2489                 NULL, NULL,
2490                 generalizedTimeMatch, NULL, NULL,
2491                 NULL},
2492
2493         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2494                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2495                 SLAP_MR_ORDERING,
2496                 NULL, NULL,
2497                 generalizedTimeOrderingMatch, NULL, NULL,
2498                 NULL},
2499
2500         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
2501                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2502                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2503                 NULL, NULL,
2504                 integerFirstComponentMatch, NULL, NULL,
2505                 NULL},
2506
2507         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
2508                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2509                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2510                 NULL, NULL,
2511                 objectIdentifierFirstComponentMatch, NULL, NULL,
2512                 NULL},
2513
2514         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
2515                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2516                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2517                 NULL, NULL,
2518                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
2519                 IA5StringApproxMatchOID },
2520
2521         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
2522                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2523                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2524                 NULL, NULL,
2525                 caseIgnoreIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
2526                 IA5StringApproxMatchOID },
2527
2528         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
2529                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2530                 SLAP_MR_SUBSTR,
2531                 NULL, NULL,
2532                 caseIgnoreIA5SubstringsMatch,
2533                 caseIgnoreIA5SubstringsIndexer,
2534                 caseIgnoreIA5SubstringsFilter,
2535                 NULL},
2536
2537         {"( 1.3.6.1.4.1.4203.666.4.3 NAME 'caseExactIA5SubstringsMatch' "
2538                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2539                 SLAP_MR_SUBSTR,
2540                 NULL, NULL,
2541                 caseExactIA5SubstringsMatch,
2542                 caseExactIA5SubstringsIndexer,
2543                 caseExactIA5SubstringsFilter,
2544                 NULL},
2545
2546         {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
2547                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2548                 SLAP_MR_EQUALITY,
2549                 NULL, NULL,
2550                 authPasswordMatch, NULL, NULL,
2551                 NULL},
2552
2553         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
2554                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
2555                 SLAP_MR_EQUALITY,
2556                 NULL, NULL,
2557                 OpenLDAPaciMatch, NULL, NULL,
2558                 NULL},
2559
2560         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
2561 };
2562
2563 int
2564 schema_init( void )
2565 {
2566         int             res;
2567         int             i;
2568
2569         /* we should only be called once (from main) */
2570         assert( schema_init_done == 0 );
2571
2572         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
2573                 res = register_syntax( syntax_defs[i].sd_desc,
2574                     syntax_defs[i].sd_flags,
2575                     syntax_defs[i].sd_validate,
2576                     syntax_defs[i].sd_normalize,
2577                         syntax_defs[i].sd_pretty
2578 #ifdef SLAPD_BINARY_CONVERSION
2579                         ,
2580                     syntax_defs[i].sd_ber2str,
2581                         syntax_defs[i].sd_str2ber
2582 #endif
2583                 );
2584
2585                 if ( res ) {
2586                         fprintf( stderr, "schema_init: Error registering syntax %s\n",
2587                                  syntax_defs[i].sd_desc );
2588                         return LDAP_OTHER;
2589                 }
2590         }
2591
2592         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
2593                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
2594                         fprintf( stderr,
2595                                 "schema_init: Ingoring unusable matching rule %s\n",
2596                                  mrule_defs[i].mrd_desc );
2597                         continue;
2598                 }
2599
2600                 res = register_matching_rule(
2601                         mrule_defs[i].mrd_desc,
2602                         mrule_defs[i].mrd_usage,
2603                         mrule_defs[i].mrd_convert,
2604                         mrule_defs[i].mrd_normalize,
2605                     mrule_defs[i].mrd_match,
2606                         mrule_defs[i].mrd_indexer,
2607                         mrule_defs[i].mrd_filter,
2608                         mrule_defs[i].mrd_associated );
2609
2610                 if ( res ) {
2611                         fprintf( stderr,
2612                                 "schema_init: Error registering matching rule %s\n",
2613                                  mrule_defs[i].mrd_desc );
2614                         return LDAP_OTHER;
2615                 }
2616         }
2617         schema_init_done = 1;
2618         return LDAP_SUCCESS;
2619 }