]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
Import changes from devel
[openldap] / servers / slapd / schema_init.c
1 /* schema_init.c - init builtin schema */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/ctype.h>
13 #include <ac/string.h>
14 #include <ac/socket.h>
15
16 #include "slap.h"
17 #include "ldap_pvt.h"
18 #include "lutil_md5.h"
19
20 /* recycled validatation routines */
21 #define berValidate                                             blobValidate
22 #define nameUIDValidate                                 dnValidate
23
24 /* unimplemented validators */
25 #define bitStringValidate                               NULL
26
27 /* recycled normalization routines */
28 #define faxNumberNormalize                              numericStringNormalize
29 #define phoneNumberNormalize                    numericStringNormalize
30 #define telexNumberNormalize                    numericStringNormalize
31 #define integerNormalize                                numericStringNormalize
32 #define nameUIDNormalize                                dnNormalize
33
34 /* unimplemented normalizers */
35 #define bitStringNormalize                              NULL
36
37 /* unimplemented pretters */
38 #define dnPretty                                                NULL
39 #define integerPretty                                   NULL
40
41 /* recycled pretters */
42 #define nameUIDPretty                                   dnPretty
43
44 /* recycled matching routines */
45 #define caseIgnoreMatch                                 caseIgnoreIA5Match
46 #define caseIgnoreOrderingMatch                 caseIgnoreMatch
47 #define caseIgnoreSubstringsMatch               caseIgnoreIA5SubstringsMatch
48
49 #define caseExactMatch                                  caseExactIA5Match
50 #define caseExactOrderingMatch                  caseExactMatch
51 #define caseExactSubstringsMatch                caseExactIA5SubstringsMatch
52
53 #define numericStringMatch                              caseIgnoreMatch
54 #define objectIdentifierMatch                   numericStringMatch
55 #define integerMatch                                    numericStringMatch
56 #define telephoneNumberMatch                    numericStringMatch
57 #define telephoneNumberSubstringsMatch  caseIgnoreIA5SubstringsMatch
58 #define generalizedTimeMatch                    numericStringMatch
59 #define generalizedTimeOrderingMatch    numericStringMatch
60 #define uniqueMemberMatch                               dnMatch
61
62 /* unimplemented matching routines */
63 #define caseIgnoreListMatch                             NULL
64 #define caseIgnoreListSubstringsMatch   NULL
65 #define bitStringMatch                                  NULL
66 #define presentationAddressMatch                NULL
67 #define protocolInformationMatch                NULL
68 #define integerFirstComponentMatch              NULL
69
70 #define OpenLDAPaciMatch                                NULL
71
72 /* recycled indexing/filtering routines */
73 #define caseIgnoreIndexer                               caseIgnoreIA5Indexer
74 #define caseIgnoreFilter                                caseIgnoreIA5Filter
75 #define caseExactIndexer                                caseExactIA5Indexer
76 #define caseExactFilter                                 caseExactIA5Filter
77 #define dnIndexer                                               caseIgnoreIndexer
78 #define dnFilter                                                caseIgnoreFilter
79
80 #define caseIgnoreSubstringsIndexer             caseIgnoreIA5SubstringsIndexer
81 #define caseIgnoreSubstringsFilter              caseIgnoreIA5SubstringsFilter
82 #define caseExactSubstringsIndexer              caseExactIA5SubstringsIndexer
83 #define caseExactSubstringsFilter               caseExactIA5SubstringsFilter
84
85
86 static int
87 octetStringMatch(
88         int *matchp,
89         slap_mask_t flags,
90         Syntax *syntax,
91         MatchingRule *mr,
92         struct berval *value,
93         void *assertedValue )
94 {
95         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
96
97         if( match == 0 ) {
98                 match = memcmp( value->bv_val,
99                         ((struct berval *) assertedValue)->bv_val,
100                         value->bv_len );
101         }
102
103         *matchp = match;
104         return LDAP_SUCCESS;
105 }
106
107 /* Index generation function */
108 int octetStringIndexer(
109         slap_mask_t use,
110         slap_mask_t flags,
111         Syntax *syntax,
112         MatchingRule *mr,
113         struct berval *prefix,
114         struct berval **values,
115         struct berval ***keysp )
116 {
117         int i;
118         size_t slen, mlen;
119         struct berval **keys;
120         lutil_MD5_CTX   MD5context;
121         unsigned char   MD5digest[16];
122         struct berval digest;
123         digest.bv_val = MD5digest;
124         digest.bv_len = sizeof(MD5digest);
125
126         for( i=0; values[i] != NULL; i++ ) {
127                 /* just count them */
128         }
129
130         assert( i > 0 );
131
132         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
133
134         slen = strlen( syntax->ssyn_oid );
135         mlen = strlen( mr->smr_oid );
136
137         for( i=0; values[i] != NULL; i++ ) {
138                 lutil_MD5Init( &MD5context );
139                 if( prefix != NULL && prefix->bv_len > 0 ) {
140                         lutil_MD5Update( &MD5context,
141                                 prefix->bv_val, prefix->bv_len );
142                 }
143                 lutil_MD5Update( &MD5context,
144                         syntax->ssyn_oid, slen );
145                 lutil_MD5Update( &MD5context,
146                         mr->smr_oid, mlen );
147                 lutil_MD5Update( &MD5context,
148                         values[i]->bv_val, values[i]->bv_len );
149                 lutil_MD5Final( MD5digest, &MD5context );
150
151                 keys[i] = ber_bvdup( &digest );
152         }
153
154         keys[i] = NULL;
155
156         *keysp = keys;
157
158         return LDAP_SUCCESS;
159 }
160
161 /* Index generation function */
162 int octetStringFilter(
163         slap_mask_t use,
164         slap_mask_t 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         slap_mask_t 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         slap_mask_t 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         slap_mask_t 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         slap_mask_t 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         slap_mask_t use,
777         slap_mask_t flags,
778         Syntax *syntax,
779         MatchingRule *mr,
780         struct berval *prefix,
781         struct berval **values,
782         struct berval ***keysp )
783 {
784         int i;
785         size_t slen, mlen;
786         struct berval **keys;
787         lutil_MD5_CTX   MD5context;
788         unsigned char   MD5digest[16];
789         struct berval digest;
790         digest.bv_val = MD5digest;
791         digest.bv_len = sizeof(MD5digest);
792
793         for( i=0; values[i] != NULL; i++ ) {
794                 /* just count them */
795         }
796
797         assert( i > 0 );
798
799         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
800
801         slen = strlen( syntax->ssyn_oid );
802         mlen = strlen( mr->smr_oid );
803
804         for( i=0; values[i] != NULL; i++ ) {
805                 struct berval *value = values[i];
806
807                 lutil_MD5Init( &MD5context );
808                 if( prefix != NULL && prefix->bv_len > 0 ) {
809                         lutil_MD5Update( &MD5context,
810                                 prefix->bv_val, prefix->bv_len );
811                 }
812                 lutil_MD5Update( &MD5context,
813                         syntax->ssyn_oid, slen );
814                 lutil_MD5Update( &MD5context,
815                         mr->smr_oid, mlen );
816                 lutil_MD5Update( &MD5context,
817                         value->bv_val, value->bv_len );
818                 lutil_MD5Final( MD5digest, &MD5context );
819
820                 keys[i] = ber_bvdup( &digest );
821         }
822
823         keys[i] = NULL;
824         *keysp = keys;
825         return LDAP_SUCCESS;
826 }
827
828 /* Index generation function */
829 int caseExactIA5Filter(
830         slap_mask_t use,
831         slap_mask_t flags,
832         Syntax *syntax,
833         MatchingRule *mr,
834         struct berval *prefix,
835         void * assertValue,
836         struct berval ***keysp )
837 {
838         size_t slen, mlen;
839         struct berval **keys;
840         lutil_MD5_CTX   MD5context;
841         unsigned char   MD5digest[LUTIL_MD5_BYTES];
842         struct berval *value;
843         struct berval digest;
844         digest.bv_val = MD5digest;
845         digest.bv_len = sizeof(MD5digest);
846
847         slen = strlen( syntax->ssyn_oid );
848         mlen = strlen( mr->smr_oid );
849
850         value = (struct berval *) assertValue;
851
852         keys = ch_malloc( sizeof( struct berval * ) * 2 );
853
854         lutil_MD5Init( &MD5context );
855         if( prefix != NULL && prefix->bv_len > 0 ) {
856                 lutil_MD5Update( &MD5context,
857                         prefix->bv_val, prefix->bv_len );
858         }
859         lutil_MD5Update( &MD5context,
860                 syntax->ssyn_oid, slen );
861         lutil_MD5Update( &MD5context,
862                 mr->smr_oid, mlen );
863         lutil_MD5Update( &MD5context,
864                 value->bv_val, value->bv_len );
865         lutil_MD5Final( MD5digest, &MD5context );
866
867         keys[0] = ber_bvdup( &digest );
868         keys[1] = NULL;
869
870         *keysp = keys;
871         return LDAP_SUCCESS;
872 }
873
874 /* Substrings Index generation function */
875 int caseExactIA5SubstringsIndexer(
876         slap_mask_t use,
877         slap_mask_t flags,
878         Syntax *syntax,
879         MatchingRule *mr,
880         struct berval *prefix,
881         struct berval **values,
882         struct berval ***keysp )
883 {
884         ber_len_t i, nkeys;
885         size_t slen, mlen;
886         struct berval **keys;
887         lutil_MD5_CTX   MD5context;
888         unsigned char   MD5digest[16];
889         struct berval digest;
890         digest.bv_val = MD5digest;
891         digest.bv_len = sizeof(MD5digest);
892
893         nkeys=0;
894         for( i=0; values[i] != NULL; i++ ) {
895                 /* count number of indices to generate */
896                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
897                         continue;
898                 }
899
900                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
901                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
902                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
903                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
904                         } else {
905                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
906                         }
907                 }
908
909                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
910                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
911                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
912                         }
913                 }
914
915                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
916                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
917                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
918                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
919                         } else {
920                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
921                         }
922                 }
923         }
924         assert( i > 0 );
925
926         if( nkeys == 0 ) {
927                 /* no keys to generate */
928                 *keysp = NULL;
929                 return LDAP_SUCCESS;
930         }
931
932         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
933
934         slen = strlen( syntax->ssyn_oid );
935         mlen = strlen( mr->smr_oid );
936
937         nkeys=0;
938         for( i=0; values[i] != NULL; i++ ) {
939                 ber_len_t j,max;
940                 struct berval *value;
941
942                 value = values[i];
943                 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
944
945                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
946                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
947                 {
948                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
949                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
950
951                         for( j=0; j<max; j++ ) {
952                                 lutil_MD5Init( &MD5context );
953                                 if( prefix != NULL && prefix->bv_len > 0 ) {
954                                         lutil_MD5Update( &MD5context,
955                                                 prefix->bv_val, prefix->bv_len );
956                                 }
957
958                                 lutil_MD5Update( &MD5context,
959                                         &pre, sizeof( pre ) );
960                                 lutil_MD5Update( &MD5context,
961                                         syntax->ssyn_oid, slen );
962                                 lutil_MD5Update( &MD5context,
963                                         mr->smr_oid, mlen );
964                                 lutil_MD5Update( &MD5context,
965                                         &value->bv_val[j],
966                                         SLAP_INDEX_SUBSTR_MAXLEN );
967                                 lutil_MD5Final( MD5digest, &MD5context );
968
969                                 keys[nkeys++] = ber_bvdup( &digest );
970                         }
971                 }
972
973                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
974                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
975
976                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
977                         char pre;
978
979                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
980                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
981                                 lutil_MD5Init( &MD5context );
982                                 if( prefix != NULL && prefix->bv_len > 0 ) {
983                                         lutil_MD5Update( &MD5context,
984                                                 prefix->bv_val, prefix->bv_len );
985                                 }
986                                 lutil_MD5Update( &MD5context,
987                                         &pre, sizeof( pre ) );
988                                 lutil_MD5Update( &MD5context,
989                                         syntax->ssyn_oid, slen );
990                                 lutil_MD5Update( &MD5context,
991                                         mr->smr_oid, mlen );
992                                 lutil_MD5Update( &MD5context,
993                                         value->bv_val, j );
994                                 lutil_MD5Final( MD5digest, &MD5context );
995
996                                 keys[nkeys++] = ber_bvdup( &digest );
997                         }
998
999                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1000                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1001                                 lutil_MD5Init( &MD5context );
1002                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1003                                         lutil_MD5Update( &MD5context,
1004                                                 prefix->bv_val, prefix->bv_len );
1005                                 }
1006                                 lutil_MD5Update( &MD5context,
1007                                         &pre, sizeof( pre ) );
1008                                 lutil_MD5Update( &MD5context,
1009                                         syntax->ssyn_oid, slen );
1010                                 lutil_MD5Update( &MD5context,
1011                                         mr->smr_oid, mlen );
1012                                 lutil_MD5Update( &MD5context,
1013                                         &value->bv_val[value->bv_len-j], j );
1014                                 lutil_MD5Final( MD5digest, &MD5context );
1015
1016                                 keys[nkeys++] = ber_bvdup( &digest );
1017                         }
1018
1019                 }
1020         }
1021
1022         if( nkeys > 0 ) {
1023                 keys[nkeys] = NULL;
1024                 *keysp = keys;
1025         } else {
1026                 ch_free( keys );
1027                 *keysp = NULL;
1028         }
1029
1030         return LDAP_SUCCESS;
1031 }
1032
1033 int caseExactIA5SubstringsFilter(
1034         slap_mask_t use,
1035         slap_mask_t flags,
1036         Syntax *syntax,
1037         MatchingRule *mr,
1038         struct berval *prefix,
1039         void * assertValue,
1040         struct berval ***keysp )
1041 {
1042         SubstringsAssertion *sa = assertValue;
1043         char pre;
1044         ber_len_t nkeys = 0;
1045         size_t slen, mlen, klen;
1046         struct berval **keys;
1047         lutil_MD5_CTX   MD5context;
1048         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1049         struct berval *value;
1050         struct berval digest;
1051
1052         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1053                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1054         {
1055                 nkeys++;
1056         }
1057
1058         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1059                 ber_len_t i;
1060                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1061                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1062                                 /* don't bother accounting for stepping */
1063                                 nkeys += sa->sa_any[i]->bv_len -
1064                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1065                         }
1066                 }
1067         }
1068
1069         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1070                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1071         {
1072                 nkeys++;
1073         }
1074
1075         if( nkeys == 0 ) {
1076                 *keysp = NULL;
1077                 return LDAP_SUCCESS;
1078         }
1079
1080         digest.bv_val = MD5digest;
1081         digest.bv_len = sizeof(MD5digest);
1082
1083         slen = strlen( syntax->ssyn_oid );
1084         mlen = strlen( mr->smr_oid );
1085
1086         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1087         nkeys = 0;
1088
1089         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1090                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1091         {
1092                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1093                 value = sa->sa_initial;
1094
1095                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1096                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1097
1098                 lutil_MD5Init( &MD5context );
1099                 if( prefix != NULL && prefix->bv_len > 0 ) {
1100                         lutil_MD5Update( &MD5context,
1101                                 prefix->bv_val, prefix->bv_len );
1102                 }
1103                 lutil_MD5Update( &MD5context,
1104                         &pre, sizeof( pre ) );
1105                 lutil_MD5Update( &MD5context,
1106                         syntax->ssyn_oid, slen );
1107                 lutil_MD5Update( &MD5context,
1108                         mr->smr_oid, mlen );
1109                 lutil_MD5Update( &MD5context,
1110                         value->bv_val, klen );
1111                 lutil_MD5Final( MD5digest, &MD5context );
1112
1113                 keys[nkeys++] = ber_bvdup( &digest );
1114         }
1115
1116         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1117                 ber_len_t i, j;
1118                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1119                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1120
1121                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1122                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1123                                 continue;
1124                         }
1125
1126                         value = sa->sa_any[i];
1127
1128                         for(j=0;
1129                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1130                                 j += SLAP_INDEX_SUBSTR_STEP )
1131                         {
1132                                 lutil_MD5Init( &MD5context );
1133                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1134                                         lutil_MD5Update( &MD5context,
1135                                                 prefix->bv_val, prefix->bv_len );
1136                                 }
1137                                 lutil_MD5Update( &MD5context,
1138                                         &pre, sizeof( pre ) );
1139                                 lutil_MD5Update( &MD5context,
1140                                         syntax->ssyn_oid, slen );
1141                                 lutil_MD5Update( &MD5context,
1142                                         mr->smr_oid, mlen );
1143                                 lutil_MD5Update( &MD5context,
1144                                         &value->bv_val[j], klen ); 
1145                                 lutil_MD5Final( MD5digest, &MD5context );
1146
1147                                 keys[nkeys++] = ber_bvdup( &digest );
1148                         }
1149                 }
1150         }
1151
1152         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1153                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1154         {
1155                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1156                 value = sa->sa_final;
1157
1158                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1159                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1160
1161                 lutil_MD5Init( &MD5context );
1162                 if( prefix != NULL && prefix->bv_len > 0 ) {
1163                         lutil_MD5Update( &MD5context,
1164                                 prefix->bv_val, prefix->bv_len );
1165                 }
1166                 lutil_MD5Update( &MD5context,
1167                         &pre, sizeof( pre ) );
1168                 lutil_MD5Update( &MD5context,
1169                         syntax->ssyn_oid, slen );
1170                 lutil_MD5Update( &MD5context,
1171                         mr->smr_oid, mlen );
1172                 lutil_MD5Update( &MD5context,
1173                         &value->bv_val[value->bv_len-klen], klen );
1174                 lutil_MD5Final( MD5digest, &MD5context );
1175
1176                 keys[nkeys++] = ber_bvdup( &digest );
1177         }
1178
1179         if( nkeys > 0 ) {
1180                 keys[nkeys] = NULL;
1181                 *keysp = keys;
1182         } else {
1183                 ch_free( keys );
1184                 *keysp = NULL;
1185         }
1186
1187         return LDAP_SUCCESS;
1188 }
1189         
1190 static int
1191 caseIgnoreIA5Match(
1192         int *matchp,
1193         slap_mask_t flags,
1194         Syntax *syntax,
1195         MatchingRule *mr,
1196         struct berval *value,
1197         void *assertedValue )
1198 {
1199         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
1200
1201         if( match == 0 ) {
1202                 match = strncasecmp( value->bv_val,
1203                         ((struct berval *) assertedValue)->bv_val,
1204                         value->bv_len );
1205         }
1206
1207         *matchp = match;
1208         return LDAP_SUCCESS;
1209 }
1210
1211 static char *strcasechr( const char *str, int c )
1212 {
1213         char *lower = strchr( str, TOLOWER(c) );
1214         char *upper = strchr( str, TOUPPER(c) );
1215
1216         if( lower && upper ) {
1217                 return lower < upper ? lower : upper;
1218         } else if ( lower ) {
1219                 return lower;
1220         } else {
1221                 return upper;
1222         }
1223 }
1224
1225 static int
1226 caseIgnoreIA5SubstringsMatch(
1227         int *matchp,
1228         slap_mask_t flags,
1229         Syntax *syntax,
1230         MatchingRule *mr,
1231         struct berval *value,
1232         void *assertedValue )
1233 {
1234         int match = 0;
1235         SubstringsAssertion *sub = assertedValue;
1236         struct berval left = *value;
1237         int i;
1238         ber_len_t inlen=0;
1239
1240         /* Add up asserted input length */
1241         if( sub->sa_initial ) {
1242                 inlen += sub->sa_initial->bv_len;
1243         }
1244         if( sub->sa_any ) {
1245                 for(i=0; sub->sa_any[i] != NULL; i++) {
1246                         inlen += sub->sa_any[i]->bv_len;
1247                 }
1248         }
1249         if( sub->sa_final ) {
1250                 inlen += sub->sa_final->bv_len;
1251         }
1252
1253         if( sub->sa_initial ) {
1254                 if( inlen > left.bv_len ) {
1255                         match = 1;
1256                         goto done;
1257                 }
1258
1259                 match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
1260                         sub->sa_initial->bv_len );
1261
1262                 if( match != 0 ) {
1263                         goto done;
1264                 }
1265
1266                 left.bv_val += sub->sa_initial->bv_len;
1267                 left.bv_len -= sub->sa_initial->bv_len;
1268                 inlen -= sub->sa_initial->bv_len;
1269         }
1270
1271         if( sub->sa_final ) {
1272                 if( inlen > left.bv_len ) {
1273                         match = 1;
1274                         goto done;
1275                 }
1276
1277                 match = strncasecmp( sub->sa_final->bv_val,
1278                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1279                         sub->sa_final->bv_len );
1280
1281                 if( match != 0 ) {
1282                         goto done;
1283                 }
1284
1285                 left.bv_len -= sub->sa_final->bv_len;
1286                 inlen -= sub->sa_final->bv_len;
1287         }
1288
1289         if( sub->sa_any ) {
1290                 for(i=0; sub->sa_any[i]; i++) {
1291                         ber_len_t idx;
1292                         char *p;
1293
1294 retry:
1295                         if( inlen > left.bv_len ) {
1296                                 /* not enough length */
1297                                 match = 1;
1298                                 goto done;
1299                         }
1300
1301                         if( sub->sa_any[i]->bv_len == 0 ) {
1302                                 continue;
1303                         }
1304
1305                         p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );
1306
1307                         if( p == NULL ) {
1308                                 match = 1;
1309                                 goto done;
1310                         }
1311
1312                         idx = p - left.bv_val;
1313                         assert( idx < left.bv_len );
1314
1315                         if( idx >= left.bv_len ) {
1316                                 /* this shouldn't happen */
1317                                 return LDAP_OTHER;
1318                         }
1319
1320                         left.bv_val = p;
1321                         left.bv_len -= idx;
1322
1323                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
1324                                 /* not enough left */
1325                                 match = 1;
1326                                 goto done;
1327                         }
1328
1329                         match = strncasecmp( left.bv_val,
1330                                 sub->sa_any[i]->bv_val,
1331                                 sub->sa_any[i]->bv_len );
1332
1333                         if( match != 0 ) {
1334                                 left.bv_val++;
1335                                 left.bv_len--;
1336
1337                                 goto retry;
1338                         }
1339
1340                         left.bv_val += sub->sa_any[i]->bv_len;
1341                         left.bv_len -= sub->sa_any[i]->bv_len;
1342                         inlen -= sub->sa_any[i]->bv_len;
1343                 }
1344         }
1345
1346 done:
1347         *matchp = match;
1348         return LDAP_SUCCESS;
1349 }
1350
1351 /* Index generation function */
1352 int caseIgnoreIA5Indexer(
1353         slap_mask_t use,
1354         slap_mask_t flags,
1355         Syntax *syntax,
1356         MatchingRule *mr,
1357         struct berval *prefix,
1358         struct berval **values,
1359         struct berval ***keysp )
1360 {
1361         int i;
1362         size_t slen, mlen;
1363         struct berval **keys;
1364         lutil_MD5_CTX   MD5context;
1365         unsigned char   MD5digest[16];
1366         struct berval digest;
1367         digest.bv_val = MD5digest;
1368         digest.bv_len = sizeof(MD5digest);
1369
1370         for( i=0; values[i] != NULL; i++ ) {
1371                 /* just count them */
1372         }
1373
1374         assert( i > 0 );
1375
1376         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
1377
1378         slen = strlen( syntax->ssyn_oid );
1379         mlen = strlen( mr->smr_oid );
1380
1381         for( i=0; values[i] != NULL; i++ ) {
1382                 struct berval *value = ber_bvdup( values[i] );
1383                 ldap_pvt_str2upper( value->bv_val );
1384
1385                 lutil_MD5Init( &MD5context );
1386                 if( prefix != NULL && prefix->bv_len > 0 ) {
1387                         lutil_MD5Update( &MD5context,
1388                                 prefix->bv_val, prefix->bv_len );
1389                 }
1390                 lutil_MD5Update( &MD5context,
1391                         syntax->ssyn_oid, slen );
1392                 lutil_MD5Update( &MD5context,
1393                         mr->smr_oid, mlen );
1394                 lutil_MD5Update( &MD5context,
1395                         value->bv_val, value->bv_len );
1396                 lutil_MD5Final( MD5digest, &MD5context );
1397
1398                 ber_bvfree( value );
1399
1400                 keys[i] = ber_bvdup( &digest );
1401         }
1402
1403         keys[i] = NULL;
1404         *keysp = keys;
1405         return LDAP_SUCCESS;
1406 }
1407
1408 /* Index generation function */
1409 int caseIgnoreIA5Filter(
1410         slap_mask_t use,
1411         slap_mask_t flags,
1412         Syntax *syntax,
1413         MatchingRule *mr,
1414         struct berval *prefix,
1415         void * assertValue,
1416         struct berval ***keysp )
1417 {
1418         size_t slen, mlen;
1419         struct berval **keys;
1420         lutil_MD5_CTX   MD5context;
1421         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1422         struct berval *value;
1423         struct berval digest;
1424         digest.bv_val = MD5digest;
1425         digest.bv_len = sizeof(MD5digest);
1426
1427         slen = strlen( syntax->ssyn_oid );
1428         mlen = strlen( mr->smr_oid );
1429
1430         value = ber_bvdup( (struct berval *) assertValue );
1431         ldap_pvt_str2upper( value->bv_val );
1432
1433         keys = ch_malloc( sizeof( struct berval * ) * 2 );
1434
1435         lutil_MD5Init( &MD5context );
1436         if( prefix != NULL && prefix->bv_len > 0 ) {
1437                 lutil_MD5Update( &MD5context,
1438                         prefix->bv_val, prefix->bv_len );
1439         }
1440         lutil_MD5Update( &MD5context,
1441                 syntax->ssyn_oid, slen );
1442         lutil_MD5Update( &MD5context,
1443                 mr->smr_oid, mlen );
1444         lutil_MD5Update( &MD5context,
1445                 value->bv_val, value->bv_len );
1446         lutil_MD5Final( MD5digest, &MD5context );
1447
1448         keys[0] = ber_bvdup( &digest );
1449         keys[1] = NULL;
1450
1451         ber_bvfree( value );
1452
1453         *keysp = keys;
1454
1455         return LDAP_SUCCESS;
1456 }
1457
1458 /* Substrings Index generation function */
1459 int caseIgnoreIA5SubstringsIndexer(
1460         slap_mask_t use,
1461         slap_mask_t flags,
1462         Syntax *syntax,
1463         MatchingRule *mr,
1464         struct berval *prefix,
1465         struct berval **values,
1466         struct berval ***keysp )
1467 {
1468         ber_len_t i, nkeys;
1469         size_t slen, mlen;
1470         struct berval **keys;
1471         lutil_MD5_CTX   MD5context;
1472         unsigned char   MD5digest[16];
1473         struct berval digest;
1474         digest.bv_val = MD5digest;
1475         digest.bv_len = sizeof(MD5digest);
1476
1477         nkeys=0;
1478         for( i=0; values[i] != NULL; i++ ) {
1479                 /* count number of indices to generate */
1480                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1481                         continue;
1482                 }
1483
1484                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1485                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1486                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1487                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1488                         } else {
1489                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1490                         }
1491                 }
1492
1493                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1494                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1495                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1496                         }
1497                 }
1498
1499                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1500                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1501                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1502                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1503                         } else {
1504                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1505                         }
1506                 }
1507         }
1508         assert( i > 0 );
1509
1510         if( nkeys == 0 ) {
1511                 /* no keys to generate */
1512                 *keysp = NULL;
1513                 return LDAP_SUCCESS;
1514         }
1515
1516         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1517
1518         slen = strlen( syntax->ssyn_oid );
1519         mlen = strlen( mr->smr_oid );
1520
1521         nkeys=0;
1522         for( i=0; values[i] != NULL; i++ ) {
1523                 int j,max;
1524                 struct berval *value;
1525
1526                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1527
1528                 value = ber_bvdup( values[i] );
1529                 ldap_pvt_str2upper( value->bv_val );
1530
1531                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1532                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1533                 {
1534                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
1535                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1536
1537                         for( j=0; j<max; j++ ) {
1538                                 lutil_MD5Init( &MD5context );
1539                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1540                                         lutil_MD5Update( &MD5context,
1541                                                 prefix->bv_val, prefix->bv_len );
1542                                 }
1543
1544                                 lutil_MD5Update( &MD5context,
1545                                         &pre, sizeof( pre ) );
1546                                 lutil_MD5Update( &MD5context,
1547                                         syntax->ssyn_oid, slen );
1548                                 lutil_MD5Update( &MD5context,
1549                                         mr->smr_oid, mlen );
1550                                 lutil_MD5Update( &MD5context,
1551                                         &value->bv_val[j],
1552                                         SLAP_INDEX_SUBSTR_MAXLEN );
1553                                 lutil_MD5Final( MD5digest, &MD5context );
1554
1555                                 keys[nkeys++] = ber_bvdup( &digest );
1556                         }
1557                 }
1558
1559                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1560                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1561
1562                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1563                         char pre;
1564
1565                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1566                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1567                                 lutil_MD5Init( &MD5context );
1568                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1569                                         lutil_MD5Update( &MD5context,
1570                                                 prefix->bv_val, prefix->bv_len );
1571                                 }
1572                                 lutil_MD5Update( &MD5context,
1573                                         &pre, sizeof( pre ) );
1574                                 lutil_MD5Update( &MD5context,
1575                                         syntax->ssyn_oid, slen );
1576                                 lutil_MD5Update( &MD5context,
1577                                         mr->smr_oid, mlen );
1578                                 lutil_MD5Update( &MD5context,
1579                                         value->bv_val, j );
1580                                 lutil_MD5Final( MD5digest, &MD5context );
1581
1582                                 keys[nkeys++] = ber_bvdup( &digest );
1583                         }
1584
1585                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1586                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1587                                 lutil_MD5Init( &MD5context );
1588                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1589                                         lutil_MD5Update( &MD5context,
1590                                                 prefix->bv_val, prefix->bv_len );
1591                                 }
1592                                 lutil_MD5Update( &MD5context,
1593                                         &pre, sizeof( pre ) );
1594                                 lutil_MD5Update( &MD5context,
1595                                         syntax->ssyn_oid, slen );
1596                                 lutil_MD5Update( &MD5context,
1597                                         mr->smr_oid, mlen );
1598                                 lutil_MD5Update( &MD5context,
1599                                         &value->bv_val[value->bv_len-j], j );
1600                                 lutil_MD5Final( MD5digest, &MD5context );
1601
1602                                 keys[nkeys++] = ber_bvdup( &digest );
1603                         }
1604
1605                 }
1606
1607                 ber_bvfree( value );
1608         }
1609
1610         if( nkeys > 0 ) {
1611                 keys[nkeys] = NULL;
1612                 *keysp = keys;
1613         } else {
1614                 ch_free( keys );
1615                 *keysp = NULL;
1616         }
1617
1618         return LDAP_SUCCESS;
1619 }
1620
1621 int caseIgnoreIA5SubstringsFilter(
1622         slap_mask_t use,
1623         slap_mask_t flags,
1624         Syntax *syntax,
1625         MatchingRule *mr,
1626         struct berval *prefix,
1627         void * assertValue,
1628         struct berval ***keysp )
1629 {
1630         SubstringsAssertion *sa = assertValue;
1631         char pre;
1632         ber_len_t nkeys = 0;
1633         size_t slen, mlen, klen;
1634         struct berval **keys;
1635         lutil_MD5_CTX   MD5context;
1636         unsigned char   MD5digest[LUTIL_MD5_BYTES];
1637         struct berval *value;
1638         struct berval digest;
1639
1640         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
1641                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1642         {
1643                 nkeys++;
1644         }
1645
1646         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
1647                 ber_len_t i;
1648                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1649                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1650                                 /* don't bother accounting for stepping */
1651                                 nkeys += sa->sa_any[i]->bv_len -
1652                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1653                         }
1654                 }
1655         }
1656
1657         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
1658                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1659         {
1660                 nkeys++;
1661         }
1662
1663         if( nkeys == 0 ) {
1664                 *keysp = NULL;
1665                 return LDAP_SUCCESS;
1666         }
1667
1668         digest.bv_val = MD5digest;
1669         digest.bv_len = sizeof(MD5digest);
1670
1671         slen = strlen( syntax->ssyn_oid );
1672         mlen = strlen( mr->smr_oid );
1673
1674         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1675         nkeys = 0;
1676
1677         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
1678                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1679         {
1680                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1681                 value = ber_bvdup( sa->sa_initial );
1682                 ldap_pvt_str2upper( value->bv_val );
1683
1684                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1685                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1686
1687                 lutil_MD5Init( &MD5context );
1688                 if( prefix != NULL && prefix->bv_len > 0 ) {
1689                         lutil_MD5Update( &MD5context,
1690                                 prefix->bv_val, prefix->bv_len );
1691                 }
1692                 lutil_MD5Update( &MD5context,
1693                         &pre, sizeof( pre ) );
1694                 lutil_MD5Update( &MD5context,
1695                         syntax->ssyn_oid, slen );
1696                 lutil_MD5Update( &MD5context,
1697                         mr->smr_oid, mlen );
1698                 lutil_MD5Update( &MD5context,
1699                         value->bv_val, klen );
1700                 lutil_MD5Final( MD5digest, &MD5context );
1701
1702                 ber_bvfree( value );
1703                 keys[nkeys++] = ber_bvdup( &digest );
1704         }
1705
1706         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
1707                 ber_len_t i, j;
1708                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1709                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1710
1711                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1712                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1713                                 continue;
1714                         }
1715
1716                         value = ber_bvdup( sa->sa_any[i] );
1717                         ldap_pvt_str2upper( value->bv_val );
1718
1719                         for(j=0;
1720                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1721                                 j += SLAP_INDEX_SUBSTR_STEP )
1722                         {
1723                                 lutil_MD5Init( &MD5context );
1724                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1725                                         lutil_MD5Update( &MD5context,
1726                                                 prefix->bv_val, prefix->bv_len );
1727                                 }
1728                                 lutil_MD5Update( &MD5context,
1729                                         &pre, sizeof( pre ) );
1730                                 lutil_MD5Update( &MD5context,
1731                                         syntax->ssyn_oid, slen );
1732                                 lutil_MD5Update( &MD5context,
1733                                         mr->smr_oid, mlen );
1734                                 lutil_MD5Update( &MD5context,
1735                                         &value->bv_val[j], klen );
1736                                 lutil_MD5Final( MD5digest, &MD5context );
1737
1738                                 keys[nkeys++] = ber_bvdup( &digest );
1739                         }
1740
1741                         ber_bvfree( value );
1742                 }
1743         }
1744
1745         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
1746                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1747         {
1748                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1749                 value = ber_bvdup( sa->sa_final );
1750                 ldap_pvt_str2upper( value->bv_val );
1751
1752                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1753                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1754
1755                 lutil_MD5Init( &MD5context );
1756                 if( prefix != NULL && prefix->bv_len > 0 ) {
1757                         lutil_MD5Update( &MD5context,
1758                                 prefix->bv_val, prefix->bv_len );
1759                 }
1760                 lutil_MD5Update( &MD5context,
1761                         &pre, sizeof( pre ) );
1762                 lutil_MD5Update( &MD5context,
1763                         syntax->ssyn_oid, slen );
1764                 lutil_MD5Update( &MD5context,
1765                         mr->smr_oid, mlen );
1766                 lutil_MD5Update( &MD5context,
1767                         &value->bv_val[value->bv_len-klen], klen );
1768                 lutil_MD5Final( MD5digest, &MD5context );
1769
1770                 ber_bvfree( value );
1771                 keys[nkeys++] = ber_bvdup( &digest );
1772         }
1773
1774         if( nkeys > 0 ) {
1775                 keys[nkeys] = NULL;
1776                 *keysp = keys;
1777         } else {
1778                 ch_free( keys );
1779                 *keysp = NULL;
1780         }
1781
1782         return LDAP_SUCCESS;
1783 }
1784         
1785 static int
1786 numericStringNormalize(
1787         Syntax *syntax,
1788         struct berval *val,
1789         struct berval **normalized )
1790 {
1791         /* similiar to IA5StringNormalize except removes all spaces */
1792         struct berval *newval;
1793         char *p, *q;
1794
1795         newval = ch_malloc( sizeof( struct berval ) );
1796
1797         p = val->bv_val;
1798
1799         /* Ignore initial whitespace */
1800         while ( ASCII_SPACE( *p ) ) {
1801                 p++;
1802         }
1803
1804         if( *p == '\0' ) {
1805                 ch_free( newval );
1806                 return LDAP_INVALID_SYNTAX;
1807         }
1808
1809         newval->bv_val = ch_strdup( p );
1810         p = q = newval->bv_val;
1811
1812         while ( *p ) {
1813                 if ( ASCII_SPACE( *p ) ) {
1814                         /* Ignore whitespace */
1815                         p++;
1816                 } else {
1817                         *q++ = *p++;
1818                 }
1819         }
1820
1821         assert( *newval->bv_val );
1822         assert( newval->bv_val < p );
1823         assert( q <= p );
1824
1825         /* cannot start with a space */
1826         assert( !ASCII_SPACE(*newval->bv_val) );
1827
1828         /* cannot end with a space */
1829         assert( !ASCII_SPACE( q[-1] ) );
1830
1831         /* null terminate */
1832         *q = '\0';
1833
1834         newval->bv_len = q - newval->bv_val;
1835         *normalized = newval;
1836
1837         return LDAP_SUCCESS;
1838 }
1839
1840 static int
1841 objectIdentifierFirstComponentMatch(
1842         int *matchp,
1843         slap_mask_t flags,
1844         Syntax *syntax,
1845         MatchingRule *mr,
1846         struct berval *value,
1847         void *assertedValue )
1848 {
1849         int rc = LDAP_SUCCESS;
1850         int match;
1851         struct berval *asserted = (struct berval *) assertedValue;
1852         ber_len_t i;
1853         struct berval oid;
1854
1855         if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1856                 return LDAP_INVALID_SYNTAX;
1857         }
1858
1859         /* trim leading white space */
1860         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1861                 /* empty */
1862         }
1863
1864         /* grab next word */
1865         oid.bv_val = &value->bv_val[i];
1866         oid.bv_len = value->bv_len - i;
1867         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
1868                 /* empty */
1869         }
1870         oid.bv_len = i;
1871
1872         /* insert attributeTypes, objectclass check here */
1873         if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1874                 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1875
1876         } else {
1877                 char *stored = ch_malloc( oid.bv_len + 1 );
1878                 AC_MEMCPY( stored, oid.bv_val, oid.bv_len );
1879                 stored[oid.bv_len] = '\0';
1880
1881                 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1882                         MatchingRule *asserted_mr = mr_find( asserted->bv_val );
1883                         MatchingRule *stored_mr = mr_find( stored );
1884
1885                         if( asserted_mr == NULL ) {
1886                                 rc = SLAPD_COMPARE_UNDEFINED;
1887                         } else {
1888                                 match = asserted_mr != stored_mr;
1889                         }
1890
1891                 } else if ( !strcmp( syntax->ssyn_oid,
1892                         SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1893                 {
1894                         AttributeType *asserted_at = at_find( asserted->bv_val );
1895                         AttributeType *stored_at = at_find( stored );
1896
1897                         if( asserted_at == NULL ) {
1898                                 rc = SLAPD_COMPARE_UNDEFINED;
1899                         } else {
1900                                 match = asserted_at != stored_at;
1901                         }
1902
1903                 } else if ( !strcmp( syntax->ssyn_oid,
1904                         SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1905                 {
1906                         ObjectClass *asserted_oc = oc_find( asserted->bv_val );
1907                         ObjectClass *stored_oc = oc_find( stored );
1908
1909                         if( asserted_oc == NULL ) {
1910                                 rc = SLAPD_COMPARE_UNDEFINED;
1911                         } else {
1912                                 match = asserted_oc != stored_oc;
1913                         }
1914                 }
1915
1916                 ch_free( stored );
1917         }
1918
1919         Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1920                 "%d\n\t\"%s\"\n\t\"%s\"\n",
1921             match, value->bv_val, asserted->bv_val );
1922
1923         if( rc == LDAP_SUCCESS ) *matchp = match;
1924         return rc;
1925 }
1926
1927 static int
1928 check_time_syntax (struct berval *val,
1929         int start,
1930         int *parts)
1931 {
1932         static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
1933         static int mdays[2][12] = {
1934                 /* non-leap years */
1935                 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
1936                 /* leap years */
1937                 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
1938         };
1939         char *p, *e;
1940         int part, c, tzoffset, leapyear = 0 ;
1941
1942         if( val->bv_len == 0 ) {
1943                 return LDAP_INVALID_SYNTAX;
1944         }
1945
1946         p = (char *)val->bv_val;
1947         e = p + val->bv_len;
1948
1949         /* Ignore initial whitespace */
1950         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
1951                 p++;
1952         }
1953
1954         if (e - p < 13 - (2 * start)) {
1955                 return LDAP_INVALID_SYNTAX;
1956         }
1957
1958         for (part = 0; part < 9; part++) {
1959                 parts[part] = 0;
1960         }
1961
1962         for (part = start; part < 7; part++) {
1963                 c = *p;
1964                 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
1965                         part++;
1966                         break;
1967                 }
1968                 p++;
1969                 c -= '0';
1970                 if (p == e) {
1971                         return LDAP_INVALID_SYNTAX;
1972                 }
1973                 if (c < 0 || c > 9) {
1974                         return LDAP_INVALID_SYNTAX;
1975                 }
1976                 parts[part] = c;
1977
1978                 c = *p++ - '0';
1979                 if (p == e) {
1980                         return LDAP_INVALID_SYNTAX;
1981                 }
1982                 if (c < 0 || c > 9) {
1983                         return LDAP_INVALID_SYNTAX;
1984                 }
1985                 parts[part] *= 10;
1986                 parts[part] += c;
1987
1988                 if (part == 2 || part == 3) {
1989                         parts[part]--;
1990                 }
1991                 if (parts[part] < 0) {
1992                         return LDAP_INVALID_SYNTAX;
1993                 }
1994                 if (parts[part] > ceiling[part]) {
1995                         return LDAP_INVALID_SYNTAX;
1996                 }
1997         }
1998
1999         /* leapyear check for the Gregorian calendar (year>1581) */
2000         if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2001                 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2002         {
2003                 leapyear = 1;
2004         }
2005
2006         if (parts[3] > mdays[leapyear][parts[2]]) {
2007                 return LDAP_INVALID_SYNTAX;
2008         }
2009         
2010         c = *p++;
2011         if (c == 'Z') {
2012                 tzoffset = 0; /* UTC */
2013         } else if (c != '+' && c != '-') {
2014                 return LDAP_INVALID_SYNTAX;
2015         } else {
2016                 if (c == '-') {
2017                         tzoffset = -1;
2018                 } else /* c == '+' */ {
2019                         tzoffset = 1;
2020                 }
2021
2022                 if (p > e - 4) {
2023                         return LDAP_INVALID_SYNTAX;
2024                 }
2025
2026                 for (part = 7; part < 9; part++) {
2027                         c = *p++ - '0';
2028                         if (c < 0 || c > 9) {
2029                                 return LDAP_INVALID_SYNTAX;
2030                         }
2031                         parts[part] = c;
2032
2033                         c = *p++ - '0';
2034                         if (c < 0 || c > 9) {
2035                                 return LDAP_INVALID_SYNTAX;
2036                         }
2037                         parts[part] *= 10;
2038                         parts[part] += c;
2039                         if (parts[part] < 0 || parts[part] > ceiling[part]) {
2040                                 return LDAP_INVALID_SYNTAX;
2041                         }
2042                 }
2043         }
2044
2045         /* Ignore trailing whitespace */
2046         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2047                 p++;
2048         }
2049         if (p != e) {
2050                 return LDAP_INVALID_SYNTAX;
2051         }
2052
2053         switch ( tzoffset ) {
2054         case -1: /* negativ offset to UTC, ie west of Greenwich  */
2055                 parts[4] += parts[7];
2056                 parts[5] += parts[8];
2057                 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2058                         if (part != 3) {
2059                                 c = ceiling[part];
2060                         } else {
2061                                 c = mdays[leapyear][parts[2]];
2062                         }
2063                         if (parts[part] > c) {
2064                                 parts[part] -= c + 1;
2065                                 parts[part - 1]++;
2066                         }
2067                 }
2068                 break;
2069         case 1: /* positive offset to UTC, ie east of Greenwich */
2070                 parts[4] -= parts[7];
2071                 parts[5] -= parts[8];
2072                 for (part = 6; --part > 0; ) {
2073                         if (part != 3) {
2074                                 c = ceiling[part];
2075                         } else {
2076                                 /* first arg to % needs to be non negativ */
2077                                 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2078                         }
2079                         if (parts[part] < 0) {
2080                                 parts[part] += c + 1;
2081                                 parts[part - 1]--;
2082                         }
2083                 }
2084                 break;
2085         case 0: /* already UTC */
2086                 break;
2087         }
2088
2089         return LDAP_SUCCESS;
2090 }
2091
2092 static int
2093 utcTimeNormalize(
2094         Syntax *syntax,
2095         struct berval *val,
2096         struct berval **normalized )
2097 {
2098         struct berval *out;
2099         int parts[9], rc;
2100
2101         rc = check_time_syntax(val, 1, parts);
2102         if (rc != LDAP_SUCCESS) {
2103                 return rc;
2104         }
2105
2106         *normalized = NULL;
2107         out = ch_malloc( sizeof(struct berval) );
2108         if( out == NULL ) {
2109                 return LBER_ERROR_MEMORY;
2110         }
2111
2112         out->bv_val = ch_malloc( 14 );
2113         if ( out->bv_val == NULL ) {
2114                 ch_free( out );
2115                 return LBER_ERROR_MEMORY;
2116         }
2117
2118         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ldZ",
2119                 parts[1], parts[2] + 1, parts[3] + 1,
2120                 parts[4], parts[5], parts[6] );
2121         out->bv_len = 13;
2122         *normalized = out;
2123
2124         return LDAP_SUCCESS;
2125 }
2126
2127 static int
2128 utcTimeValidate(
2129         Syntax *syntax,
2130         struct berval *in )
2131 {
2132         int parts[9];
2133
2134         return check_time_syntax(in, 1, parts);
2135 }
2136
2137 static int
2138 generalizedTimeValidate(
2139         Syntax *syntax,
2140         struct berval *in )
2141 {
2142         int parts[9];
2143
2144         return check_time_syntax(in, 0, parts);
2145 }
2146
2147 static int
2148 generalizedTimeNormalize(
2149         Syntax *syntax,
2150         struct berval *val,
2151         struct berval **normalized )
2152 {
2153         struct berval *out;
2154         int parts[9], rc;
2155
2156         rc = check_time_syntax(val, 0, parts);
2157         if (rc != LDAP_SUCCESS) {
2158                 return rc;
2159         }
2160
2161         *normalized = NULL;
2162         out = ch_malloc( sizeof(struct berval) );
2163         if( out == NULL ) {
2164                 return LBER_ERROR_MEMORY;
2165         }
2166
2167         out->bv_val = ch_malloc( 16 );
2168         if ( out->bv_val == NULL ) {
2169                 ch_free( out );
2170                 return LBER_ERROR_MEMORY;
2171         }
2172
2173         sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ld%02ldZ",
2174                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2175                 parts[4], parts[5], parts[6] );
2176         out->bv_len = 15;
2177         *normalized = out;
2178
2179         return LDAP_SUCCESS;
2180 }
2181
2182 static int
2183 nisNetgroupTripleValidate(
2184         Syntax *syntax,
2185         struct berval *val )
2186 {
2187         char *p, *e;
2188         int commas = 0;
2189
2190         if ( val->bv_len == 0 ) {
2191                 return LDAP_INVALID_SYNTAX;
2192         }
2193
2194         p = (char *)val->bv_val;
2195         e = p + val->bv_len;
2196
2197 #if 0
2198         /* syntax does not allow leading white space */
2199         /* Ignore initial whitespace */
2200         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2201                 p++;
2202         }
2203 #endif
2204
2205         if ( *p != '(' /*')'*/ ) {
2206                 return LDAP_INVALID_SYNTAX;
2207         }
2208
2209         for ( p++; ( p < e ) && ( *p != ')' ); p++ ) {
2210                 if ( *p == ',' ) {
2211                         commas++;
2212                         if ( commas > 2 ) {
2213                                 return LDAP_INVALID_SYNTAX;
2214                         }
2215
2216                 } else if ( !ATTR_CHAR( *p ) ) {
2217                         return LDAP_INVALID_SYNTAX;
2218                 }
2219         }
2220
2221         if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2222                 return LDAP_INVALID_SYNTAX;
2223         }
2224
2225         p++;
2226
2227 #if 0
2228         /* syntax does not allow trailing white space */
2229         /* Ignore trailing whitespace */
2230         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2231                 p++;
2232         }
2233 #endif
2234
2235         if (p != e) {
2236                 return LDAP_INVALID_SYNTAX;
2237         }
2238
2239         return LDAP_SUCCESS;
2240 }
2241
2242 static int
2243 bootParameterValidate(
2244         Syntax *syntax,
2245         struct berval *val )
2246 {
2247         char *p, *e;
2248
2249         if ( val->bv_len == 0 ) {
2250                 return LDAP_INVALID_SYNTAX;
2251         }
2252
2253         p = (char *)val->bv_val;
2254         e = p + val->bv_len;
2255
2256         /* key */
2257         for (; ( p < e ) && ( *p != '=' ); p++ ) {
2258                 if ( !ATTR_CHAR( *p ) ) {
2259                         return LDAP_INVALID_SYNTAX;
2260                 }
2261         }
2262
2263         if ( *p != '=' ) {
2264                 return LDAP_INVALID_SYNTAX;
2265         }
2266
2267         /* server */
2268         for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2269                 if ( !ATTR_CHAR( *p ) ) {
2270                         return LDAP_INVALID_SYNTAX;
2271                 }
2272         }
2273
2274         if ( *p != ':' ) {
2275                 return LDAP_INVALID_SYNTAX;
2276         }
2277
2278         /* path */
2279         for ( p++; p < e; p++ ) {
2280                 if ( !ATTR_CHAR( *p ) ) {
2281                         return LDAP_INVALID_SYNTAX;
2282                 }
2283         }
2284
2285         return LDAP_SUCCESS;
2286 }
2287
2288 struct syntax_defs_rec {
2289         char *sd_desc;
2290         int sd_flags;
2291         slap_syntax_validate_func *sd_validate;
2292         slap_syntax_transform_func *sd_normalize;
2293         slap_syntax_transform_func *sd_pretty;
2294 #ifdef SLAPD_BINARY_CONVERSION
2295         slap_syntax_transform_func *sd_ber2str;
2296         slap_syntax_transform_func *sd_str2ber;
2297 #endif
2298 };
2299
2300 #define X_HIDE "X-HIDE 'TRUE' "
2301 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2302 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2303
2304 struct syntax_defs_rec syntax_defs[] = {
2305         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
2306                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
2307         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2308                 0, NULL, NULL, NULL},
2309         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2310                 0, NULL, NULL, NULL},
2311         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
2312                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
2313         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_BINARY X_NOT_H_R ")",
2314                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2315         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2316                 0, bitStringValidate, bitStringNormalize, NULL },
2317         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2318                 0, booleanValidate, NULL, NULL},
2319         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2320                 X_BINARY X_NOT_H_R ")",
2321                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2322         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2323                 X_BINARY X_NOT_H_R ")",
2324                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2325         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2326                 X_BINARY X_NOT_H_R ")",
2327                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2328         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2329                 0, NULL, NULL, NULL},
2330         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2331                 0, dnValidate, dnNormalize, dnPretty},
2332         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2333                 0, NULL, NULL, NULL},
2334         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2335                 0, NULL, NULL, NULL},
2336         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2337                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
2338         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2339                 0, NULL, NULL, NULL},
2340         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2341                 0, NULL, NULL, NULL},
2342         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2343                 0, NULL, NULL, NULL},
2344         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2345                 0, NULL, NULL, NULL},
2346         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2347                 0, NULL, NULL, NULL},
2348         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2349                 0, IA5StringValidate, faxNumberNormalize, NULL},
2350         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2351                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
2352         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2353                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
2354         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2355                 0, NULL, NULL, NULL},
2356         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2357                 0, IA5StringValidate, IA5StringNormalize, NULL},
2358         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2359                 0, integerValidate, integerNormalize, integerPretty},
2360         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2361                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
2362         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2363                 0, NULL, NULL, NULL},
2364         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2365                 0, NULL, NULL, NULL},
2366         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2367                 0, NULL, NULL, NULL},
2368         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2369                 0, NULL, NULL, NULL},
2370         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2371                 0, NULL, NULL, NULL},
2372         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2373                 0, nameUIDValidate, nameUIDNormalize, nameUIDPretty},
2374         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2375                 0, NULL, NULL, NULL},
2376         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2377                 0, IA5StringValidate, numericStringNormalize, NULL},
2378         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2379                 0, NULL, NULL, NULL},
2380         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2381                 0, oidValidate, NULL, NULL},
2382         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2383                 0, NULL, NULL, NULL},
2384         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2385                 0, blobValidate, NULL, NULL},
2386         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2387                 0, blobValidate, NULL, NULL},
2388         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2389                 0, NULL, NULL, NULL},
2390         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2391                 0, NULL, NULL, NULL},
2392         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2393                 0, printableStringValidate, NULL, NULL},
2394         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2395                 X_BINARY X_NOT_H_R ")",
2396                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
2397         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2398                 0, IA5StringValidate, phoneNumberNormalize, NULL},
2399         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2400                 0, NULL, NULL, NULL},
2401         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2402                 0, IA5StringValidate, telexNumberNormalize, NULL},
2403         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2404                 0, utcTimeValidate, utcTimeNormalize, NULL},
2405         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2406                 0, NULL, NULL, NULL},
2407         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2408                 0, NULL, NULL, NULL},
2409         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2410                 0, NULL, NULL, NULL},
2411         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2412                 0, NULL, NULL, NULL},
2413         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2414                 0, NULL, NULL, NULL},
2415
2416         /* RFC 2307 NIS Syntaxes */
2417         {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Triple' )",
2418                 0, nisNetgroupTripleValidate, NULL, NULL},
2419         {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
2420                 0, bootParameterValidate, NULL, NULL},
2421
2422         /* OpenLDAP Experimental Syntaxes */
2423         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2424                 0, IA5StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2425                 NULL, NULL},
2426
2427         /* OpenLDAP Void Syntax */
2428         {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' " X_HIDE ")" ,
2429                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
2430         {NULL, 0, NULL, NULL, NULL}
2431 };
2432
2433 struct mrule_defs_rec {
2434         char *                                          mrd_desc;
2435         slap_mask_t                                     mrd_usage;
2436         slap_mr_convert_func *          mrd_convert;
2437         slap_mr_normalize_func *        mrd_normalize;
2438         slap_mr_match_func *            mrd_match;
2439         slap_mr_indexer_func *          mrd_indexer;
2440         slap_mr_filter_func *           mrd_filter;
2441
2442         char *                                          mrd_associated;
2443 };
2444
2445 /*
2446  * Other matching rules in X.520 that we do not use (yet):
2447  *
2448  * 2.5.13.9             numericStringOrderingMatch
2449  * 2.5.13.13    booleanMatch
2450  * 2.5.13.15    integerOrderingMatch
2451  * 2.5.13.18    octetStringOrderingMatch
2452  * 2.5.13.19    octetStringSubstringsMatch
2453  * 2.5.13.25    uTCTimeMatch
2454  * 2.5.13.26    uTCTimeOrderingMatch
2455  * 2.5.13.31    directoryStringFirstComponentMatch
2456  * 2.5.13.32    wordMatch
2457  * 2.5.13.33    keywordMatch
2458  * 2.5.13.34    certificateExactMatch
2459  * 2.5.13.35    certificateMatch
2460  * 2.5.13.36    certificatePairExactMatch
2461  * 2.5.13.37    certificatePairMatch
2462  * 2.5.13.38    certificateListExactMatch
2463  * 2.5.13.39    certificateListMatch
2464  * 2.5.13.40    algorithmIdentifierMatch
2465  * 2.5.13.41    storedPrefixMatch
2466  * 2.5.13.42    attributeCertificateMatch
2467  * 2.5.13.43    readerAndKeyIDMatch
2468  * 2.5.13.44    attributeIntegrityMatch
2469  */
2470
2471 struct mrule_defs_rec mrule_defs[] = {
2472         /*
2473          * Other matching rules
2474          */
2475         
2476         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2477                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2478                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2479                 NULL, NULL,
2480                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
2481                 NULL},
2482
2483         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2484                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2485                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2486                 NULL, NULL,
2487                 dnMatch, dnIndexer, dnFilter,
2488                 NULL},
2489
2490         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2491                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2492                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2493                 NULL, NULL,
2494                 caseIgnoreMatch, caseIgnoreIndexer, caseIgnoreFilter,
2495                 NULL},
2496
2497         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2498                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2499                 SLAP_MR_ORDERING,
2500                 NULL, NULL,
2501                 caseIgnoreOrderingMatch, NULL, NULL,
2502                 NULL},
2503
2504         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2505                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2506                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2507                 NULL, NULL,
2508                 caseIgnoreSubstringsMatch,
2509                 caseIgnoreSubstringsIndexer,
2510                 caseIgnoreSubstringsFilter,
2511                 NULL},
2512
2513         {"( 2.5.13.5 NAME 'caseExactMatch' "
2514                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2515                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2516                 NULL, NULL,
2517                 caseExactMatch, caseExactIndexer, caseExactFilter,
2518                 NULL},
2519
2520         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2521                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2522                 SLAP_MR_ORDERING,
2523                 NULL, NULL,
2524                 caseExactOrderingMatch, NULL, NULL,
2525                 NULL},
2526
2527         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2528                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2529                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2530                 NULL, NULL,
2531                 caseExactSubstringsMatch,
2532                 caseExactSubstringsIndexer,
2533                 caseExactSubstringsFilter,
2534                 NULL},
2535
2536         {"( 2.5.13.8 NAME 'numericStringMatch' "
2537                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2538                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2539                 NULL, NULL,
2540                 caseIgnoreIA5Match, NULL, NULL,
2541                 NULL},
2542
2543         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2544                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2545                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2546                 NULL, NULL,
2547                 caseIgnoreIA5SubstringsMatch,
2548                 caseIgnoreIA5SubstringsIndexer,
2549                 caseIgnoreIA5SubstringsFilter,
2550                 NULL},
2551
2552         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2553                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2554                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2555                 NULL, NULL,
2556                 caseIgnoreListMatch, NULL, NULL,
2557                 NULL},
2558
2559         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2560                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2561                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2562                 NULL, NULL,
2563                 caseIgnoreListSubstringsMatch, NULL, NULL,
2564                 NULL},
2565
2566         {"( 2.5.13.13 NAME 'booleanMatch' "
2567                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2568                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2569                 NULL, NULL,
2570                 booleanMatch, NULL, NULL,
2571                 NULL},
2572
2573         {"( 2.5.13.14 NAME 'integerMatch' "
2574                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2575                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2576                 NULL, NULL,
2577                 integerMatch, NULL, NULL,
2578                 NULL},
2579
2580         {"( 2.5.13.16 NAME 'bitStringMatch' "
2581                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2582                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2583                 NULL, NULL,
2584                 bitStringMatch, NULL, NULL,
2585                 NULL},
2586
2587         {"( 2.5.13.17 NAME 'octetStringMatch' "
2588                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
2589                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2590                 NULL, NULL,
2591                 octetStringMatch, octetStringIndexer, octetStringFilter,
2592                 NULL},
2593
2594         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
2595                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
2596                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2597                 NULL, NULL,
2598                 telephoneNumberMatch, NULL, NULL,
2599                 NULL},
2600
2601         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
2602                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2603                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
2604                 NULL, NULL,
2605                 telephoneNumberSubstringsMatch, NULL, NULL,
2606                 NULL},
2607
2608         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
2609                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
2610                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2611                 NULL, NULL,
2612                 presentationAddressMatch, NULL, NULL,
2613                 NULL},
2614
2615         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
2616                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
2617                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2618                 NULL, NULL,
2619                 uniqueMemberMatch, NULL, NULL,
2620                 NULL},
2621
2622         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
2623                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
2624                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2625                 NULL, NULL,
2626                 protocolInformationMatch, NULL, NULL,
2627                 NULL},
2628
2629         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
2630                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2631                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2632                 NULL, NULL,
2633                 generalizedTimeMatch, NULL, NULL,
2634                 NULL},
2635
2636         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
2637                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
2638                 SLAP_MR_ORDERING,
2639                 NULL, NULL,
2640                 generalizedTimeOrderingMatch, NULL, NULL,
2641                 NULL},
2642
2643         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
2644                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2645                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2646                 NULL, NULL,
2647                 integerFirstComponentMatch, NULL, NULL,
2648                 NULL},
2649
2650         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
2651                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2652                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2653                 NULL, NULL,
2654                 objectIdentifierFirstComponentMatch, NULL, NULL,
2655                 NULL},
2656
2657         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
2658                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2659                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2660                 NULL, NULL,
2661                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
2662                 NULL},
2663
2664         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
2665                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2666                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2667                 NULL, NULL,
2668                 caseIgnoreIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
2669                 NULL},
2670
2671         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
2672                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2673                 SLAP_MR_SUBSTR,
2674                 NULL, NULL,
2675                 caseIgnoreIA5SubstringsMatch,
2676                 caseIgnoreIA5SubstringsIndexer,
2677                 caseIgnoreIA5SubstringsFilter,
2678                 NULL},
2679
2680         {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
2681                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2682                 SLAP_MR_SUBSTR,
2683                 NULL, NULL,
2684                 caseExactIA5SubstringsMatch,
2685                 caseExactIA5SubstringsIndexer,
2686                 caseExactIA5SubstringsFilter,
2687                 NULL},
2688
2689         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
2690                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
2691                 SLAP_MR_EQUALITY,
2692                 NULL, NULL,
2693                 OpenLDAPaciMatch, NULL, NULL,
2694                 NULL},
2695
2696         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
2697 };
2698
2699 int
2700 schema_init( void )
2701 {
2702         int             res;
2703         int             i;
2704
2705         /* we should only be called once (from main) */
2706         assert( schema_init_done == 0 );
2707
2708         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
2709                 res = register_syntax( syntax_defs[i].sd_desc,
2710                     syntax_defs[i].sd_flags,
2711                     syntax_defs[i].sd_validate,
2712                     syntax_defs[i].sd_normalize,
2713                         syntax_defs[i].sd_pretty
2714 #ifdef SLAPD_BINARY_CONVERSION
2715                         ,
2716                     syntax_defs[i].sd_ber2str,
2717                         syntax_defs[i].sd_str2ber
2718 #endif
2719                 );
2720
2721                 if ( res ) {
2722                         fprintf( stderr, "schema_init: Error registering syntax %s\n",
2723                                  syntax_defs[i].sd_desc );
2724                         return LDAP_OTHER;
2725                 }
2726         }
2727
2728         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
2729                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
2730                         fprintf( stderr,
2731                                 "schema_init: Ingoring unusable matching rule %s\n",
2732                                  mrule_defs[i].mrd_desc );
2733                         continue;
2734                 }
2735
2736                 res = register_matching_rule(
2737                         mrule_defs[i].mrd_desc,
2738                         mrule_defs[i].mrd_usage,
2739                         mrule_defs[i].mrd_convert,
2740                         mrule_defs[i].mrd_normalize,
2741                     mrule_defs[i].mrd_match,
2742                         mrule_defs[i].mrd_indexer,
2743                         mrule_defs[i].mrd_filter,
2744                         mrule_defs[i].mrd_associated );
2745
2746                 if ( res ) {
2747                         fprintf( stderr,
2748                                 "schema_init: Error registering matching rule %s\n",
2749                                  mrule_defs[i].mrd_desc );
2750                         return LDAP_OTHER;
2751                 }
2752         }
2753         schema_init_done = 1;
2754         return LDAP_SUCCESS;
2755 }