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