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