]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
Fixup bdb_entry_release now that entry_decode uses two memory blocks
[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 #include <limits.h>
12
13 #include <ac/ctype.h>
14 #include <ac/errno.h>
15 #include <ac/string.h>
16 #include <ac/socket.h>
17
18 #include "slap.h"
19 #include "ldap_pvt.h"
20
21 #include "ldap_utf8.h"
22
23 #include "lutil_hash.h"
24 /* We should replace MD5 with a faster hash */
25 #define HASH_BYTES                              LUTIL_HASH_BYTES
26 #define HASH_CONTEXT                    lutil_HASH_CTX
27 #define HASH_Init(c)                    lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len)  lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c)                 lutil_HASHFinal(d,c)
30
31 /* recycled validatation routines */
32 #define berValidate                                             blobValidate
33
34 /* unimplemented pretters */
35 #ifndef USE_LDAP_DN_PARSING
36 #define dnPretty                                                NULL
37 #endif /* !USE_LDAP_DN_PARSING */
38 #define integerPretty                                   NULL
39
40 /* recycled matching routines */
41 #define bitStringMatch                                  octetStringMatch
42 #define numericStringMatch                              caseIgnoreIA5Match
43 #define objectIdentifierMatch                   caseIgnoreIA5Match
44 #define telephoneNumberMatch                    caseIgnoreIA5Match
45 #define telephoneNumberSubstringsMatch  caseIgnoreIA5SubstringsMatch
46 #define generalizedTimeMatch                    caseIgnoreIA5Match
47 #define generalizedTimeOrderingMatch    caseIgnoreIA5Match
48 #define uniqueMemberMatch                               dnMatch
49
50 /* approx matching rules */
51 #define directoryStringApproxMatchOID   "1.3.6.1.4.1.4203.666.4.4"
52 #define directoryStringApproxMatch      approxMatch
53 #define directoryStringApproxIndexer    approxIndexer
54 #define directoryStringApproxFilter     approxFilter
55 #define IA5StringApproxMatchOID                 "1.3.6.1.4.1.4203.666.4.5"
56 #define IA5StringApproxMatch                    approxMatch
57 #define IA5StringApproxIndexer                  approxIndexer
58 #define IA5StringApproxFilter                   approxFilter
59
60 /* orderring matching rules */
61 #define caseIgnoreOrderingMatch                 caseIgnoreMatch
62 #define caseExactOrderingMatch                  caseExactMatch
63
64 /* unimplemented matching routines */
65 #define caseIgnoreListMatch                             NULL
66 #define caseIgnoreListSubstringsMatch   NULL
67 #define protocolInformationMatch                NULL
68 #define integerFirstComponentMatch              NULL
69
70 #define OpenLDAPaciMatch                                NULL
71 #define authPasswordMatch                               NULL
72
73 /* recycled indexing/filtering routines */
74 #define dnIndexer                               caseExactIgnoreIndexer
75 #define dnFilter                                caseExactIgnoreFilter
76 #define bitStringFilter                 octetStringFilter
77 #define bitStringIndexer                octetStringIndexer
78
79 #define telephoneNumberIndexer                  caseIgnoreIA5Indexer
80 #define telephoneNumberFilter                   caseIgnoreIA5Filter
81 #define telephoneNumberSubstringsIndexer        caseIgnoreIA5SubstringsIndexer
82 #define telephoneNumberSubstringsFilter         caseIgnoreIA5SubstringsFilter
83
84 /* must match OIDs below */
85 #define caseExactMatchOID                       "2.5.13.5"
86 #define caseExactSubstringsMatchOID             "2.5.13.7"
87
88 static char *strcasechr( const char *str, int c )
89 {
90         char *lower = strchr( str, TOLOWER(c) );
91         char *upper = strchr( str, TOUPPER(c) );
92
93         if( lower && upper ) {
94                 return lower < upper ? lower : upper;
95         } else if ( lower ) {
96                 return lower;
97         } else {
98                 return upper;
99         }
100 }
101
102 static int
103 octetStringMatch(
104         int *matchp,
105         slap_mask_t flags,
106         Syntax *syntax,
107         MatchingRule *mr,
108         struct berval *value,
109         void *assertedValue )
110 {
111         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
112
113         if( match == 0 ) {
114                 match = memcmp( value->bv_val,
115                         ((struct berval *) assertedValue)->bv_val,
116                         value->bv_len );
117         }
118
119         *matchp = match;
120         return LDAP_SUCCESS;
121 }
122
123 /* Index generation function */
124 int octetStringIndexer(
125         slap_mask_t use,
126         slap_mask_t flags,
127         Syntax *syntax,
128         MatchingRule *mr,
129         struct berval *prefix,
130         struct berval **values,
131         struct berval ***keysp )
132 {
133         int i;
134         size_t slen, mlen;
135         struct berval **keys;
136         HASH_CONTEXT   HASHcontext;
137         unsigned char   HASHdigest[HASH_BYTES];
138         struct berval digest;
139         digest.bv_val = HASHdigest;
140         digest.bv_len = sizeof(HASHdigest);
141
142         for( i=0; values[i] != NULL; i++ ) {
143                 /* just count them */
144         }
145
146         /* we should have at least one value at this point */
147         assert( i > 0 );
148
149         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
150
151         slen = strlen( syntax->ssyn_oid );
152         mlen = strlen( mr->smr_oid );
153
154         for( i=0; values[i] != NULL; i++ ) {
155                 HASH_Init( &HASHcontext );
156                 if( prefix != NULL && prefix->bv_len > 0 ) {
157                         HASH_Update( &HASHcontext,
158                                 prefix->bv_val, prefix->bv_len );
159                 }
160                 HASH_Update( &HASHcontext,
161                         syntax->ssyn_oid, slen );
162                 HASH_Update( &HASHcontext,
163                         mr->smr_oid, mlen );
164                 HASH_Update( &HASHcontext,
165                         values[i]->bv_val, values[i]->bv_len );
166                 HASH_Final( HASHdigest, &HASHcontext );
167
168                 keys[i] = ber_bvdup( &digest );
169         }
170
171         keys[i] = NULL;
172
173         *keysp = keys;
174
175         return LDAP_SUCCESS;
176 }
177
178 /* Index generation function */
179 int octetStringFilter(
180         slap_mask_t use,
181         slap_mask_t flags,
182         Syntax *syntax,
183         MatchingRule *mr,
184         struct berval *prefix,
185         void * assertValue,
186         struct berval ***keysp )
187 {
188         size_t slen, mlen;
189         struct berval **keys;
190         HASH_CONTEXT   HASHcontext;
191         unsigned char   HASHdigest[HASH_BYTES];
192         struct berval *value = (struct berval *) assertValue;
193         struct berval digest;
194         digest.bv_val = HASHdigest;
195         digest.bv_len = sizeof(HASHdigest);
196
197         slen = strlen( syntax->ssyn_oid );
198         mlen = strlen( mr->smr_oid );
199
200         keys = ch_malloc( sizeof( struct berval * ) * 2 );
201
202         HASH_Init( &HASHcontext );
203         if( prefix != NULL && prefix->bv_len > 0 ) {
204                 HASH_Update( &HASHcontext,
205                         prefix->bv_val, prefix->bv_len );
206         }
207         HASH_Update( &HASHcontext,
208                 syntax->ssyn_oid, slen );
209         HASH_Update( &HASHcontext,
210                 mr->smr_oid, mlen );
211         HASH_Update( &HASHcontext,
212                 value->bv_val, value->bv_len );
213         HASH_Final( HASHdigest, &HASHcontext );
214
215         keys[0] = ber_bvdup( &digest );
216         keys[1] = NULL;
217
218         *keysp = keys;
219
220         return LDAP_SUCCESS;
221 }
222
223 #ifdef USE_LDAP_DN_PARSING
224 static int
225 dnValidate(
226         Syntax *syntax,
227         struct berval *in )
228 {
229         int             rc;
230         LDAPDN          *dn = NULL;
231
232         if ( in->bv_len == 0 ) {
233                 return( LDAP_SUCCESS );
234         }
235
236         rc = ldap_str2dn( in->bv_val, &dn, LDAP_DN_FORMAT_LDAPV3 );
237         ldapava_free_dn( dn );
238         
239         if ( rc != LDAP_SUCCESS ) {
240                 return( LDAP_INVALID_SYNTAX );
241         }
242
243         return( LDAP_SUCCESS );
244 }
245
246 int
247 dnNormalize(
248         Syntax *syntax,
249         struct berval *val,
250         struct berval **normalized )
251 {
252         struct berval *out = NULL;
253
254         if ( val->bv_len != 0 ) {
255                 LDAPDN          *dn = NULL;
256                 char            *dn_out = NULL;
257                 int             rc;
258
259                 rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAPV3 );
260                 if ( rc != LDAP_SUCCESS ) {
261                         return( LDAP_INVALID_SYNTAX );
262                 }
263
264                 rc = ldap_dn2str( dn, &dn_out, LDAP_DN_FORMAT_LDAPV3 );
265                 ldapava_free_dn( dn );
266
267                 if ( rc != LDAP_SUCCESS ) {
268                         return( LDAP_INVALID_SYNTAX );
269                 }
270
271                 out = ber_bvstr( dn_out );
272
273         } else {
274                 out = ber_bvdup( val );
275         }
276
277         *normalized = out;
278
279         return( LDAP_SUCCESS );
280 }
281
282 int
283 dnPretty(
284         Syntax *syntax,
285         struct berval *val,
286         struct berval **normalized)
287 {
288         struct berval *out = NULL;
289
290         if ( val->bv_len != 0 ) {
291                 LDAPDN          *dn = NULL;
292                 char            *dn_out = NULL;
293                 unsigned        flags = LDAP_DN_FORMAT_LDAPV3;
294                 int             rc;
295
296                 rc = ldap_str2dn( val->bv_val, &dn, flags );
297                 if ( rc != LDAP_SUCCESS ) {
298                         return( LDAP_INVALID_SYNTAX );
299                 }
300
301                 flags |= LDAP_DN_PRETTY;
302
303                 rc = ldap_dn2str( dn, &dn_out, flags );
304                 ldapava_free_dn( dn );
305
306                 if ( rc != LDAP_SUCCESS ) {
307                         return( LDAP_INVALID_SYNTAX );
308                 }
309
310                 out = ber_bvstr( dn_out );
311
312         } else {
313                 out = ber_bvdup( val );
314         }
315
316         *normalized = out;
317
318         return( LDAP_SUCCESS );
319 }
320
321 int
322 dnMatch(
323         int *matchp,
324         slap_mask_t flags,
325         Syntax *syntax,
326         MatchingRule *mr,
327         struct berval *value,
328         void *assertedValue )
329 {
330         int match;
331         struct berval *asserted = (struct berval *) assertedValue;
332         
333         match = value->bv_len - asserted->bv_len;
334
335         if ( match == 0 ) {
336 #ifdef USE_DN_NORMALIZE
337                 match = strcmp( value->bv_val, asserted->bv_val );
338                 fprintf(stderr, "USE_DN_NORMALIZE :(\n");
339 #else
340                 match = strcasecmp( value->bv_val, asserted->bv_val );
341                 fprintf(stderr, "!USE_DN_NORMALIZE :)\n");
342 #endif
343         }
344
345 #ifdef NEW_LOGGING
346         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
347                 "dnMatch: %d\n    %s\n    %s\n", match,
348                 value->bv_val, asserted->bv_val ));
349 #else
350         Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
351                 match, value->bv_val, asserted->bv_val );
352 #endif
353
354         *matchp = match;
355         return( LDAP_SUCCESS );
356 }
357
358 #else /* !USE_LDAP_DN_PARSING */
359
360 static int
361 dnValidate(
362         Syntax *syntax,
363         struct berval *in )
364 {
365         int rc;
366         char *dn;
367
368         if( in->bv_len == 0 ) return LDAP_SUCCESS;
369
370         dn = ch_strdup( in->bv_val );
371
372         if( dn == NULL ) {
373                 return LDAP_INVALID_SYNTAX;
374
375         } else if ( strlen( in->bv_val ) != in->bv_len ) {
376                 rc = LDAP_INVALID_SYNTAX;
377
378         } else if ( dn_validate( dn ) == NULL ) {
379                 rc = LDAP_INVALID_SYNTAX;
380
381         } else {
382                 rc = LDAP_SUCCESS;
383         }
384
385         ch_free( dn );
386         return rc;
387 }
388
389 int
390 dnNormalize(
391         Syntax *syntax,
392         struct berval *val,
393         struct berval **normalized )
394 {
395         struct berval *out;
396
397         if ( val->bv_len != 0 ) {
398                 char *dn;
399                 out = ber_bvstr( UTF8normalize( val, UTF8_CASEFOLD ) );
400
401                 dn = dn_validate( out->bv_val );
402
403                 if( dn == NULL ) {
404                         ber_bvfree( out );
405                         return LDAP_INVALID_SYNTAX;
406                 }
407
408                 out->bv_val = dn;
409                 out->bv_len = strlen( dn );
410         } else {
411                 out = ber_bvdup( val );
412         }
413
414         *normalized = out;
415         return LDAP_SUCCESS;
416 }
417
418 int
419 dnMatch(
420         int *matchp,
421         slap_mask_t flags,
422         Syntax *syntax,
423         MatchingRule *mr,
424         struct berval *value,
425         void *assertedValue )
426 {
427         int match;
428         struct berval *asserted = (struct berval *) assertedValue;
429         
430         match = value->bv_len - asserted->bv_len;
431
432         if( match == 0 ) {
433 #ifdef USE_DN_NORMALIZE
434                 match = strcmp( value->bv_val, asserted->bv_val );
435 #else
436                 match = strcasecmp( value->bv_val, asserted->bv_val );
437 #endif
438         }
439
440 #ifdef NEW_LOGGING
441         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
442                 "dnMatch: %d\n    %s\n    %s\n", match,
443                 value->bv_val, asserted->bv_val ));
444 #else
445         Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
446                 match, value->bv_val, asserted->bv_val );
447 #endif
448
449
450         *matchp = match;
451         return LDAP_SUCCESS;
452 }
453
454 #endif /* !USE_LDAP_DN_PARSING */
455
456 static int
457 nameUIDValidate(
458         Syntax *syntax,
459         struct berval *in )
460 {
461         int rc;
462         struct berval *dn;
463
464         if( in->bv_len == 0 ) return LDAP_SUCCESS;
465
466         dn = ber_bvdup( in );
467
468         if( dn->bv_val[dn->bv_len-1] == '\'' ) {
469                 /* assume presence of optional UID */
470                 ber_len_t i;
471
472                 for(i=dn->bv_len-2; i>2; i--) {
473                         if( dn->bv_val[i] != '0' &&     dn->bv_val[i] != '1' ) {
474                                 break;
475                         }
476                 }
477                 if( dn->bv_val[i] != '\'' ||
478                     dn->bv_val[i-1] != 'B' ||
479                     dn->bv_val[i-2] != '#' ) {
480                         ber_bvfree( dn );
481                         return LDAP_INVALID_SYNTAX;
482                 }
483
484                 /* trim the UID to allow use of dn_validate */
485                 dn->bv_val[i-2] = '\0';
486         }
487
488         rc = dn_validate( dn->bv_val ) == NULL
489                 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
490
491         ber_bvfree( dn );
492         return rc;
493 }
494
495 static int
496 nameUIDNormalize(
497         Syntax *syntax,
498         struct berval *val,
499         struct berval **normalized )
500 {
501         struct berval *out = ber_bvdup( val );
502
503         if( out->bv_len != 0 ) {
504                 char *dn;
505                 ber_len_t dnlen;
506                 char *uid = NULL;
507                 ber_len_t uidlen = 0;
508
509                 if( out->bv_val[out->bv_len-1] == '\'' ) {
510                         /* assume presence of optional UID */
511                         uid = strrchr( out->bv_val, '#' );
512
513                         if( uid == NULL ) {
514                                 ber_bvfree( out );
515                                 return LDAP_INVALID_SYNTAX;
516                         }
517
518                         uidlen = out->bv_len - (out->bv_val - uid);
519                         /* temporarily trim the UID */
520                         *uid = '\0';
521                 }
522
523 #ifdef USE_DN_NORMALIZE
524                 dn = dn_normalize( out->bv_val );
525 #else
526                 dn = dn_validate( out->bv_val );
527 #endif
528
529                 if( dn == NULL ) {
530                         ber_bvfree( out );
531                         return LDAP_INVALID_SYNTAX;
532                 }
533
534                 dnlen = strlen(dn);
535
536                 if( uidlen ) {
537                         /* restore the separator */
538                         *uid = '#';
539                         /* shift the UID */
540                         SAFEMEMCPY( &dn[dnlen], uid, uidlen );
541                 }
542
543                 out->bv_val = dn;
544                 out->bv_len = dnlen + uidlen;
545         }
546
547         *normalized = out;
548         return LDAP_SUCCESS;
549 }
550
551 static int
552 inValidate(
553         Syntax *syntax,
554         struct berval *in )
555 {
556         /* any value allowed */
557         return LDAP_OTHER;
558 }
559
560 static int
561 blobValidate(
562         Syntax *syntax,
563         struct berval *in )
564 {
565         /* any value allowed */
566         return LDAP_SUCCESS;
567 }
568
569 static int
570 bitStringValidate(
571         Syntax *syntax,
572         struct berval *in )
573 {
574         ber_len_t i;
575
576         /* very unforgiving validation, requires no normalization
577          * before simplistic matching
578          */
579         if( in->bv_len < 3 ) {
580                 return LDAP_INVALID_SYNTAX;
581         }
582
583         /*
584          * rfc 2252 section 6.3 Bit String
585          * bitstring = "'" *binary-digit "'"
586          * binary-digit = "0" / "1"
587          * example: '0101111101'B
588          */
589         
590         if( in->bv_val[0] != '\'' ||
591                 in->bv_val[in->bv_len-2] != '\'' ||
592                 in->bv_val[in->bv_len-1] != 'B' )
593         {
594                 return LDAP_INVALID_SYNTAX;
595         }
596
597         for( i=in->bv_len-3; i>0; i-- ) {
598                 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
599                         return LDAP_INVALID_SYNTAX;
600                 }
601         }
602
603         return LDAP_SUCCESS;
604 }
605
606 static int
607 bitStringNormalize(
608         Syntax *syntax,
609         struct berval *val,
610         struct berval **normalized )
611 {
612         /*
613      * A normalized bitString is has no extaneous (leading) zero bits.
614          * That is, '00010'B is normalized to '10'B
615          * However, as a special case, '0'B requires no normalization.
616      */
617         struct berval *newval;
618         char *p;
619
620         /* start at the first bit */
621         p = &val->bv_val[1];
622
623         /* Find the first non-zero bit */
624         while ( *p == '0' ) p++;
625
626         newval = (struct berval *) ch_malloc( sizeof(struct berval) );
627
628         if( *p == '\'' ) {
629                 /* no non-zero bits */
630                 newval->bv_val = ch_strdup("\'0\'B");
631                 newval->bv_len = sizeof("\'0\'B") - 1;
632                 goto done;
633         }
634
635         newval->bv_val = ch_malloc( val->bv_len + 1 );
636
637         newval->bv_val[0] = '\'';
638         newval->bv_len = 1;
639
640         for( ; *p != '\0'; p++ ) {
641                 newval->bv_val[newval->bv_len++] = *p;
642         }
643
644         newval->bv_val[newval->bv_len] = '\0';
645
646 done:
647         *normalized = newval;
648         return LDAP_SUCCESS;
649 }
650
651 /*
652  * Handling boolean syntax and matching is quite rigid.
653  * A more flexible approach would be to allow a variety
654  * of strings to be normalized and prettied into TRUE
655  * and FALSE.
656  */
657 static int
658 booleanValidate(
659         Syntax *syntax,
660         struct berval *in )
661 {
662         /* very unforgiving validation, requires no normalization
663          * before simplistic matching
664          */
665
666         if( in->bv_len == 4 ) {
667                 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
668                         return LDAP_SUCCESS;
669                 }
670         } else if( in->bv_len == 5 ) {
671                 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
672                         return LDAP_SUCCESS;
673                 }
674         }
675
676         return LDAP_INVALID_SYNTAX;
677 }
678
679 static int
680 booleanMatch(
681         int *matchp,
682         slap_mask_t flags,
683         Syntax *syntax,
684         MatchingRule *mr,
685         struct berval *value,
686         void *assertedValue )
687 {
688         /* simplistic matching allowed by rigid validation */
689         struct berval *asserted = (struct berval *) assertedValue;
690         *matchp = value->bv_len != asserted->bv_len;
691         return LDAP_SUCCESS;
692 }
693
694 static int
695 UTF8StringValidate(
696         Syntax *syntax,
697         struct berval *in )
698 {
699         ber_len_t count;
700         int len;
701         unsigned char *u = in->bv_val;
702
703         if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
704
705         for( count = in->bv_len; count > 0; count-=len, u+=len ) {
706                 /* get the length indicated by the first byte */
707                 len = LDAP_UTF8_CHARLEN( u );
708
709                 /* should not be zero */
710                 if( len == 0 ) return LDAP_INVALID_SYNTAX;
711
712                 /* make sure len corresponds with the offset
713                         to the next character */
714                 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
715         }
716
717         if( count != 0 ) return LDAP_INVALID_SYNTAX;
718
719         return LDAP_SUCCESS;
720 }
721
722 static int
723 UTF8StringNormalize(
724         Syntax *syntax,
725         struct berval *val,
726         struct berval **normalized )
727 {
728         struct berval *newval;
729         char *p, *q, *s;
730
731         newval = ch_malloc( sizeof( struct berval ) );
732
733         p = val->bv_val;
734
735         /* Ignore initial whitespace */
736         while ( ldap_utf8_isspace( p ) ) {
737                 LDAP_UTF8_INCR( p );
738         }
739
740         if( *p == '\0' ) {
741                 ch_free( newval );
742                 return LDAP_INVALID_SYNTAX;
743         }
744
745         newval->bv_val = ch_strdup( p );
746         p = q = newval->bv_val;
747         s = NULL;
748
749         while ( *p ) {
750                 int len;
751
752                 if ( ldap_utf8_isspace( p ) ) {
753                         len = LDAP_UTF8_COPY(q,p);
754                         s=q;
755                         p+=len;
756                         q+=len;
757
758                         /* Ignore the extra whitespace */
759                         while ( ldap_utf8_isspace( p ) ) {
760                                 LDAP_UTF8_INCR( p );
761                         }
762                 } else {
763                         len = LDAP_UTF8_COPY(q,p);
764                         s=NULL;
765                         p+=len;
766                         q+=len;
767                 }
768         }
769
770         assert( *newval->bv_val );
771         assert( newval->bv_val < p );
772         assert( q <= p );
773
774         /* cannot start with a space */
775         assert( !ldap_utf8_isspace(newval->bv_val) );
776
777         /*
778          * If the string ended in space, backup the pointer one
779          * position.  One is enough because the above loop collapsed
780          * all whitespace to a single space.
781          */
782
783         if ( s != NULL ) {
784                 q = s;
785         }
786
787         /* cannot end with a space */
788         assert( !ldap_utf8_isspace( LDAP_UTF8_PREV(q) ) );
789
790         /* null terminate */
791         *q = '\0';
792
793         newval->bv_len = q - newval->bv_val;
794         *normalized = newval;
795
796         return LDAP_SUCCESS;
797 }
798
799 /* Returns Unicode cannonically normalized copy of a substring assertion
800  * Skipping attribute description */
801 SubstringsAssertion *
802 UTF8SubstringsassertionNormalize(
803         SubstringsAssertion *sa,
804         char casefold )
805 {
806         SubstringsAssertion *nsa;
807         int i;
808
809         nsa = (SubstringsAssertion *)ch_calloc( 1, sizeof(SubstringsAssertion) );
810         if( nsa == NULL ) {
811                 return NULL;
812         }
813
814         if( sa->sa_initial != NULL ) {
815                 nsa->sa_initial = ber_bvstr( UTF8normalize( sa->sa_initial, casefold ) );
816                 if( nsa->sa_initial == NULL ) {
817                         goto err;
818                 }
819         }
820
821         if( sa->sa_any != NULL ) {
822                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
823                         /* empty */
824                 }
825                 nsa->sa_any = (struct berval **)ch_malloc( (i + 1) * sizeof(struct berval *) );
826                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
827                         nsa->sa_any[i] = ber_bvstr( UTF8normalize( sa->sa_any[i], casefold ) );
828                         if( nsa->sa_any[i] == NULL ) {
829                                 goto err;
830                         }
831                 }
832                 nsa->sa_any[i] = NULL;
833         }
834
835         if( sa->sa_final != NULL ) {
836                 nsa->sa_final = ber_bvstr( UTF8normalize( sa->sa_final, casefold ) );
837                 if( nsa->sa_final == NULL ) {
838                         goto err;
839                 }
840         }
841
842         return nsa;
843
844 err:
845         ber_bvfree( nsa->sa_final );
846         ber_bvecfree( nsa->sa_any );
847         ber_bvfree( nsa->sa_initial );
848         ch_free( nsa );
849         return NULL;
850 }
851
852 /* Strip characters with the 8th bit set */
853 char *
854 strip8bitChars(
855         char *in )      
856 {
857         char *p = in, *q;
858   
859         if( in == NULL ) {
860                 return NULL;
861         }
862         while( *p ) {
863                 if( *p & 0x80 ) {
864                         q = p;
865                         while( *++q & 0x80 ) {
866                                 /* empty */
867                         }
868                         p = memmove(p, q, strlen(q) + 1);
869                 } else {
870                         p++;
871                 }
872         }
873         return in;
874 }
875
876 #ifndef SLAPD_APPROX_OLDSINGLESTRING
877
878 #if defined(SLAPD_APPROX_INITIALS)
879 #define SLAPD_APPROX_DELIMITER "._ "
880 #define SLAPD_APPROX_WORDLEN 2
881 #else
882 #define SLAPD_APPROX_DELIMITER " "
883 #define SLAPD_APPROX_WORDLEN 1
884 #endif
885
886 static int
887 approxMatch(
888         int *matchp,
889         slap_mask_t flags,
890         Syntax *syntax,
891         MatchingRule *mr,
892         struct berval *value,
893         void *assertedValue )
894 {
895         char *val, *nval, *assertv, **values, **words, *c;
896         int i, count, len, nextchunk=0, nextavail=0;
897         size_t avlen;
898
899         /* Yes, this is necessary */
900         nval = UTF8normalize( value, UTF8_NOCASEFOLD );
901         if( nval == NULL ) {
902                 *matchp = 1;
903                 return LDAP_SUCCESS;
904         }
905         strip8bitChars( nval );
906
907         /* Yes, this is necessary */
908         assertv = UTF8normalize( ((struct berval *)assertedValue),
909                                  UTF8_NOCASEFOLD );
910         if( assertv == NULL ) {
911                 ch_free( nval );
912                 *matchp = 1;
913                 return LDAP_SUCCESS;
914         }
915         strip8bitChars( assertv );
916         avlen = strlen( assertv );
917
918         /* Isolate how many words there are */
919         for( c=nval,count=1; *c; c++ ) {
920                 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
921                 if ( c == NULL ) break;
922                 *c = '\0';
923                 count++;
924         }
925
926         /* Get a phonetic copy of each word */
927         words = (char **)ch_malloc( count * sizeof(char *) );
928         values = (char **)ch_malloc( count * sizeof(char *) );
929         for( c=nval,i=0;  i<count;  i++,c+=strlen(c)+1 ) {
930                 words[i] = c;
931                 values[i] = phonetic(c);
932         }
933
934         /* Work through the asserted value's words, to see if at least some
935            of the words are there, in the same order. */
936         len = 0;
937         while ( nextchunk < avlen ) {
938                 len = strcspn( assertv + nextchunk, SLAPD_APPROX_DELIMITER);
939                 if( len == 0 ) {
940                         nextchunk++;
941                         continue;
942                 }
943 #if defined(SLAPD_APPROX_INITIALS)
944                 else if( len == 1 ) {
945                         /* Single letter words need to at least match one word's initial */
946                         for( i=nextavail; i<count; i++ )
947                                 if( !strncasecmp( assertv+nextchunk, words[i], 1 )) {
948                                         nextavail=i+1;
949                                         break;
950                                 }
951                 }
952 #endif
953                 else {
954                         /* Isolate the next word in the asserted value and phonetic it */
955                         assertv[nextchunk+len] = '\0';
956                         val = phonetic( assertv + nextchunk );
957
958                         /* See if this phonetic chunk is in the remaining words of *value */
959                         for( i=nextavail; i<count; i++ ){
960                                 if( !strcmp( val, values[i] ) ){
961                                         nextavail = i+1;
962                                         break;
963                                 }
964                         }
965                         ch_free( val );
966                 }
967
968                 /* This chunk in the asserted value was NOT within the *value. */
969                 if( i >= count ) {
970                         nextavail=-1;
971                         break;
972                 }
973
974                 /* Go on to the next word in the asserted value */
975                 nextchunk += len+1;
976         }
977
978         /* If some of the words were seen, call it a match */
979         if( nextavail > 0 ) {
980                 *matchp = 0;
981         }
982         else {
983                 *matchp = 1;
984         }
985
986         /* Cleanup allocs */
987         free( assertv );
988         for( i=0; i<count; i++ ) {
989                 ch_free( values[i] );
990         }
991         ch_free( values );
992         ch_free( words );
993         ch_free( nval );
994
995         return LDAP_SUCCESS;
996 }
997
998 int 
999 approxIndexer(
1000         slap_mask_t use,
1001         slap_mask_t flags,
1002         Syntax *syntax,
1003         MatchingRule *mr,
1004         struct berval *prefix,
1005         struct berval **values,
1006         struct berval ***keysp )
1007 {
1008         char *val, *c;
1009         int i,j, len, wordcount, keycount=0;
1010         struct berval **newkeys, **keys=NULL;
1011
1012         for( j=0; values[j] != NULL; j++ ) {
1013                 /* Yes, this is necessary */
1014                 val = UTF8normalize( values[j], UTF8_NOCASEFOLD );
1015                 strip8bitChars( val );
1016
1017                 /* Isolate how many words there are. There will be a key for each */
1018                 for( wordcount=0,c=val;  *c;  c++) {
1019                         len = strcspn(c, SLAPD_APPROX_DELIMITER);
1020                         if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1021                         c+= len;
1022                         if (*c == '\0') break;
1023                         *c = '\0';
1024                 }
1025
1026                 /* Allocate/increase storage to account for new keys */
1027                 newkeys = (struct berval **)ch_malloc( (keycount + wordcount + 1) 
1028                         * sizeof(struct berval *) );
1029                 memcpy( newkeys, keys, keycount * sizeof(struct berval *) );
1030                 if( keys ) ch_free( keys );
1031                 keys = newkeys;
1032
1033                 /* Get a phonetic copy of each word */
1034                 for( c=val,i=0;  i<wordcount;  c+=len+1  ) {
1035                         len = strlen( c );
1036                         if( len < SLAPD_APPROX_WORDLEN ) continue;
1037                         keys[keycount] = (struct berval *)ch_malloc( sizeof(struct berval) );
1038                         keys[keycount]->bv_val = phonetic( c );
1039                         keys[keycount]->bv_len = strlen( keys[keycount]->bv_val );
1040                         keycount++;
1041                         i++;
1042                 }
1043
1044                 free( val );
1045         }
1046         keys[keycount] = NULL;
1047         *keysp = keys;
1048
1049         return LDAP_SUCCESS;
1050 }
1051
1052 int 
1053 approxFilter(
1054         slap_mask_t use,
1055         slap_mask_t flags,
1056         Syntax *syntax,
1057         MatchingRule *mr,
1058         struct berval *prefix,
1059         void * assertValue,
1060         struct berval ***keysp )
1061 {
1062         char *val, *c;
1063         int i, count, len;
1064         struct berval **keys;
1065
1066         /* Yes, this is necessary */
1067         val = UTF8normalize( ((struct berval *)assertValue),
1068                              UTF8_NOCASEFOLD );
1069         if( val == NULL ) {
1070                 keys = (struct berval **)ch_malloc( sizeof(struct berval *) );
1071                 keys[0] = NULL;
1072                 *keysp = keys;
1073                 return LDAP_SUCCESS;
1074         }
1075         strip8bitChars( val );
1076
1077         /* Isolate how many words there are. There will be a key for each */
1078         for( count=0,c=val;  *c;  c++) {
1079                 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1080                 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1081                 c+= len;
1082                 if (*c == '\0') break;
1083                 *c = '\0';
1084         }
1085
1086         /* Allocate storage for new keys */
1087         keys = (struct berval **)ch_malloc( (count + 1) * sizeof(struct berval *) );
1088
1089         /* Get a phonetic copy of each word */
1090         for( c=val,i=0;  i<count; c+=len+1 ) {
1091                 len = strlen(c);
1092                 if( len < SLAPD_APPROX_WORDLEN ) continue;
1093                 keys[i] = ber_bvstr( phonetic( c ) );
1094                 i++;
1095         }
1096
1097         free( val );
1098
1099         keys[count] = NULL;
1100         *keysp = keys;
1101
1102         return LDAP_SUCCESS;
1103 }
1104
1105
1106 #else
1107 /* No other form of Approximate Matching is defined */
1108
1109 static int
1110 approxMatch(
1111         int *matchp,
1112         slap_mask_t flags,
1113         Syntax *syntax,
1114         MatchingRule *mr,
1115         struct berval *value,
1116         void *assertedValue )
1117 {
1118         char *vapprox, *avapprox;
1119         char *s, *t;
1120
1121         /* Yes, this is necessary */
1122         s = UTF8normalize( value, UTF8_NOCASEFOLD );
1123         if( s == NULL ) {
1124                 *matchp = 1;
1125                 return LDAP_SUCCESS;
1126         }
1127
1128         /* Yes, this is necessary */
1129         t = UTF8normalize( ((struct berval *)assertedValue),
1130                            UTF8_NOCASEFOLD );
1131         if( t == NULL ) {
1132                 free( s );
1133                 *matchp = -1;
1134                 return LDAP_SUCCESS;
1135         }
1136
1137         vapprox = phonetic( strip8bitChars( s ) );
1138         avapprox = phonetic( strip8bitChars( t ) );
1139
1140         free( s );
1141         free( t );
1142
1143         *matchp = strcmp( vapprox, avapprox );
1144
1145         ch_free( vapprox );
1146         ch_free( avapprox );
1147
1148         return LDAP_SUCCESS;
1149 }
1150
1151 int 
1152 approxIndexer(
1153         slap_mask_t use,
1154         slap_mask_t flags,
1155         Syntax *syntax,
1156         MatchingRule *mr,
1157         struct berval *prefix,
1158         struct berval **values,
1159         struct berval ***keysp )
1160 {
1161         int i;
1162         struct berval **keys;
1163         char *s;
1164
1165         for( i=0; values[i] != NULL; i++ ) {
1166                 /* empty - just count them */
1167         }
1168
1169         /* we should have at least one value at this point */
1170         assert( i > 0 );
1171
1172         keys = (struct berval **)ch_malloc( sizeof( struct berval * ) * (i+1) );
1173
1174         /* Copy each value and run it through phonetic() */
1175         for( i=0; values[i] != NULL; i++ ) {
1176                 /* Yes, this is necessary */
1177                 s = UTF8normalize( values[i], UTF8_NOCASEFOLD );
1178
1179                 /* strip 8-bit chars and run through phonetic() */
1180                 keys[i] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1181                 free( s );
1182         }
1183         keys[i] = NULL;
1184
1185         *keysp = keys;
1186         return LDAP_SUCCESS;
1187 }
1188
1189
1190 int 
1191 approxFilter(
1192         slap_mask_t use,
1193         slap_mask_t flags,
1194         Syntax *syntax,
1195         MatchingRule *mr,
1196         struct berval *prefix,
1197         void * assertValue,
1198         struct berval ***keysp )
1199 {
1200         struct berval **keys;
1201         char *s;
1202
1203         keys = (struct berval **)ch_malloc( sizeof( struct berval * ) * 2 );
1204
1205         /* Yes, this is necessary */
1206         s = UTF8normalize( ((struct berval *)assertValue),
1207                              UTF8_NOCASEFOLD );
1208         if( s == NULL ) {
1209                 keys[0] = NULL;
1210         } else {
1211                 /* strip 8-bit chars and run through phonetic() */
1212                 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1213                 free( s );
1214                 keys[1] = NULL;
1215         }
1216
1217         *keysp = keys;
1218         return LDAP_SUCCESS;
1219 }
1220 #endif
1221
1222
1223 static int
1224 caseExactMatch(
1225         int *matchp,
1226         slap_mask_t flags,
1227         Syntax *syntax,
1228         MatchingRule *mr,
1229         struct berval *value,
1230         void *assertedValue )
1231 {
1232         *matchp = UTF8normcmp( value->bv_val,
1233                 ((struct berval *) assertedValue)->bv_val,
1234                 UTF8_NOCASEFOLD );
1235         return LDAP_SUCCESS;
1236 }
1237
1238 static int
1239 caseExactIgnoreSubstringsMatch(
1240         int *matchp,
1241         slap_mask_t flags,
1242         Syntax *syntax,
1243         MatchingRule *mr,
1244         struct berval *value,
1245         void *assertedValue )
1246 {
1247         int match = 0;
1248         SubstringsAssertion *sub = NULL;
1249         struct berval left;
1250         int i;
1251         ber_len_t inlen=0;
1252         char *nav, casefold;
1253
1254         casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
1255                 ? UTF8_CASEFOLD : UTF8_NOCASEFOLD;
1256
1257         nav = UTF8normalize( value, casefold );
1258         if( nav == NULL ) {
1259                 match = 1;
1260                 goto done;
1261         }
1262         left.bv_val = nav;
1263         left.bv_len = strlen( nav );
1264
1265         sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1266         if( sub == NULL ) {
1267                 match = -1;
1268                 goto done;
1269         }
1270
1271         /* Add up asserted input length */
1272         if( sub->sa_initial ) {
1273                 inlen += sub->sa_initial->bv_len;
1274         }
1275         if( sub->sa_any ) {
1276                 for(i=0; sub->sa_any[i] != NULL; i++) {
1277                         inlen += sub->sa_any[i]->bv_len;
1278                 }
1279         }
1280         if( sub->sa_final ) {
1281                 inlen += sub->sa_final->bv_len;
1282         }
1283
1284         if( sub->sa_initial ) {
1285                 if( inlen > left.bv_len ) {
1286                         match = 1;
1287                         goto done;
1288                 }
1289
1290                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
1291                         sub->sa_initial->bv_len );
1292
1293                 if( match != 0 ) {
1294                         goto done;
1295                 }
1296
1297                 left.bv_val += sub->sa_initial->bv_len;
1298                 left.bv_len -= sub->sa_initial->bv_len;
1299                 inlen -= sub->sa_initial->bv_len;
1300         }
1301
1302         if( sub->sa_final ) {
1303                 if( inlen > left.bv_len ) {
1304                         match = 1;
1305                         goto done;
1306                 }
1307
1308                 match = strncmp( sub->sa_final->bv_val,
1309                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
1310                         sub->sa_final->bv_len );
1311
1312                 if( match != 0 ) {
1313                         goto done;
1314                 }
1315
1316                 left.bv_len -= sub->sa_final->bv_len;
1317                 inlen -= sub->sa_final->bv_len;
1318         }
1319
1320         if( sub->sa_any ) {
1321                 for(i=0; sub->sa_any[i]; i++) {
1322                         ber_len_t idx;
1323                         char *p;
1324
1325 retry:
1326                         if( inlen > left.bv_len ) {
1327                                 /* not enough length */
1328                                 match = 1;
1329                                 goto done;
1330                         }
1331
1332                         if( sub->sa_any[i]->bv_len == 0 ) {
1333                                 continue;
1334                         }
1335
1336                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
1337
1338                         if( p == NULL ) {
1339                                 match = 1;
1340                                 goto done;
1341                         }
1342
1343                         idx = p - left.bv_val;
1344                         assert( idx < left.bv_len );
1345
1346                         if( idx >= left.bv_len ) {
1347                                 /* this shouldn't happen */
1348                                 free( nav );
1349                                 ch_free( sub->sa_final );
1350                                 ber_bvecfree( sub->sa_any );
1351                                 ch_free( sub->sa_initial );
1352                                 ch_free( sub );
1353                                 return LDAP_OTHER;
1354                         }
1355
1356                         left.bv_val = p;
1357                         left.bv_len -= idx;
1358
1359                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
1360                                 /* not enough left */
1361                                 match = 1;
1362                                 goto done;
1363                         }
1364
1365                         match = strncmp( left.bv_val,
1366                                 sub->sa_any[i]->bv_val,
1367                                 sub->sa_any[i]->bv_len );
1368
1369                         if( match != 0 ) {
1370                                 left.bv_val++;
1371                                 left.bv_len--;
1372                                 goto retry;
1373                         }
1374
1375                         left.bv_val += sub->sa_any[i]->bv_len;
1376                         left.bv_len -= sub->sa_any[i]->bv_len;
1377                         inlen -= sub->sa_any[i]->bv_len;
1378                 }
1379         }
1380
1381 done:
1382         free( nav );
1383         if( sub != NULL ) {
1384                 ber_bvfree( sub->sa_final );
1385                 ber_bvecfree( sub->sa_any );
1386                 ber_bvfree( sub->sa_initial );
1387                 ch_free( sub );
1388         }
1389         *matchp = match;
1390         return LDAP_SUCCESS;
1391 }
1392
1393 /* Index generation function */
1394 int caseExactIgnoreIndexer(
1395         slap_mask_t use,
1396         slap_mask_t flags,
1397         Syntax *syntax,
1398         MatchingRule *mr,
1399         struct berval *prefix,
1400         struct berval **values,
1401         struct berval ***keysp )
1402 {
1403         int i;
1404         char casefold;
1405         size_t slen, mlen;
1406         struct berval **keys;
1407         HASH_CONTEXT   HASHcontext;
1408         unsigned char   HASHdigest[HASH_BYTES];
1409         struct berval digest;
1410         digest.bv_val = HASHdigest;
1411         digest.bv_len = sizeof(HASHdigest);
1412
1413         for( i=0; values[i] != NULL; i++ ) {
1414                 /* empty - just count them */
1415         }
1416
1417         /* we should have at least one value at this point */
1418         assert( i > 0 );
1419
1420         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
1421
1422         slen = strlen( syntax->ssyn_oid );
1423         mlen = strlen( mr->smr_oid );
1424
1425         casefold = strcmp( mr->smr_oid, caseExactMatchOID )
1426                 ? UTF8_CASEFOLD : UTF8_NOCASEFOLD;
1427
1428         for( i=0; values[i] != NULL; i++ ) {
1429                 struct berval *value;
1430                 value = ber_bvstr( UTF8normalize( values[i],
1431                         casefold ) );
1432
1433                 HASH_Init( &HASHcontext );
1434                 if( prefix != NULL && prefix->bv_len > 0 ) {
1435                         HASH_Update( &HASHcontext,
1436                                 prefix->bv_val, prefix->bv_len );
1437                 }
1438                 HASH_Update( &HASHcontext,
1439                         syntax->ssyn_oid, slen );
1440                 HASH_Update( &HASHcontext,
1441                         mr->smr_oid, mlen );
1442                 HASH_Update( &HASHcontext,
1443                         value->bv_val, value->bv_len );
1444                 HASH_Final( HASHdigest, &HASHcontext );
1445
1446                 ber_bvfree( value );
1447
1448                 keys[i] = ber_bvdup( &digest );
1449         }
1450
1451         keys[i] = NULL;
1452         *keysp = keys;
1453         return LDAP_SUCCESS;
1454 }
1455
1456 /* Index generation function */
1457 int caseExactIgnoreFilter(
1458         slap_mask_t use,
1459         slap_mask_t flags,
1460         Syntax *syntax,
1461         MatchingRule *mr,
1462         struct berval *prefix,
1463         void * assertValue,
1464         struct berval ***keysp )
1465 {
1466         char casefold;
1467         size_t slen, mlen;
1468         struct berval **keys;
1469         HASH_CONTEXT   HASHcontext;
1470         unsigned char   HASHdigest[HASH_BYTES];
1471         struct berval *value;
1472         struct berval digest;
1473         digest.bv_val = HASHdigest;
1474         digest.bv_len = sizeof(HASHdigest);
1475
1476         slen = strlen( syntax->ssyn_oid );
1477         mlen = strlen( mr->smr_oid );
1478
1479         casefold = strcmp( mr->smr_oid, caseExactMatchOID )
1480                 ? UTF8_CASEFOLD : UTF8_NOCASEFOLD;
1481
1482         value = ber_bvstr( UTF8normalize( ((struct berval *) assertValue),
1483                 casefold ) );
1484         /* This usually happens if filter contains bad UTF8 */
1485         if( value == NULL ) {
1486                 keys = ch_malloc( sizeof( struct berval * ) );
1487                 keys[0] = NULL;
1488                 return LDAP_SUCCESS;
1489         }
1490
1491         keys = ch_malloc( sizeof( struct berval * ) * 2 );
1492
1493         HASH_Init( &HASHcontext );
1494         if( prefix != NULL && prefix->bv_len > 0 ) {
1495                 HASH_Update( &HASHcontext,
1496                         prefix->bv_val, prefix->bv_len );
1497         }
1498         HASH_Update( &HASHcontext,
1499                 syntax->ssyn_oid, slen );
1500         HASH_Update( &HASHcontext,
1501                 mr->smr_oid, mlen );
1502         HASH_Update( &HASHcontext,
1503                 value->bv_val, value->bv_len );
1504         HASH_Final( HASHdigest, &HASHcontext );
1505
1506         keys[0] = ber_bvdup( &digest );
1507         keys[1] = NULL;
1508
1509         ber_bvfree( value );
1510
1511         *keysp = keys;
1512         return LDAP_SUCCESS;
1513 }
1514
1515 /* Substrings Index generation function */
1516 int caseExactIgnoreSubstringsIndexer(
1517         slap_mask_t use,
1518         slap_mask_t flags,
1519         Syntax *syntax,
1520         MatchingRule *mr,
1521         struct berval *prefix,
1522         struct berval **values,
1523         struct berval ***keysp )
1524 {
1525         char casefold;
1526         ber_len_t i, nkeys;
1527         size_t slen, mlen;
1528         struct berval **keys;
1529         struct berval **nvalues;
1530
1531         HASH_CONTEXT   HASHcontext;
1532         unsigned char   HASHdigest[HASH_BYTES];
1533         struct berval digest;
1534         digest.bv_val = HASHdigest;
1535         digest.bv_len = sizeof(HASHdigest);
1536
1537         nkeys=0;
1538
1539         for( i=0; values[i] != NULL; i++ ) {
1540                 /* empty - just count them */
1541         }
1542
1543         /* we should have at least one value at this point */
1544         assert( i > 0 );
1545
1546         casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
1547                 ? UTF8_CASEFOLD : UTF8_NOCASEFOLD;
1548
1549         nvalues = ch_malloc( sizeof( struct berval * ) * (i+1) );
1550         for( i=0; values[i] != NULL; i++ ) {
1551                 nvalues[i] = ber_bvstr( UTF8normalize( values[i],
1552                         casefold ) );
1553         }
1554         nvalues[i] = NULL;
1555         values = nvalues;
1556
1557         for( i=0; values[i] != NULL; i++ ) {
1558                 /* count number of indices to generate */
1559                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1560                         continue;
1561                 }
1562
1563                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1564                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1565                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1566                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1567                         } else {
1568                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1569                         }
1570                 }
1571
1572                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1573                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1574                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1575                         }
1576                 }
1577
1578                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1579                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1580                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1581                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1582                         } else {
1583                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1584                         }
1585                 }
1586         }
1587
1588         if( nkeys == 0 ) {
1589                 /* no keys to generate */
1590                 *keysp = NULL;
1591                 ber_bvecfree( nvalues );
1592                 return LDAP_SUCCESS;
1593         }
1594
1595         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1596
1597         slen = strlen( syntax->ssyn_oid );
1598         mlen = strlen( mr->smr_oid );
1599
1600         nkeys=0;
1601         for( i=0; values[i] != NULL; i++ ) {
1602                 ber_len_t j,max;
1603                 struct berval *value;
1604
1605                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1606
1607                 value = values[i];
1608
1609                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1610                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1611                 {
1612                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
1613                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1614
1615                         for( j=0; j<max; j++ ) {
1616                                 HASH_Init( &HASHcontext );
1617                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1618                                         HASH_Update( &HASHcontext,
1619                                                 prefix->bv_val, prefix->bv_len );
1620                                 }
1621
1622                                 HASH_Update( &HASHcontext,
1623                                         &pre, sizeof( pre ) );
1624                                 HASH_Update( &HASHcontext,
1625                                         syntax->ssyn_oid, slen );
1626                                 HASH_Update( &HASHcontext,
1627                                         mr->smr_oid, mlen );
1628                                 HASH_Update( &HASHcontext,
1629                                         &value->bv_val[j],
1630                                         SLAP_INDEX_SUBSTR_MAXLEN );
1631                                 HASH_Final( HASHdigest, &HASHcontext );
1632
1633                                 keys[nkeys++] = ber_bvdup( &digest );
1634                         }
1635                 }
1636
1637                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1638                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1639
1640                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1641                         char pre;
1642
1643                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1644                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1645                                 HASH_Init( &HASHcontext );
1646                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1647                                         HASH_Update( &HASHcontext,
1648                                                 prefix->bv_val, prefix->bv_len );
1649                                 }
1650                                 HASH_Update( &HASHcontext,
1651                                         &pre, sizeof( pre ) );
1652                                 HASH_Update( &HASHcontext,
1653                                         syntax->ssyn_oid, slen );
1654                                 HASH_Update( &HASHcontext,
1655                                         mr->smr_oid, mlen );
1656                                 HASH_Update( &HASHcontext,
1657                                         value->bv_val, j );
1658                                 HASH_Final( HASHdigest, &HASHcontext );
1659
1660                                 keys[nkeys++] = ber_bvdup( &digest );
1661                         }
1662
1663                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1664                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1665                                 HASH_Init( &HASHcontext );
1666                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1667                                         HASH_Update( &HASHcontext,
1668                                                 prefix->bv_val, prefix->bv_len );
1669                                 }
1670                                 HASH_Update( &HASHcontext,
1671                                         &pre, sizeof( pre ) );
1672                                 HASH_Update( &HASHcontext,
1673                                         syntax->ssyn_oid, slen );
1674                                 HASH_Update( &HASHcontext,
1675                                         mr->smr_oid, mlen );
1676                                 HASH_Update( &HASHcontext,
1677                                         &value->bv_val[value->bv_len-j], j );
1678                                 HASH_Final( HASHdigest, &HASHcontext );
1679
1680                                 keys[nkeys++] = ber_bvdup( &digest );
1681                         }
1682
1683                 }
1684
1685         }
1686
1687         if( nkeys > 0 ) {
1688                 keys[nkeys] = NULL;
1689                 *keysp = keys;
1690         } else {
1691                 ch_free( keys );
1692                 *keysp = NULL;
1693         }
1694
1695         ber_bvecfree( nvalues );
1696
1697         return LDAP_SUCCESS;
1698 }
1699
1700 int caseExactIgnoreSubstringsFilter(
1701         slap_mask_t use,
1702         slap_mask_t flags,
1703         Syntax *syntax,
1704         MatchingRule *mr,
1705         struct berval *prefix,
1706         void * assertValue,
1707         struct berval ***keysp )
1708 {
1709         SubstringsAssertion *sa;
1710         char pre, casefold;
1711         ber_len_t nkeys = 0;
1712         size_t slen, mlen, klen;
1713         struct berval **keys;
1714         HASH_CONTEXT   HASHcontext;
1715         unsigned char   HASHdigest[HASH_BYTES];
1716         struct berval *value;
1717         struct berval digest;
1718
1719         casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
1720                 ? UTF8_CASEFOLD : UTF8_NOCASEFOLD;
1721
1722         sa = UTF8SubstringsassertionNormalize( assertValue, casefold );
1723         if( sa == NULL ) {
1724                 *keysp = NULL;
1725                 return LDAP_SUCCESS;
1726         }
1727
1728         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1729                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1730         {
1731                 nkeys++;
1732         }
1733
1734         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1735                 ber_len_t i;
1736                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1737                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1738                                 /* don't bother accounting for stepping */
1739                                 nkeys += sa->sa_any[i]->bv_len -
1740                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1741                         }
1742                 }
1743         }
1744
1745         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1746                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1747         {
1748                 nkeys++;
1749         }
1750
1751         if( nkeys == 0 ) {
1752                 ber_bvfree( sa->sa_final );
1753                 ber_bvecfree( sa->sa_any );
1754                 ber_bvfree( sa->sa_initial );
1755                 ch_free( sa );
1756                 *keysp = NULL;
1757                 return LDAP_SUCCESS;
1758         }
1759
1760         digest.bv_val = HASHdigest;
1761         digest.bv_len = sizeof(HASHdigest);
1762
1763         slen = strlen( syntax->ssyn_oid );
1764         mlen = strlen( mr->smr_oid );
1765
1766         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
1767         nkeys = 0;
1768
1769         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
1770                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1771         {
1772                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1773                 value = sa->sa_initial;
1774
1775                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1776                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1777
1778                 HASH_Init( &HASHcontext );
1779                 if( prefix != NULL && prefix->bv_len > 0 ) {
1780                         HASH_Update( &HASHcontext,
1781                                 prefix->bv_val, prefix->bv_len );
1782                 }
1783                 HASH_Update( &HASHcontext,
1784                         &pre, sizeof( pre ) );
1785                 HASH_Update( &HASHcontext,
1786                         syntax->ssyn_oid, slen );
1787                 HASH_Update( &HASHcontext,
1788                         mr->smr_oid, mlen );
1789                 HASH_Update( &HASHcontext,
1790                         value->bv_val, klen );
1791                 HASH_Final( HASHdigest, &HASHcontext );
1792
1793                 keys[nkeys++] = ber_bvdup( &digest );
1794         }
1795
1796         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1797                 ber_len_t i, j;
1798                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1799                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1800
1801                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
1802                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1803                                 continue;
1804                         }
1805
1806                         value = sa->sa_any[i];
1807
1808                         for(j=0;
1809                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1810                                 j += SLAP_INDEX_SUBSTR_STEP )
1811                         {
1812                                 HASH_Init( &HASHcontext );
1813                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1814                                         HASH_Update( &HASHcontext,
1815                                                 prefix->bv_val, prefix->bv_len );
1816                                 }
1817                                 HASH_Update( &HASHcontext,
1818                                         &pre, sizeof( pre ) );
1819                                 HASH_Update( &HASHcontext,
1820                                         syntax->ssyn_oid, slen );
1821                                 HASH_Update( &HASHcontext,
1822                                         mr->smr_oid, mlen );
1823                                 HASH_Update( &HASHcontext,
1824                                         &value->bv_val[j], klen ); 
1825                                 HASH_Final( HASHdigest, &HASHcontext );
1826
1827                                 keys[nkeys++] = ber_bvdup( &digest );
1828                         }
1829
1830                 }
1831         }
1832
1833         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
1834                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1835         {
1836                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1837                 value = sa->sa_final;
1838
1839                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1840                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1841
1842                 HASH_Init( &HASHcontext );
1843                 if( prefix != NULL && prefix->bv_len > 0 ) {
1844                         HASH_Update( &HASHcontext,
1845                                 prefix->bv_val, prefix->bv_len );
1846                 }
1847                 HASH_Update( &HASHcontext,
1848                         &pre, sizeof( pre ) );
1849                 HASH_Update( &HASHcontext,
1850                         syntax->ssyn_oid, slen );
1851                 HASH_Update( &HASHcontext,
1852                         mr->smr_oid, mlen );
1853                 HASH_Update( &HASHcontext,
1854                         &value->bv_val[value->bv_len-klen], klen );
1855                 HASH_Final( HASHdigest, &HASHcontext );
1856
1857                 keys[nkeys++] = ber_bvdup( &digest );
1858         }
1859
1860         if( nkeys > 0 ) {
1861                 keys[nkeys] = NULL;
1862                 *keysp = keys;
1863         } else {
1864                 ch_free( keys );
1865                 *keysp = NULL;
1866         }
1867         ber_bvfree( sa->sa_final );
1868         ber_bvecfree( sa->sa_any );
1869         ber_bvfree( sa->sa_initial );
1870         ch_free( sa );
1871
1872         return LDAP_SUCCESS;
1873 }
1874
1875 static int
1876 caseIgnoreMatch(
1877         int *matchp,
1878         slap_mask_t flags,
1879         Syntax *syntax,
1880         MatchingRule *mr,
1881         struct berval *value,
1882         void *assertedValue )
1883 {
1884         *matchp = UTF8normcmp( value->bv_val,
1885                 ((struct berval *) assertedValue)->bv_val,
1886                 UTF8_CASEFOLD );
1887         return LDAP_SUCCESS;
1888 }
1889         
1890 static int
1891 oidValidate(
1892         Syntax *syntax,
1893         struct berval *val )
1894 {
1895         ber_len_t i;
1896
1897         if( val->bv_len == 0 ) {
1898                 /* disallow empty strings */
1899                 return LDAP_INVALID_SYNTAX;
1900         }
1901
1902         if( OID_LEADCHAR(val->bv_val[0]) ) {
1903                 int dot = 0;
1904                 for(i=1; i < val->bv_len; i++) {
1905                         if( OID_SEPARATOR( val->bv_val[i] ) ) {
1906                                 if( dot++ ) return 1;
1907                         } else if ( OID_CHAR( val->bv_val[i] ) ) {
1908                                 dot = 0;
1909                         } else {
1910                                 return LDAP_INVALID_SYNTAX;
1911                         }
1912                 }
1913
1914                 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1915
1916         } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1917                 for(i=1; i < val->bv_len; i++) {
1918                         if( !DESC_CHAR(val->bv_val[i] ) ) {
1919                                 return LDAP_INVALID_SYNTAX;
1920                         }
1921                 }
1922
1923                 return LDAP_SUCCESS;
1924         }
1925         
1926         return LDAP_INVALID_SYNTAX;
1927 }
1928
1929 static int
1930 integerMatch(
1931         int *matchp,
1932         slap_mask_t flags,
1933         Syntax *syntax,
1934         MatchingRule *mr,
1935         struct berval *value,
1936         void *assertedValue )
1937 {
1938         char *v, *av;
1939         int vsign=0, avsign=0;
1940         struct berval *asserted;
1941         ber_len_t vlen, avlen;
1942
1943
1944         /* Start off pessimistic */
1945         *matchp = 1;
1946
1947         /* Skip past leading spaces/zeros, and get the sign of the *value number */
1948         v = value->bv_val;
1949         vlen = value->bv_len;
1950         while( vlen ) {
1951                 if( ASCII_SPACE(*v) || ( *v == '0' )) {
1952                         /* empty -- skip spaces */
1953                 }
1954                 else if ( *v == '+' ) {
1955                         vsign = 1;
1956                 }
1957                 else if ( *v == '-' ) {
1958                         vsign = -1;
1959                 }
1960                 else if ( ASCII_DIGIT(*v) ) {
1961                         if ( vsign == 0 ) vsign = 1;
1962                         vsign *= 2;
1963                         break;
1964                 }
1965                 v++;
1966                 vlen--;
1967         }
1968
1969         /* Skip past leading spaces/zeros, and get the sign of the *assertedValue
1970            number */
1971         asserted = (struct berval *) assertedValue;
1972         av = asserted->bv_val;
1973         avlen = asserted->bv_len;
1974         while( avlen ) {
1975                 if( ASCII_SPACE(*av) || ( *av == '0' )) {
1976                         /* empty -- skip spaces */
1977                 }
1978                 else if ( *av == '+' ) {
1979                         avsign = 1;
1980                 }
1981                 else if ( *av == '-' ) {
1982                         avsign = -1;
1983                 }
1984                 else if ( ASCII_DIGIT(*av) ) {
1985                         if ( avsign == 0 ) avsign = 1;
1986                         avsign *= 2;
1987                         break;
1988                 }
1989                 av++;
1990                 avlen--;
1991         }
1992
1993         /* The two ?sign vars are now one of :
1994            -2  negative non-zero number
1995            -1  -0   \
1996             0   0   collapse these three to 0
1997            +1  +0   /
1998            +2  positive non-zero number
1999         */
2000         if ( abs( vsign ) == 1 ) vsign = 0;
2001         if ( abs( avsign ) == 1 ) avsign = 0;
2002
2003         if( vsign != avsign ) return LDAP_SUCCESS;
2004
2005         /* Check the significant digits */
2006         while( vlen && avlen ) {
2007                 if( *v != *av ) break;
2008                 v++;
2009                 vlen--;
2010                 av++;
2011                 avlen--;
2012         }
2013
2014         /* If all digits compared equal, the numbers are equal */
2015         if(( vlen == 0 ) && ( avlen == 0 )) {
2016                 *matchp = 0;
2017         }
2018         return LDAP_SUCCESS;
2019 }
2020         
2021 static int
2022 integerValidate(
2023         Syntax *syntax,
2024         struct berval *val )
2025 {
2026         ber_len_t i;
2027
2028         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2029
2030         if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
2031                 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
2032         } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
2033                 return LDAP_INVALID_SYNTAX;
2034         }
2035
2036         for( i=1; i < val->bv_len; i++ ) {
2037                 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
2038         }
2039
2040         return LDAP_SUCCESS;
2041 }
2042
2043 static int
2044 integerNormalize(
2045         Syntax *syntax,
2046         struct berval *val,
2047         struct berval **normalized )
2048 {
2049         char *p;
2050         int negative=0;
2051         struct berval *newval;
2052         ber_len_t len;
2053
2054
2055         p = val->bv_val;
2056         len = val->bv_len;
2057
2058         /* Ignore leading spaces */
2059         while ( len && ( *p == ' ' )) {
2060                 p++;
2061                 len--;
2062         }
2063
2064         /* save sign */
2065         if( len ) {
2066                 negative = ( *p == '-' );
2067                 if(( *p == '-' ) || ( *p == '+' )) {
2068                         p++;
2069                         len--;
2070                 }
2071         }
2072
2073         /* Ignore leading zeros */
2074         while ( len && ( *p == '0' )) {
2075                 p++;
2076                 len--;
2077         }
2078
2079         newval = (struct berval *) ch_malloc( sizeof(struct berval) );
2080
2081         /* If there are no non-zero digits left, the number is zero, otherwise
2082            allocate space for the number and copy it into the buffer */
2083         if( len == 0 ) {
2084                 newval->bv_val = ch_strdup("0");
2085                 newval->bv_len = 1;
2086         }
2087         else {
2088                 newval->bv_len = len+negative;
2089                 newval->bv_val = ch_malloc( newval->bv_len );
2090                 if( negative ) {
2091                         newval->bv_val[0] = '-';
2092                 }
2093                 memcpy( newval->bv_val + negative, p, len );
2094         }
2095
2096         *normalized = newval;
2097         return LDAP_SUCCESS;
2098 }
2099
2100 /* Index generation function */
2101 int integerIndexer(
2102         slap_mask_t use,
2103         slap_mask_t flags,
2104         Syntax *syntax,
2105         MatchingRule *mr,
2106         struct berval *prefix,
2107         struct berval **values,
2108         struct berval ***keysp )
2109 {
2110         int i;
2111         struct berval **keys;
2112
2113         /* we should have at least one value at this point */
2114         assert( values != NULL && values[0] != NULL );
2115
2116         for( i=0; values[i] != NULL; i++ ) {
2117                 /* empty -- just count them */
2118         }
2119
2120         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
2121
2122         for( i=0; values[i] != NULL; i++ ) {
2123                 integerNormalize( syntax, values[i], &keys[i] );
2124         }
2125
2126         keys[i] = NULL;
2127         *keysp = keys;
2128         return LDAP_SUCCESS;
2129 }
2130
2131 /* Index generation function */
2132 int integerFilter(
2133         slap_mask_t use,
2134         slap_mask_t flags,
2135         Syntax *syntax,
2136         MatchingRule *mr,
2137         struct berval *prefix,
2138         void * assertValue,
2139         struct berval ***keysp )
2140 {
2141         struct berval **keys;
2142
2143         keys = ch_malloc( sizeof( struct berval * ) * 2 );
2144         integerNormalize( syntax, assertValue, &keys[0] );
2145         keys[1] = NULL;
2146         *keysp = keys;
2147
2148         return LDAP_SUCCESS;
2149 }
2150
2151
2152 static int
2153 countryStringValidate(
2154         Syntax *syntax,
2155         struct berval *val )
2156 {
2157         if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2158
2159         if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2160                 return LDAP_INVALID_SYNTAX;
2161         }
2162         if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2163                 return LDAP_INVALID_SYNTAX;
2164         }
2165
2166         return LDAP_SUCCESS;
2167 }
2168
2169 static int
2170 printableStringValidate(
2171         Syntax *syntax,
2172         struct berval *val )
2173 {
2174         ber_len_t i;
2175
2176         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2177
2178         for(i=0; i < val->bv_len; i++) {
2179                 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2180                         return LDAP_INVALID_SYNTAX;
2181                 }
2182         }
2183
2184         return LDAP_SUCCESS;
2185 }
2186
2187 static int
2188 printablesStringValidate(
2189         Syntax *syntax,
2190         struct berval *val )
2191 {
2192         ber_len_t i;
2193
2194         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2195
2196         for(i=0; i < val->bv_len; i++) {
2197                 if( !SLAP_PRINTABLES(val->bv_val[i]) ) {
2198                         return LDAP_INVALID_SYNTAX;
2199                 }
2200         }
2201
2202         return LDAP_SUCCESS;
2203 }
2204
2205 static int
2206 IA5StringValidate(
2207         Syntax *syntax,
2208         struct berval *val )
2209 {
2210         ber_len_t i;
2211
2212         if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2213
2214         for(i=0; i < val->bv_len; i++) {
2215                 if( !isascii(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
2216         }
2217
2218         return LDAP_SUCCESS;
2219 }
2220
2221 static int
2222 IA5StringNormalize(
2223         Syntax *syntax,
2224         struct berval *val,
2225         struct berval **normalized )
2226 {
2227         struct berval *newval;
2228         char *p, *q;
2229
2230         newval = ch_malloc( sizeof( struct berval ) );
2231
2232         p = val->bv_val;
2233
2234         /* Ignore initial whitespace */
2235         while ( ASCII_SPACE( *p ) ) {
2236                 p++;
2237         }
2238
2239         if( *p == '\0' ) {
2240                 ch_free( newval );
2241                 return LDAP_INVALID_SYNTAX;
2242         }
2243
2244         newval->bv_val = ch_strdup( p );
2245         p = q = newval->bv_val;
2246
2247         while ( *p ) {
2248                 if ( ASCII_SPACE( *p ) ) {
2249                         *q++ = *p++;
2250
2251                         /* Ignore the extra whitespace */
2252                         while ( ASCII_SPACE( *p ) ) {
2253                                 p++;
2254                         }
2255                 } else {
2256                         *q++ = *p++;
2257                 }
2258         }
2259
2260         assert( *newval->bv_val );
2261         assert( newval->bv_val < p );
2262         assert( q <= p );
2263
2264         /* cannot start with a space */
2265         assert( !ASCII_SPACE(*newval->bv_val) );
2266
2267         /*
2268          * If the string ended in space, backup the pointer one
2269          * position.  One is enough because the above loop collapsed
2270          * all whitespace to a single space.
2271          */
2272
2273         if ( ASCII_SPACE( q[-1] ) ) {
2274                 --q;
2275         }
2276
2277         /* cannot end with a space */
2278         assert( !ASCII_SPACE( q[-1] ) );
2279
2280         /* null terminate */
2281         *q = '\0';
2282
2283         newval->bv_len = q - newval->bv_val;
2284         *normalized = newval;
2285
2286         return LDAP_SUCCESS;
2287 }
2288
2289 static int
2290 caseExactIA5Match(
2291         int *matchp,
2292         slap_mask_t flags,
2293         Syntax *syntax,
2294         MatchingRule *mr,
2295         struct berval *value,
2296         void *assertedValue )
2297 {
2298         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2299
2300         if( match == 0 ) {
2301                 match = strncmp( value->bv_val,
2302                         ((struct berval *) assertedValue)->bv_val,
2303                         value->bv_len );
2304         }
2305
2306         *matchp = match;
2307         return LDAP_SUCCESS;
2308 }
2309
2310 static int
2311 caseExactIA5SubstringsMatch(
2312         int *matchp,
2313         slap_mask_t flags,
2314         Syntax *syntax,
2315         MatchingRule *mr,
2316         struct berval *value,
2317         void *assertedValue )
2318 {
2319         int match = 0;
2320         SubstringsAssertion *sub = assertedValue;
2321         struct berval left = *value;
2322         int i;
2323         ber_len_t inlen=0;
2324
2325         /* Add up asserted input length */
2326         if( sub->sa_initial ) {
2327                 inlen += sub->sa_initial->bv_len;
2328         }
2329         if( sub->sa_any ) {
2330                 for(i=0; sub->sa_any[i] != NULL; i++) {
2331                         inlen += sub->sa_any[i]->bv_len;
2332                 }
2333         }
2334         if( sub->sa_final ) {
2335                 inlen += sub->sa_final->bv_len;
2336         }
2337
2338         if( sub->sa_initial ) {
2339                 if( inlen > left.bv_len ) {
2340                         match = 1;
2341                         goto done;
2342                 }
2343
2344                 match = strncmp( sub->sa_initial->bv_val, left.bv_val,
2345                         sub->sa_initial->bv_len );
2346
2347                 if( match != 0 ) {
2348                         goto done;
2349                 }
2350
2351                 left.bv_val += sub->sa_initial->bv_len;
2352                 left.bv_len -= sub->sa_initial->bv_len;
2353                 inlen -= sub->sa_initial->bv_len;
2354         }
2355
2356         if( sub->sa_final ) {
2357                 if( inlen > left.bv_len ) {
2358                         match = 1;
2359                         goto done;
2360                 }
2361
2362                 match = strncmp( sub->sa_final->bv_val,
2363                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
2364                         sub->sa_final->bv_len );
2365
2366                 if( match != 0 ) {
2367                         goto done;
2368                 }
2369
2370                 left.bv_len -= sub->sa_final->bv_len;
2371                 inlen -= sub->sa_final->bv_len;
2372         }
2373
2374         if( sub->sa_any ) {
2375                 for(i=0; sub->sa_any[i]; i++) {
2376                         ber_len_t idx;
2377                         char *p;
2378
2379 retry:
2380                         if( inlen > left.bv_len ) {
2381                                 /* not enough length */
2382                                 match = 1;
2383                                 goto done;
2384                         }
2385
2386                         if( sub->sa_any[i]->bv_len == 0 ) {
2387                                 continue;
2388                         }
2389
2390                         p = strchr( left.bv_val, *sub->sa_any[i]->bv_val );
2391
2392                         if( p == NULL ) {
2393                                 match = 1;
2394                                 goto done;
2395                         }
2396
2397                         idx = p - left.bv_val;
2398                         assert( idx < left.bv_len );
2399
2400                         if( idx >= left.bv_len ) {
2401                                 /* this shouldn't happen */
2402                                 return LDAP_OTHER;
2403                         }
2404
2405                         left.bv_val = p;
2406                         left.bv_len -= idx;
2407
2408                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
2409                                 /* not enough left */
2410                                 match = 1;
2411                                 goto done;
2412                         }
2413
2414                         match = strncmp( left.bv_val,
2415                                 sub->sa_any[i]->bv_val,
2416                                 sub->sa_any[i]->bv_len );
2417
2418                         if( match != 0 ) {
2419                                 left.bv_val++;
2420                                 left.bv_len--;
2421                                 goto retry;
2422                         }
2423
2424                         left.bv_val += sub->sa_any[i]->bv_len;
2425                         left.bv_len -= sub->sa_any[i]->bv_len;
2426                         inlen -= sub->sa_any[i]->bv_len;
2427                 }
2428         }
2429
2430 done:
2431         *matchp = match;
2432         return LDAP_SUCCESS;
2433 }
2434
2435 /* Index generation function */
2436 int caseExactIA5Indexer(
2437         slap_mask_t use,
2438         slap_mask_t flags,
2439         Syntax *syntax,
2440         MatchingRule *mr,
2441         struct berval *prefix,
2442         struct berval **values,
2443         struct berval ***keysp )
2444 {
2445         int i;
2446         size_t slen, mlen;
2447         struct berval **keys;
2448         HASH_CONTEXT   HASHcontext;
2449         unsigned char   HASHdigest[HASH_BYTES];
2450         struct berval digest;
2451         digest.bv_val = HASHdigest;
2452         digest.bv_len = sizeof(HASHdigest);
2453
2454         for( i=0; values[i] != NULL; i++ ) {
2455                 /* empty - just count them */
2456         }
2457
2458         /* we should have at least one value at this point */
2459         assert( i > 0 );
2460
2461         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
2462
2463         slen = strlen( syntax->ssyn_oid );
2464         mlen = strlen( mr->smr_oid );
2465
2466         for( i=0; values[i] != NULL; i++ ) {
2467                 struct berval *value = values[i];
2468
2469                 HASH_Init( &HASHcontext );
2470                 if( prefix != NULL && prefix->bv_len > 0 ) {
2471                         HASH_Update( &HASHcontext,
2472                                 prefix->bv_val, prefix->bv_len );
2473                 }
2474                 HASH_Update( &HASHcontext,
2475                         syntax->ssyn_oid, slen );
2476                 HASH_Update( &HASHcontext,
2477                         mr->smr_oid, mlen );
2478                 HASH_Update( &HASHcontext,
2479                         value->bv_val, value->bv_len );
2480                 HASH_Final( HASHdigest, &HASHcontext );
2481
2482                 keys[i] = ber_bvdup( &digest );
2483         }
2484
2485         keys[i] = NULL;
2486         *keysp = keys;
2487         return LDAP_SUCCESS;
2488 }
2489
2490 /* Index generation function */
2491 int caseExactIA5Filter(
2492         slap_mask_t use,
2493         slap_mask_t flags,
2494         Syntax *syntax,
2495         MatchingRule *mr,
2496         struct berval *prefix,
2497         void * assertValue,
2498         struct berval ***keysp )
2499 {
2500         size_t slen, mlen;
2501         struct berval **keys;
2502         HASH_CONTEXT   HASHcontext;
2503         unsigned char   HASHdigest[HASH_BYTES];
2504         struct berval *value;
2505         struct berval digest;
2506         digest.bv_val = HASHdigest;
2507         digest.bv_len = sizeof(HASHdigest);
2508
2509         slen = strlen( syntax->ssyn_oid );
2510         mlen = strlen( mr->smr_oid );
2511
2512         value = (struct berval *) assertValue;
2513
2514         keys = ch_malloc( sizeof( struct berval * ) * 2 );
2515
2516         HASH_Init( &HASHcontext );
2517         if( prefix != NULL && prefix->bv_len > 0 ) {
2518                 HASH_Update( &HASHcontext,
2519                         prefix->bv_val, prefix->bv_len );
2520         }
2521         HASH_Update( &HASHcontext,
2522                 syntax->ssyn_oid, slen );
2523         HASH_Update( &HASHcontext,
2524                 mr->smr_oid, mlen );
2525         HASH_Update( &HASHcontext,
2526                 value->bv_val, value->bv_len );
2527         HASH_Final( HASHdigest, &HASHcontext );
2528
2529         keys[0] = ber_bvdup( &digest );
2530         keys[1] = NULL;
2531
2532         *keysp = keys;
2533         return LDAP_SUCCESS;
2534 }
2535
2536 /* Substrings Index generation function */
2537 int caseExactIA5SubstringsIndexer(
2538         slap_mask_t use,
2539         slap_mask_t flags,
2540         Syntax *syntax,
2541         MatchingRule *mr,
2542         struct berval *prefix,
2543         struct berval **values,
2544         struct berval ***keysp )
2545 {
2546         ber_len_t i, nkeys;
2547         size_t slen, mlen;
2548         struct berval **keys;
2549         HASH_CONTEXT   HASHcontext;
2550         unsigned char   HASHdigest[HASH_BYTES];
2551         struct berval digest;
2552         digest.bv_val = HASHdigest;
2553         digest.bv_len = sizeof(HASHdigest);
2554
2555         /* we should have at least one value at this point */
2556         assert( values != NULL && values[0] != NULL );
2557
2558         nkeys=0;
2559         for( i=0; values[i] != NULL; i++ ) {
2560                 /* count number of indices to generate */
2561                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2562                         continue;
2563                 }
2564
2565                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2566                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2567                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2568                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2569                         } else {
2570                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2571                         }
2572                 }
2573
2574                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2575                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2576                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2577                         }
2578                 }
2579
2580                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2581                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2582                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2583                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2584                         } else {
2585                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2586                         }
2587                 }
2588         }
2589
2590         if( nkeys == 0 ) {
2591                 /* no keys to generate */
2592                 *keysp = NULL;
2593                 return LDAP_SUCCESS;
2594         }
2595
2596         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2597
2598         slen = strlen( syntax->ssyn_oid );
2599         mlen = strlen( mr->smr_oid );
2600
2601         nkeys=0;
2602         for( i=0; values[i] != NULL; i++ ) {
2603                 ber_len_t j,max;
2604                 struct berval *value;
2605
2606                 value = values[i];
2607                 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2608
2609                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2610                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2611                 {
2612                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
2613                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2614
2615                         for( j=0; j<max; j++ ) {
2616                                 HASH_Init( &HASHcontext );
2617                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2618                                         HASH_Update( &HASHcontext,
2619                                                 prefix->bv_val, prefix->bv_len );
2620                                 }
2621
2622                                 HASH_Update( &HASHcontext,
2623                                         &pre, sizeof( pre ) );
2624                                 HASH_Update( &HASHcontext,
2625                                         syntax->ssyn_oid, slen );
2626                                 HASH_Update( &HASHcontext,
2627                                         mr->smr_oid, mlen );
2628                                 HASH_Update( &HASHcontext,
2629                                         &value->bv_val[j],
2630                                         SLAP_INDEX_SUBSTR_MAXLEN );
2631                                 HASH_Final( HASHdigest, &HASHcontext );
2632
2633                                 keys[nkeys++] = ber_bvdup( &digest );
2634                         }
2635                 }
2636
2637                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2638                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2639
2640                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2641                         char pre;
2642
2643                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2644                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2645                                 HASH_Init( &HASHcontext );
2646                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2647                                         HASH_Update( &HASHcontext,
2648                                                 prefix->bv_val, prefix->bv_len );
2649                                 }
2650                                 HASH_Update( &HASHcontext,
2651                                         &pre, sizeof( pre ) );
2652                                 HASH_Update( &HASHcontext,
2653                                         syntax->ssyn_oid, slen );
2654                                 HASH_Update( &HASHcontext,
2655                                         mr->smr_oid, mlen );
2656                                 HASH_Update( &HASHcontext,
2657                                         value->bv_val, j );
2658                                 HASH_Final( HASHdigest, &HASHcontext );
2659
2660                                 keys[nkeys++] = ber_bvdup( &digest );
2661                         }
2662
2663                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2664                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2665                                 HASH_Init( &HASHcontext );
2666                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2667                                         HASH_Update( &HASHcontext,
2668                                                 prefix->bv_val, prefix->bv_len );
2669                                 }
2670                                 HASH_Update( &HASHcontext,
2671                                         &pre, sizeof( pre ) );
2672                                 HASH_Update( &HASHcontext,
2673                                         syntax->ssyn_oid, slen );
2674                                 HASH_Update( &HASHcontext,
2675                                         mr->smr_oid, mlen );
2676                                 HASH_Update( &HASHcontext,
2677                                         &value->bv_val[value->bv_len-j], j );
2678                                 HASH_Final( HASHdigest, &HASHcontext );
2679
2680                                 keys[nkeys++] = ber_bvdup( &digest );
2681                         }
2682
2683                 }
2684         }
2685
2686         if( nkeys > 0 ) {
2687                 keys[nkeys] = NULL;
2688                 *keysp = keys;
2689         } else {
2690                 ch_free( keys );
2691                 *keysp = NULL;
2692         }
2693
2694         return LDAP_SUCCESS;
2695 }
2696
2697 int caseExactIA5SubstringsFilter(
2698         slap_mask_t use,
2699         slap_mask_t flags,
2700         Syntax *syntax,
2701         MatchingRule *mr,
2702         struct berval *prefix,
2703         void * assertValue,
2704         struct berval ***keysp )
2705 {
2706         SubstringsAssertion *sa = assertValue;
2707         char pre;
2708         ber_len_t nkeys = 0;
2709         size_t slen, mlen, klen;
2710         struct berval **keys;
2711         HASH_CONTEXT   HASHcontext;
2712         unsigned char   HASHdigest[HASH_BYTES];
2713         struct berval *value;
2714         struct berval digest;
2715
2716         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
2717                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2718         {
2719                 nkeys++;
2720         }
2721
2722         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2723                 ber_len_t i;
2724                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2725                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2726                                 /* don't bother accounting for stepping */
2727                                 nkeys += sa->sa_any[i]->bv_len -
2728                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2729                         }
2730                 }
2731         }
2732
2733         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
2734                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2735         {
2736                 nkeys++;
2737         }
2738
2739         if( nkeys == 0 ) {
2740                 *keysp = NULL;
2741                 return LDAP_SUCCESS;
2742         }
2743
2744         digest.bv_val = HASHdigest;
2745         digest.bv_len = sizeof(HASHdigest);
2746
2747         slen = strlen( syntax->ssyn_oid );
2748         mlen = strlen( mr->smr_oid );
2749
2750         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
2751         nkeys = 0;
2752
2753         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial != NULL &&
2754                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2755         {
2756                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2757                 value = sa->sa_initial;
2758
2759                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2760                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2761
2762                 HASH_Init( &HASHcontext );
2763                 if( prefix != NULL && prefix->bv_len > 0 ) {
2764                         HASH_Update( &HASHcontext,
2765                                 prefix->bv_val, prefix->bv_len );
2766                 }
2767                 HASH_Update( &HASHcontext,
2768                         &pre, sizeof( pre ) );
2769                 HASH_Update( &HASHcontext,
2770                         syntax->ssyn_oid, slen );
2771                 HASH_Update( &HASHcontext,
2772                         mr->smr_oid, mlen );
2773                 HASH_Update( &HASHcontext,
2774                         value->bv_val, klen );
2775                 HASH_Final( HASHdigest, &HASHcontext );
2776
2777                 keys[nkeys++] = ber_bvdup( &digest );
2778         }
2779
2780         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2781                 ber_len_t i, j;
2782                 pre = SLAP_INDEX_SUBSTR_PREFIX;
2783                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2784
2785                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
2786                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2787                                 continue;
2788                         }
2789
2790                         value = sa->sa_any[i];
2791
2792                         for(j=0;
2793                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2794                                 j += SLAP_INDEX_SUBSTR_STEP )
2795                         {
2796                                 HASH_Init( &HASHcontext );
2797                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2798                                         HASH_Update( &HASHcontext,
2799                                                 prefix->bv_val, prefix->bv_len );
2800                                 }
2801                                 HASH_Update( &HASHcontext,
2802                                         &pre, sizeof( pre ) );
2803                                 HASH_Update( &HASHcontext,
2804                                         syntax->ssyn_oid, slen );
2805                                 HASH_Update( &HASHcontext,
2806                                         mr->smr_oid, mlen );
2807                                 HASH_Update( &HASHcontext,
2808                                         &value->bv_val[j], klen ); 
2809                                 HASH_Final( HASHdigest, &HASHcontext );
2810
2811                                 keys[nkeys++] = ber_bvdup( &digest );
2812                         }
2813                 }
2814         }
2815
2816         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final != NULL &&
2817                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2818         {
2819                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2820                 value = sa->sa_final;
2821
2822                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2823                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2824
2825                 HASH_Init( &HASHcontext );
2826                 if( prefix != NULL && prefix->bv_len > 0 ) {
2827                         HASH_Update( &HASHcontext,
2828                                 prefix->bv_val, prefix->bv_len );
2829                 }
2830                 HASH_Update( &HASHcontext,
2831                         &pre, sizeof( pre ) );
2832                 HASH_Update( &HASHcontext,
2833                         syntax->ssyn_oid, slen );
2834                 HASH_Update( &HASHcontext,
2835                         mr->smr_oid, mlen );
2836                 HASH_Update( &HASHcontext,
2837                         &value->bv_val[value->bv_len-klen], klen );
2838                 HASH_Final( HASHdigest, &HASHcontext );
2839
2840                 keys[nkeys++] = ber_bvdup( &digest );
2841         }
2842
2843         if( nkeys > 0 ) {
2844                 keys[nkeys] = NULL;
2845                 *keysp = keys;
2846         } else {
2847                 ch_free( keys );
2848                 *keysp = NULL;
2849         }
2850
2851         return LDAP_SUCCESS;
2852 }
2853         
2854 static int
2855 caseIgnoreIA5Match(
2856         int *matchp,
2857         slap_mask_t flags,
2858         Syntax *syntax,
2859         MatchingRule *mr,
2860         struct berval *value,
2861         void *assertedValue )
2862 {
2863         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2864
2865         if( match == 0 && value->bv_len ) {
2866                 match = strncasecmp( value->bv_val,
2867                         ((struct berval *) assertedValue)->bv_val,
2868                         value->bv_len );
2869         }
2870
2871         *matchp = match;
2872         return LDAP_SUCCESS;
2873 }
2874
2875 static int
2876 caseIgnoreIA5SubstringsMatch(
2877         int *matchp,
2878         slap_mask_t flags,
2879         Syntax *syntax,
2880         MatchingRule *mr,
2881         struct berval *value,
2882         void *assertedValue )
2883 {
2884         int match = 0;
2885         SubstringsAssertion *sub = assertedValue;
2886         struct berval left = *value;
2887         int i;
2888         ber_len_t inlen=0;
2889
2890         /* Add up asserted input length */
2891         if( sub->sa_initial ) {
2892                 inlen += sub->sa_initial->bv_len;
2893         }
2894         if( sub->sa_any ) {
2895                 for(i=0; sub->sa_any[i] != NULL; i++) {
2896                         inlen += sub->sa_any[i]->bv_len;
2897                 }
2898         }
2899         if( sub->sa_final ) {
2900                 inlen += sub->sa_final->bv_len;
2901         }
2902
2903         if( sub->sa_initial ) {
2904                 if( inlen > left.bv_len ) {
2905                         match = 1;
2906                         goto done;
2907                 }
2908
2909                 match = strncasecmp( sub->sa_initial->bv_val, left.bv_val,
2910                         sub->sa_initial->bv_len );
2911
2912                 if( match != 0 ) {
2913                         goto done;
2914                 }
2915
2916                 left.bv_val += sub->sa_initial->bv_len;
2917                 left.bv_len -= sub->sa_initial->bv_len;
2918                 inlen -= sub->sa_initial->bv_len;
2919         }
2920
2921         if( sub->sa_final ) {
2922                 if( inlen > left.bv_len ) {
2923                         match = 1;
2924                         goto done;
2925                 }
2926
2927                 match = strncasecmp( sub->sa_final->bv_val,
2928                         &left.bv_val[left.bv_len - sub->sa_final->bv_len],
2929                         sub->sa_final->bv_len );
2930
2931                 if( match != 0 ) {
2932                         goto done;
2933                 }
2934
2935                 left.bv_len -= sub->sa_final->bv_len;
2936                 inlen -= sub->sa_final->bv_len;
2937         }
2938
2939         if( sub->sa_any ) {
2940                 for(i=0; sub->sa_any[i]; i++) {
2941                         ber_len_t idx;
2942                         char *p;
2943
2944 retry:
2945                         if( inlen > left.bv_len ) {
2946                                 /* not enough length */
2947                                 match = 1;
2948                                 goto done;
2949                         }
2950
2951                         if( sub->sa_any[i]->bv_len == 0 ) {
2952                                 continue;
2953                         }
2954
2955                         p = strcasechr( left.bv_val, *sub->sa_any[i]->bv_val );
2956
2957                         if( p == NULL ) {
2958                                 match = 1;
2959                                 goto done;
2960                         }
2961
2962                         idx = p - left.bv_val;
2963                         assert( idx < left.bv_len );
2964
2965                         if( idx >= left.bv_len ) {
2966                                 /* this shouldn't happen */
2967                                 return LDAP_OTHER;
2968                         }
2969
2970                         left.bv_val = p;
2971                         left.bv_len -= idx;
2972
2973                         if( sub->sa_any[i]->bv_len > left.bv_len ) {
2974                                 /* not enough left */
2975                                 match = 1;
2976                                 goto done;
2977                         }
2978
2979                         match = strncasecmp( left.bv_val,
2980                                 sub->sa_any[i]->bv_val,
2981                                 sub->sa_any[i]->bv_len );
2982
2983                         if( match != 0 ) {
2984                                 left.bv_val++;
2985                                 left.bv_len--;
2986
2987                                 goto retry;
2988                         }
2989
2990                         left.bv_val += sub->sa_any[i]->bv_len;
2991                         left.bv_len -= sub->sa_any[i]->bv_len;
2992                         inlen -= sub->sa_any[i]->bv_len;
2993                 }
2994         }
2995
2996 done:
2997         *matchp = match;
2998         return LDAP_SUCCESS;
2999 }
3000
3001 /* Index generation function */
3002 int caseIgnoreIA5Indexer(
3003         slap_mask_t use,
3004         slap_mask_t flags,
3005         Syntax *syntax,
3006         MatchingRule *mr,
3007         struct berval *prefix,
3008         struct berval **values,
3009         struct berval ***keysp )
3010 {
3011         int i;
3012         size_t slen, mlen;
3013         struct berval **keys;
3014         HASH_CONTEXT   HASHcontext;
3015         unsigned char   HASHdigest[HASH_BYTES];
3016         struct berval digest;
3017         digest.bv_val = HASHdigest;
3018         digest.bv_len = sizeof(HASHdigest);
3019
3020         /* we should have at least one value at this point */
3021         assert( values != NULL && values[0] != NULL );
3022
3023         for( i=0; values[i] != NULL; i++ ) {
3024                 /* just count them */
3025         }
3026
3027         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
3028
3029         slen = strlen( syntax->ssyn_oid );
3030         mlen = strlen( mr->smr_oid );
3031
3032         for( i=0; values[i] != NULL; i++ ) {
3033                 struct berval *value = ber_bvdup( values[i] );
3034                 ldap_pvt_str2upper( value->bv_val );
3035
3036                 HASH_Init( &HASHcontext );
3037                 if( prefix != NULL && prefix->bv_len > 0 ) {
3038                         HASH_Update( &HASHcontext,
3039                                 prefix->bv_val, prefix->bv_len );
3040                 }
3041                 HASH_Update( &HASHcontext,
3042                         syntax->ssyn_oid, slen );
3043                 HASH_Update( &HASHcontext,
3044                         mr->smr_oid, mlen );
3045                 HASH_Update( &HASHcontext,
3046                         value->bv_val, value->bv_len );
3047                 HASH_Final( HASHdigest, &HASHcontext );
3048
3049                 ber_bvfree( value );
3050
3051                 keys[i] = ber_bvdup( &digest );
3052         }
3053
3054         keys[i] = NULL;
3055         *keysp = keys;
3056         return LDAP_SUCCESS;
3057 }
3058
3059 /* Index generation function */
3060 int caseIgnoreIA5Filter(
3061         slap_mask_t use,
3062         slap_mask_t flags,
3063         Syntax *syntax,
3064         MatchingRule *mr,
3065         struct berval *prefix,
3066         void * assertValue,
3067         struct berval ***keysp )
3068 {
3069         size_t slen, mlen;
3070         struct berval **keys;
3071         HASH_CONTEXT   HASHcontext;
3072         unsigned char   HASHdigest[HASH_BYTES];
3073         struct berval *value;
3074         struct berval digest;
3075         digest.bv_val = HASHdigest;
3076         digest.bv_len = sizeof(HASHdigest);
3077
3078         slen = strlen( syntax->ssyn_oid );
3079         mlen = strlen( mr->smr_oid );
3080
3081         value = ber_bvdup( (struct berval *) assertValue );
3082         ldap_pvt_str2upper( value->bv_val );
3083
3084         keys = ch_malloc( sizeof( struct berval * ) * 2 );
3085
3086         HASH_Init( &HASHcontext );
3087         if( prefix != NULL && prefix->bv_len > 0 ) {
3088                 HASH_Update( &HASHcontext,
3089                         prefix->bv_val, prefix->bv_len );
3090         }
3091         HASH_Update( &HASHcontext,
3092                 syntax->ssyn_oid, slen );
3093         HASH_Update( &HASHcontext,
3094                 mr->smr_oid, mlen );
3095         HASH_Update( &HASHcontext,
3096                 value->bv_val, value->bv_len );
3097         HASH_Final( HASHdigest, &HASHcontext );
3098
3099         keys[0] = ber_bvdup( &digest );
3100         keys[1] = NULL;
3101
3102         ber_bvfree( value );
3103
3104         *keysp = keys;
3105
3106         return LDAP_SUCCESS;
3107 }
3108
3109 /* Substrings Index generation function */
3110 int caseIgnoreIA5SubstringsIndexer(
3111         slap_mask_t use,
3112         slap_mask_t flags,
3113         Syntax *syntax,
3114         MatchingRule *mr,
3115         struct berval *prefix,
3116         struct berval **values,
3117         struct berval ***keysp )
3118 {
3119         ber_len_t i, nkeys;
3120         size_t slen, mlen;
3121         struct berval **keys;
3122         HASH_CONTEXT   HASHcontext;
3123         unsigned char   HASHdigest[HASH_BYTES];
3124         struct berval digest;
3125         digest.bv_val = HASHdigest;
3126         digest.bv_len = sizeof(HASHdigest);
3127
3128         /* we should have at least one value at this point */
3129         assert( values != NULL && values[0] != NULL );
3130
3131         nkeys=0;
3132         for( i=0; values[i] != NULL; i++ ) {
3133                 /* count number of indices to generate */
3134                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3135                         continue;
3136                 }
3137
3138                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3139                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3140                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3141                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3142                         } else {
3143                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3144                         }
3145                 }
3146
3147                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3148                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3149                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3150                         }
3151                 }
3152
3153                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3154                         if( values[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3155                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3156                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3157                         } else {
3158                                 nkeys += values[i]->bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3159                         }
3160                 }
3161         }
3162
3163         if( nkeys == 0 ) {
3164                 /* no keys to generate */
3165                 *keysp = NULL;
3166                 return LDAP_SUCCESS;
3167         }
3168
3169         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
3170
3171         slen = strlen( syntax->ssyn_oid );
3172         mlen = strlen( mr->smr_oid );
3173
3174         nkeys=0;
3175         for( i=0; values[i] != NULL; i++ ) {
3176                 int j,max;
3177                 struct berval *value;
3178
3179                 if( values[i]->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3180
3181                 value = ber_bvdup( values[i] );
3182                 ldap_pvt_str2upper( value->bv_val );
3183
3184                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3185                         ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3186                 {
3187                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
3188                         max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3189
3190                         for( j=0; j<max; j++ ) {
3191                                 HASH_Init( &HASHcontext );
3192                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3193                                         HASH_Update( &HASHcontext,
3194                                                 prefix->bv_val, prefix->bv_len );
3195                                 }
3196
3197                                 HASH_Update( &HASHcontext,
3198                                         &pre, sizeof( pre ) );
3199                                 HASH_Update( &HASHcontext,
3200                                         syntax->ssyn_oid, slen );
3201                                 HASH_Update( &HASHcontext,
3202                                         mr->smr_oid, mlen );
3203                                 HASH_Update( &HASHcontext,
3204                                         &value->bv_val[j],
3205                                         SLAP_INDEX_SUBSTR_MAXLEN );
3206                                 HASH_Final( HASHdigest, &HASHcontext );
3207
3208                                 keys[nkeys++] = ber_bvdup( &digest );
3209                         }
3210                 }
3211
3212                 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3213                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3214
3215                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3216                         char pre;
3217
3218                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3219                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3220                                 HASH_Init( &HASHcontext );
3221                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3222                                         HASH_Update( &HASHcontext,
3223                                                 prefix->bv_val, prefix->bv_len );
3224                                 }
3225                                 HASH_Update( &HASHcontext,
3226                                         &pre, sizeof( pre ) );
3227                                 HASH_Update( &HASHcontext,
3228                                         syntax->ssyn_oid, slen );
3229                                 HASH_Update( &HASHcontext,
3230                                         mr->smr_oid, mlen );
3231                                 HASH_Update( &HASHcontext,
3232                                         value->bv_val, j );
3233                                 HASH_Final( HASHdigest, &HASHcontext );
3234
3235                                 keys[nkeys++] = ber_bvdup( &digest );
3236                         }
3237
3238                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3239                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3240                                 HASH_Init( &HASHcontext );
3241                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3242                                         HASH_Update( &HASHcontext,
3243                                                 prefix->bv_val, prefix->bv_len );
3244                                 }
3245                                 HASH_Update( &HASHcontext,
3246                                         &pre, sizeof( pre ) );
3247                                 HASH_Update( &HASHcontext,
3248                                         syntax->ssyn_oid, slen );
3249                                 HASH_Update( &HASHcontext,
3250                                         mr->smr_oid, mlen );
3251                                 HASH_Update( &HASHcontext,
3252                                         &value->bv_val[value->bv_len-j], j );
3253                                 HASH_Final( HASHdigest, &HASHcontext );
3254
3255                                 keys[nkeys++] = ber_bvdup( &digest );
3256                         }
3257
3258                 }
3259
3260                 ber_bvfree( value );
3261         }
3262
3263         if( nkeys > 0 ) {
3264                 keys[nkeys] = NULL;
3265                 *keysp = keys;
3266         } else {
3267                 ch_free( keys );
3268                 *keysp = NULL;
3269         }
3270
3271         return LDAP_SUCCESS;
3272 }
3273
3274 int caseIgnoreIA5SubstringsFilter(
3275         slap_mask_t use,
3276         slap_mask_t flags,
3277         Syntax *syntax,
3278         MatchingRule *mr,
3279         struct berval *prefix,
3280         void * assertValue,
3281         struct berval ***keysp )
3282 {
3283         SubstringsAssertion *sa = assertValue;
3284         char pre;
3285         ber_len_t nkeys = 0;
3286         size_t slen, mlen, klen;
3287         struct berval **keys;
3288         HASH_CONTEXT   HASHcontext;
3289         unsigned char   HASHdigest[HASH_BYTES];
3290         struct berval *value;
3291         struct berval digest;
3292
3293         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
3294                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3295         {
3296                 nkeys++;
3297         }
3298
3299         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3300                 ber_len_t i;
3301                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3302                         if( sa->sa_any[i]->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3303                                 /* don't bother accounting for stepping */
3304                                 nkeys += sa->sa_any[i]->bv_len -
3305                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3306                         }
3307                 }
3308         }
3309
3310         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
3311                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3312         {
3313                 nkeys++;
3314         }
3315
3316         if( nkeys == 0 ) {
3317                 *keysp = NULL;
3318                 return LDAP_SUCCESS;
3319         }
3320
3321         digest.bv_val = HASHdigest;
3322         digest.bv_len = sizeof(HASHdigest);
3323
3324         slen = strlen( syntax->ssyn_oid );
3325         mlen = strlen( mr->smr_oid );
3326
3327         keys = ch_malloc( sizeof( struct berval * ) * (nkeys+1) );
3328         nkeys = 0;
3329
3330         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial != NULL &&
3331                 sa->sa_initial->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3332         {
3333                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3334                 value = ber_bvdup( sa->sa_initial );
3335                 ldap_pvt_str2upper( value->bv_val );
3336
3337                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3338                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3339
3340                 HASH_Init( &HASHcontext );
3341                 if( prefix != NULL && prefix->bv_len > 0 ) {
3342                         HASH_Update( &HASHcontext,
3343                                 prefix->bv_val, prefix->bv_len );
3344                 }
3345                 HASH_Update( &HASHcontext,
3346                         &pre, sizeof( pre ) );
3347                 HASH_Update( &HASHcontext,
3348                         syntax->ssyn_oid, slen );
3349                 HASH_Update( &HASHcontext,
3350                         mr->smr_oid, mlen );
3351                 HASH_Update( &HASHcontext,
3352                         value->bv_val, klen );
3353                 HASH_Final( HASHdigest, &HASHcontext );
3354
3355                 ber_bvfree( value );
3356                 keys[nkeys++] = ber_bvdup( &digest );
3357         }
3358
3359         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3360                 ber_len_t i, j;
3361                 pre = SLAP_INDEX_SUBSTR_PREFIX;
3362                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3363
3364                 for( i=0; sa->sa_any[i] != NULL; i++ ) {
3365                         if( sa->sa_any[i]->bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3366                                 continue;
3367                         }
3368
3369                         value = ber_bvdup( sa->sa_any[i] );
3370                         ldap_pvt_str2upper( value->bv_val );
3371
3372                         for(j=0;
3373                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3374                                 j += SLAP_INDEX_SUBSTR_STEP )
3375                         {
3376                                 HASH_Init( &HASHcontext );
3377                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3378                                         HASH_Update( &HASHcontext,
3379                                                 prefix->bv_val, prefix->bv_len );
3380                                 }
3381                                 HASH_Update( &HASHcontext,
3382                                         &pre, sizeof( pre ) );
3383                                 HASH_Update( &HASHcontext,
3384                                         syntax->ssyn_oid, slen );
3385                                 HASH_Update( &HASHcontext,
3386                                         mr->smr_oid, mlen );
3387                                 HASH_Update( &HASHcontext,
3388                                         &value->bv_val[j], klen );
3389                                 HASH_Final( HASHdigest, &HASHcontext );
3390
3391                                 keys[nkeys++] = ber_bvdup( &digest );
3392                         }
3393
3394                         ber_bvfree( value );
3395                 }
3396         }
3397
3398         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final != NULL &&
3399                 sa->sa_final->bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3400         {
3401                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3402                 value = ber_bvdup( sa->sa_final );
3403                 ldap_pvt_str2upper( value->bv_val );
3404
3405                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
3406                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
3407
3408                 HASH_Init( &HASHcontext );
3409                 if( prefix != NULL && prefix->bv_len > 0 ) {
3410                         HASH_Update( &HASHcontext,
3411                                 prefix->bv_val, prefix->bv_len );
3412                 }
3413                 HASH_Update( &HASHcontext,
3414                         &pre, sizeof( pre ) );
3415                 HASH_Update( &HASHcontext,
3416                         syntax->ssyn_oid, slen );
3417                 HASH_Update( &HASHcontext,
3418                         mr->smr_oid, mlen );
3419                 HASH_Update( &HASHcontext,
3420                         &value->bv_val[value->bv_len-klen], klen );
3421                 HASH_Final( HASHdigest, &HASHcontext );
3422
3423                 ber_bvfree( value );
3424                 keys[nkeys++] = ber_bvdup( &digest );
3425         }
3426
3427         if( nkeys > 0 ) {
3428                 keys[nkeys] = NULL;
3429                 *keysp = keys;
3430         } else {
3431                 ch_free( keys );
3432                 *keysp = NULL;
3433         }
3434
3435         return LDAP_SUCCESS;
3436 }
3437         
3438 static int
3439 numericStringValidate(
3440         Syntax *syntax,
3441         struct berval *in )
3442 {
3443         ber_len_t i;
3444
3445         for(i=0; i < in->bv_len; i++) {
3446                 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3447                         return LDAP_INVALID_SYNTAX;
3448                 }
3449         }
3450
3451         return LDAP_SUCCESS;
3452 }
3453
3454 static int
3455 numericStringNormalize(
3456         Syntax *syntax,
3457         struct berval *val,
3458         struct berval **normalized )
3459 {
3460         /* removal all spaces */
3461         struct berval *newval;
3462         char *p, *q;
3463
3464         newval = ch_malloc( sizeof( struct berval ) );
3465         newval->bv_val = ch_malloc( val->bv_len + 1 );
3466
3467         p = val->bv_val;
3468         q = newval->bv_val;
3469
3470         while ( *p ) {
3471                 if ( ASCII_SPACE( *p ) ) {
3472                         /* Ignore whitespace */
3473                         p++;
3474                 } else {
3475                         *q++ = *p++;
3476                 }
3477         }
3478
3479         /* we should have copied no more then is in val */
3480         assert( (q - newval->bv_val) <= (p - val->bv_val) );
3481
3482         /* null terminate */
3483         *q = '\0';
3484
3485         newval->bv_len = q - newval->bv_val;
3486         *normalized = newval;
3487
3488         return LDAP_SUCCESS;
3489 }
3490
3491 static int
3492 objectIdentifierFirstComponentMatch(
3493         int *matchp,
3494         slap_mask_t flags,
3495         Syntax *syntax,
3496         MatchingRule *mr,
3497         struct berval *value,
3498         void *assertedValue )
3499 {
3500         int rc = LDAP_SUCCESS;
3501         int match;
3502         struct berval *asserted = (struct berval *) assertedValue;
3503         ber_len_t i;
3504         struct berval oid;
3505
3506         if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3507                 return LDAP_INVALID_SYNTAX;
3508         }
3509
3510         /* trim leading white space */
3511         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3512                 /* empty */
3513         }
3514
3515         /* grab next word */
3516         oid.bv_val = &value->bv_val[i];
3517         oid.bv_len = value->bv_len - i;
3518         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3519                 /* empty */
3520         }
3521         oid.bv_len = i;
3522
3523         /* insert attributeTypes, objectclass check here */
3524         if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3525                 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3526
3527         } else {
3528                 char *stored = ch_malloc( oid.bv_len + 1 );
3529                 AC_MEMCPY( stored, oid.bv_val, oid.bv_len );
3530                 stored[oid.bv_len] = '\0';
3531
3532                 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3533                         MatchingRule *asserted_mr = mr_find( asserted->bv_val );
3534                         MatchingRule *stored_mr = mr_find( stored );
3535
3536                         if( asserted_mr == NULL ) {
3537                                 rc = SLAPD_COMPARE_UNDEFINED;
3538                         } else {
3539                                 match = asserted_mr != stored_mr;
3540                         }
3541
3542                 } else if ( !strcmp( syntax->ssyn_oid,
3543                         SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3544                 {
3545                         AttributeType *asserted_at = at_find( asserted->bv_val );
3546                         AttributeType *stored_at = at_find( stored );
3547
3548                         if( asserted_at == NULL ) {
3549                                 rc = SLAPD_COMPARE_UNDEFINED;
3550                         } else {
3551                                 match = asserted_at != stored_at;
3552                         }
3553
3554                 } else if ( !strcmp( syntax->ssyn_oid,
3555                         SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3556                 {
3557                         ObjectClass *asserted_oc = oc_find( asserted->bv_val );
3558                         ObjectClass *stored_oc = oc_find( stored );
3559
3560                         if( asserted_oc == NULL ) {
3561                                 rc = SLAPD_COMPARE_UNDEFINED;
3562                         } else {
3563                                 match = asserted_oc != stored_oc;
3564                         }
3565                 }
3566
3567                 ch_free( stored );
3568         }
3569
3570 #ifdef NEW_LOGGING
3571         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3572                    "objectIdentifierFirstComponentMatch: %d\n    %s\n    %s\n",
3573                    match, value->bv_val, asserted->bv_val ));
3574 #else
3575         Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3576                 "%d\n\t\"%s\"\n\t\"%s\"\n",
3577                 match, value->bv_val, asserted->bv_val );
3578 #endif
3579
3580
3581         if( rc == LDAP_SUCCESS ) *matchp = match;
3582         return rc;
3583 }
3584
3585 static int
3586 integerBitAndMatch(
3587         int *matchp,
3588         slap_mask_t flags,
3589         Syntax *syntax,
3590         MatchingRule *mr,
3591         struct berval *value,
3592         void *assertedValue )
3593 {
3594         long lValue, lAssertedValue;
3595
3596         /* safe to assume integers are NUL terminated? */
3597         lValue = strtoul(value->bv_val, NULL, 10);
3598         if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3599                 return LDAP_CONSTRAINT_VIOLATION;
3600
3601         lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3602         if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3603                 return LDAP_CONSTRAINT_VIOLATION;
3604
3605         *matchp = (lValue & lAssertedValue);
3606         return LDAP_SUCCESS;
3607 }
3608
3609 static int
3610 integerBitOrMatch(
3611         int *matchp,
3612         slap_mask_t flags,
3613         Syntax *syntax,
3614         MatchingRule *mr,
3615         struct berval *value,
3616         void *assertedValue )
3617 {
3618         long lValue, lAssertedValue;
3619
3620         /* safe to assume integers are NUL terminated? */
3621         lValue = strtoul(value->bv_val, NULL, 10);
3622         if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3623                 return LDAP_CONSTRAINT_VIOLATION;
3624
3625         lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3626         if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3627                 return LDAP_CONSTRAINT_VIOLATION;
3628
3629         *matchp = (lValue | lAssertedValue);
3630         return LDAP_SUCCESS;
3631 }
3632
3633 #ifdef HAVE_TLS
3634 #include <openssl/x509.h>
3635 #include <openssl/err.h>
3636 char digit[] = "0123456789";
3637
3638 /*
3639  * Next function returns a string representation of a ASN1_INTEGER.
3640  * It works for unlimited lengths.
3641  */
3642
3643 static struct berval *
3644 asn1_integer2str(ASN1_INTEGER *a)
3645 {
3646         char buf[256];
3647         char *p;
3648   
3649         /* We work backwards, make it fill from the end of buf */
3650         p = buf + sizeof(buf) - 1;
3651         *p = '\0';
3652
3653         if ( a == NULL || a->length == 0 ) {
3654                 *--p = '0';
3655         } else {
3656                 int i;
3657                 int n = a->length;
3658                 int base = 0;
3659                 unsigned int *copy;
3660
3661                 /* We want to preserve the original */
3662                 copy = ch_malloc(n*sizeof(unsigned int));
3663                 for (i = 0; i<n; i++) {
3664                         copy[i] = a->data[i];
3665                 }
3666
3667                 /* 
3668                  * base indicates the index of the most significant
3669                  * byte that might be nonzero.  When it goes off the
3670                  * end, we now there is nothing left to do.
3671                  */
3672                 while (base < n) {
3673                         unsigned int carry;
3674
3675                         carry = 0;
3676                         for (i = base; i<n; i++ ) {
3677                                 copy[i] += carry*256;
3678                                 carry = copy[i] % 10;
3679                                 copy[i] /= 10;
3680                         }
3681                         if (p <= buf+1) {
3682                                 /*
3683                                  * Way too large, we need to leave
3684                                  * room for sign if negative
3685                                  */
3686                                 free(copy);
3687                                 return NULL;
3688                         }
3689                         *--p = digit[carry];
3690                         if (copy[base] == 0)
3691                                 base++;
3692                 }
3693                 free(copy);
3694         }
3695
3696         if ( a->type == V_ASN1_NEG_INTEGER ) {
3697                 *--p = '-';
3698         }
3699
3700         return ber_bvstrdup(p);
3701 }
3702
3703 /* Get a DN in RFC2253 format from a X509_NAME internal struct */
3704 static struct berval *
3705 dn_openssl2ldap(X509_NAME *name)
3706 {
3707         char issuer_dn[1024];
3708         BIO *bio;
3709
3710         bio = BIO_new(BIO_s_mem());
3711         if ( !bio ) {
3712 #ifdef NEW_LOGGING
3713                 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3714                            "dn_openssl2ldap: error creating BIO_s_mem: %s\n",
3715                            ERR_error_string(ERR_get_error(),NULL)));
3716 #else
3717                 Debug( LDAP_DEBUG_ARGS, "dn_openssl2ldap: "
3718                        "error creating BIO: %s\n",
3719                        ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3720 #endif
3721                 return NULL;
3722         }
3723         X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
3724
3725         BIO_gets(bio, issuer_dn, 1024);
3726
3727         BIO_free(bio);
3728         return ber_bvstrdup(issuer_dn);
3729 }
3730
3731 /*
3732  * Given a certificate in DER format, extract the corresponding
3733  * assertion value for certificateExactMatch
3734  */
3735 static int
3736 certificateExactConvert(
3737         struct berval * in,
3738         struct berval ** out )
3739 {
3740         X509 *xcert;
3741         unsigned char *p = in->bv_val;
3742         struct berval *serial;
3743         struct berval *issuer_dn;
3744         struct berval *bv_tmp;
3745
3746         xcert = d2i_X509(NULL, &p, in->bv_len);
3747         if ( !xcert ) {
3748 #ifdef NEW_LOGGING
3749                 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3750                            "certificateExactConvert: error parsing cert: %s\n",
3751                            ERR_error_string(ERR_get_error(),NULL)));
3752 #else
3753                 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3754                        "error parsing cert: %s\n",
3755                        ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3756 #endif
3757                 return LDAP_INVALID_SYNTAX;
3758         }
3759
3760         serial = asn1_integer2str(xcert->cert_info->serialNumber);
3761         if ( !serial ) {
3762                 X509_free(xcert);
3763                 return LDAP_INVALID_SYNTAX;
3764         }
3765         issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
3766         if ( !issuer_dn ) {
3767                 X509_free(xcert);
3768                 ber_bvfree(serial);
3769                 return LDAP_INVALID_SYNTAX;
3770         }
3771         /* Actually, dn_openssl2ldap returns in a normalized format, but
3772            it is different from our normalized format */
3773         bv_tmp = issuer_dn;
3774         if ( dnNormalize(NULL, bv_tmp, &issuer_dn) != LDAP_SUCCESS ) {
3775                 X509_free(xcert);
3776                 ber_bvfree(serial);
3777                 ber_bvfree(bv_tmp);
3778                 return LDAP_INVALID_SYNTAX;
3779         }
3780         ber_bvfree(bv_tmp);
3781
3782         X509_free(xcert);
3783
3784         *out = ch_malloc(sizeof(struct berval));
3785         (*out)->bv_len = serial->bv_len + 3 + issuer_dn->bv_len + 1;
3786         (*out)->bv_val = ch_malloc((*out)->bv_len);
3787         p = (*out)->bv_val;
3788         AC_MEMCPY(p, serial->bv_val, serial->bv_len);
3789         p += serial->bv_len;
3790         AC_MEMCPY(p, " $ ", 3);
3791         p += 3;
3792         AC_MEMCPY(p, issuer_dn->bv_val, issuer_dn->bv_len);
3793         p += issuer_dn->bv_len;
3794         *p++ = '\0';
3795
3796 #ifdef NEW_LOGGING
3797         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3798                    "certificateExactConvert: \n %s\n",
3799                    (*out)->bv_val));
3800 #else
3801         Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3802                 "\n\t\"%s\"\n",
3803                 (*out)->bv_val, NULL, NULL );
3804 #endif
3805
3806         ber_bvfree(serial);
3807         ber_bvfree(issuer_dn);
3808
3809         return LDAP_SUCCESS;
3810 }
3811
3812 static int
3813 serial_and_issuer_parse(
3814         struct berval *assertion,
3815         struct berval **serial,
3816         struct berval **issuer_dn
3817 )
3818 {
3819         char *begin;
3820         char *end;
3821         char *p;
3822         char *q;
3823
3824         begin = assertion->bv_val;
3825         end = assertion->bv_val+assertion->bv_len-1;
3826         for (p=begin; p<=end && *p != '$'; p++)
3827                 ;
3828         if ( p > end )
3829                 return LDAP_INVALID_SYNTAX;
3830
3831         /* p now points at the $ sign, now use begin and end to delimit the
3832            serial number */
3833         while (ASCII_SPACE(*begin))
3834                 begin++;
3835         end = p-1;
3836         while (ASCII_SPACE(*end))
3837                 end--;
3838
3839         q = ch_malloc( (end-begin+1)+1 );
3840         AC_MEMCPY( q, begin, end-begin+1 );
3841         q[end-begin+1] = '\0';
3842         *serial = ber_bvstr(q);
3843
3844         /* now extract the issuer, remember p was at the dollar sign */
3845         begin = p+1;
3846         end = assertion->bv_val+assertion->bv_len-1;
3847         while (ASCII_SPACE(*begin))
3848                 begin++;
3849         /* should we trim spaces at the end too? is it safe always? */
3850
3851         q = ch_malloc( (end-begin+1)+1 );
3852         AC_MEMCPY( q, begin, end-begin+1 );
3853         q[end-begin+1] = '\0';
3854         *issuer_dn = ber_bvstr(dn_normalize(q));
3855
3856         return LDAP_SUCCESS;
3857 }
3858
3859 static int
3860 certificateExactMatch(
3861         int *matchp,
3862         slap_mask_t flags,
3863         Syntax *syntax,
3864         MatchingRule *mr,
3865         struct berval *value,
3866         void *assertedValue )
3867 {
3868         X509 *xcert;
3869         unsigned char *p = value->bv_val;
3870         struct berval *serial;
3871         struct berval *issuer_dn;
3872         struct berval *asserted_serial;
3873         struct berval *asserted_issuer_dn;
3874         int ret;
3875
3876         xcert = d2i_X509(NULL, &p, value->bv_len);
3877         if ( !xcert ) {
3878 #ifdef NEW_LOGGING
3879                 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3880                            "certificateExactMatch: error parsing cert: %s\n",
3881                            ERR_error_string(ERR_get_error(),NULL)));
3882 #else
3883                 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3884                        "error parsing cert: %s\n",
3885                        ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3886 #endif
3887                 return LDAP_INVALID_SYNTAX;
3888         }
3889
3890         serial = asn1_integer2str(xcert->cert_info->serialNumber);
3891         issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
3892
3893         X509_free(xcert);
3894
3895         serial_and_issuer_parse(assertedValue,
3896                                 &asserted_serial,
3897                                 &asserted_issuer_dn);
3898
3899         ret = integerMatch(
3900                 matchp,
3901                 flags,
3902                 slap_schema.si_syn_integer,
3903                 slap_schema.si_mr_integerMatch,
3904                 serial,
3905                 asserted_serial);
3906         if ( ret == LDAP_SUCCESS ) {
3907                 if ( *matchp == 0 ) {
3908                         /* We need to normalize everything for dnMatch */
3909                         ret = dnMatch(
3910                                 matchp,
3911                                 flags,
3912                                 slap_schema.si_syn_distinguishedName,
3913                                 slap_schema.si_mr_distinguishedNameMatch,
3914                                 issuer_dn,
3915                                 asserted_issuer_dn);
3916                 }
3917         }
3918
3919 #ifdef NEW_LOGGING
3920         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3921                    "certificateExactMatch: %d\n  %s $ %s\n       %s $   %s\n",
3922                    *matchp, serial->bv_val, issuer_dn->bv_val,
3923                    asserted->serial->bv_val, asserted_issuer_dn->bv_val));
3924 #else
3925         Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3926                 "%d\n\t\"%s $ %s\"\n",
3927                 *matchp, serial->bv_val, issuer_dn->bv_val );
3928         Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3929                 asserted_serial->bv_val, asserted_issuer_dn->bv_val,
3930                 NULL );
3931 #endif
3932
3933         ber_bvfree(serial);
3934         ber_bvfree(issuer_dn);
3935         ber_bvfree(asserted_serial);
3936         ber_bvfree(asserted_issuer_dn);
3937
3938         return ret;
3939 }
3940
3941 /* 
3942  * Index generation function
3943  * We just index the serials, in most scenarios the issuer DN is one of
3944  * a very small set of values.
3945  */
3946 int certificateExactIndexer(
3947         slap_mask_t use,
3948         slap_mask_t flags,
3949         Syntax *syntax,
3950         MatchingRule *mr,
3951         struct berval *prefix,
3952         struct berval **values,
3953         struct berval ***keysp )
3954 {
3955         int i;
3956         struct berval **keys;
3957         X509 *xcert;
3958         unsigned char *p;
3959         struct berval * serial;
3960
3961         /* we should have at least one value at this point */
3962         assert( values != NULL && values[0] != NULL );
3963
3964         for( i=0; values[i] != NULL; i++ ) {
3965                 /* empty -- just count them */
3966         }
3967
3968         keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
3969
3970         for( i=0; values[i] != NULL; i++ ) {
3971                 p = values[i]->bv_val;
3972                 xcert = d2i_X509(NULL, &p, values[i]->bv_len);
3973                 if ( !xcert ) {
3974 #ifdef NEW_LOGGING
3975                         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3976                             "certificateExactIndexer: error parsing cert: %s\n",
3977                                 ERR_error_string(ERR_get_error(),NULL)));
3978 #else
3979                         Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3980                                "error parsing cert: %s\n",
3981                                ERR_error_string(ERR_get_error(),NULL),
3982                                NULL, NULL );
3983 #endif
3984                         /* Do we leak keys on error? */
3985                         return LDAP_INVALID_SYNTAX;
3986                 }
3987
3988                 serial = asn1_integer2str(xcert->cert_info->serialNumber);
3989                 X509_free(xcert);
3990                 integerNormalize( slap_schema.si_syn_integer,
3991                                   serial,
3992                                   &keys[i] );
3993                 ber_bvfree(serial);
3994 #ifdef NEW_LOGGING
3995                 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3996                            "certificateExactIndexer: returning: %s\n",
3997                            keys[i]->bv_val));
3998 #else
3999                 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
4000                        "returning: %s\n",
4001                        keys[i]->bv_val,
4002                        NULL, NULL );
4003 #endif
4004         }
4005
4006         keys[i] = NULL;
4007         *keysp = keys;
4008         return LDAP_SUCCESS;
4009 }
4010
4011 /* Index generation function */
4012 /* We think this is always called with a value in matching rule syntax */
4013 int certificateExactFilter(
4014         slap_mask_t use,
4015         slap_mask_t flags,
4016         Syntax *syntax,
4017         MatchingRule *mr,
4018         struct berval *prefix,
4019         void * assertValue,
4020         struct berval ***keysp )
4021 {
4022         struct berval **keys;
4023         struct berval *asserted_serial;
4024         struct berval *asserted_issuer_dn;
4025
4026         serial_and_issuer_parse(assertValue,
4027                                 &asserted_serial,
4028                                 &asserted_issuer_dn);
4029
4030         keys = ch_malloc( sizeof( struct berval * ) * 2 );
4031         integerNormalize( syntax, asserted_serial, &keys[0] );
4032         keys[1] = NULL;
4033         *keysp = keys;
4034
4035         ber_bvfree(asserted_serial);
4036         ber_bvfree(asserted_issuer_dn);
4037         return LDAP_SUCCESS;
4038 }
4039 #endif
4040
4041 static int
4042 check_time_syntax (struct berval *val,
4043         int start,
4044         int *parts)
4045 {
4046         static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
4047         static int mdays[2][12] = {
4048                 /* non-leap years */
4049                 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
4050                 /* leap years */
4051                 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
4052         };
4053         char *p, *e;
4054         int part, c, tzoffset, leapyear = 0 ;
4055
4056         if( val->bv_len == 0 ) {
4057                 return LDAP_INVALID_SYNTAX;
4058         }
4059
4060         p = (char *)val->bv_val;
4061         e = p + val->bv_len;
4062
4063         /* Ignore initial whitespace */
4064         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4065                 p++;
4066         }
4067
4068         if (e - p < 13 - (2 * start)) {
4069                 return LDAP_INVALID_SYNTAX;
4070         }
4071
4072         for (part = 0; part < 9; part++) {
4073                 parts[part] = 0;
4074         }
4075
4076         for (part = start; part < 7; part++) {
4077                 c = *p;
4078                 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
4079                         part++;
4080                         break;
4081                 }
4082                 p++;
4083                 c -= '0';
4084                 if (p == e) {
4085                         return LDAP_INVALID_SYNTAX;
4086                 }
4087                 if (c < 0 || c > 9) {
4088                         return LDAP_INVALID_SYNTAX;
4089                 }
4090                 parts[part] = c;
4091
4092                 c = *p++ - '0';
4093                 if (p == e) {
4094                         return LDAP_INVALID_SYNTAX;
4095                 }
4096                 if (c < 0 || c > 9) {
4097                         return LDAP_INVALID_SYNTAX;
4098                 }
4099                 parts[part] *= 10;
4100                 parts[part] += c;
4101
4102                 if (part == 2 || part == 3) {
4103                         parts[part]--;
4104                 }
4105                 if (parts[part] < 0) {
4106                         return LDAP_INVALID_SYNTAX;
4107                 }
4108                 if (parts[part] > ceiling[part]) {
4109                         return LDAP_INVALID_SYNTAX;
4110                 }
4111         }
4112
4113         /* leapyear check for the Gregorian calendar (year>1581) */
4114         if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
4115                 ((parts[0] % 4 == 0) && (parts[1] == 0)))
4116         {
4117                 leapyear = 1;
4118         }
4119
4120         if (parts[3] > mdays[leapyear][parts[2]]) {
4121                 return LDAP_INVALID_SYNTAX;
4122         }
4123         
4124         c = *p++;
4125         if (c == 'Z') {
4126                 tzoffset = 0; /* UTC */
4127         } else if (c != '+' && c != '-') {
4128                 return LDAP_INVALID_SYNTAX;
4129         } else {
4130                 if (c == '-') {
4131                         tzoffset = -1;
4132                 } else /* c == '+' */ {
4133                         tzoffset = 1;
4134                 }
4135
4136                 if (p > e - 4) {
4137                         return LDAP_INVALID_SYNTAX;
4138                 }
4139
4140                 for (part = 7; part < 9; part++) {
4141                         c = *p++ - '0';
4142                         if (c < 0 || c > 9) {
4143                                 return LDAP_INVALID_SYNTAX;
4144                         }
4145                         parts[part] = c;
4146
4147                         c = *p++ - '0';
4148                         if (c < 0 || c > 9) {
4149                                 return LDAP_INVALID_SYNTAX;
4150                         }
4151                         parts[part] *= 10;
4152                         parts[part] += c;
4153                         if (parts[part] < 0 || parts[part] > ceiling[part]) {
4154                                 return LDAP_INVALID_SYNTAX;
4155                         }
4156                 }
4157         }
4158
4159         /* Ignore trailing whitespace */
4160         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4161                 p++;
4162         }
4163         if (p != e) {
4164                 return LDAP_INVALID_SYNTAX;
4165         }
4166
4167         switch ( tzoffset ) {
4168         case -1: /* negativ offset to UTC, ie west of Greenwich  */
4169                 parts[4] += parts[7];
4170                 parts[5] += parts[8];
4171                 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4172                         if (part != 3) {
4173                                 c = ceiling[part];
4174                         } else {
4175                                 c = mdays[leapyear][parts[2]];
4176                         }
4177                         if (parts[part] > c) {
4178                                 parts[part] -= c + 1;
4179                                 parts[part - 1]++;
4180                         }
4181                 }
4182                 break;
4183         case 1: /* positive offset to UTC, ie east of Greenwich */
4184                 parts[4] -= parts[7];
4185                 parts[5] -= parts[8];
4186                 for (part = 6; --part > 0; ) {
4187                         if (part != 3) {
4188                                 c = ceiling[part];
4189                         } else {
4190                                 /* first arg to % needs to be non negativ */
4191                                 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4192                         }
4193                         if (parts[part] < 0) {
4194                                 parts[part] += c + 1;
4195                                 parts[part - 1]--;
4196                         }
4197                 }
4198                 break;
4199         case 0: /* already UTC */
4200                 break;
4201         }
4202
4203         return LDAP_SUCCESS;
4204 }
4205
4206 static int
4207 utcTimeNormalize(
4208         Syntax *syntax,
4209         struct berval *val,
4210         struct berval **normalized )
4211 {
4212         struct berval *out;
4213         int parts[9], rc;
4214
4215         rc = check_time_syntax(val, 1, parts);
4216         if (rc != LDAP_SUCCESS) {
4217                 return rc;
4218         }
4219
4220         *normalized = NULL;
4221         out = ch_malloc( sizeof(struct berval) );
4222         if( out == NULL ) {
4223                 return LBER_ERROR_MEMORY;
4224         }
4225
4226         out->bv_val = ch_malloc( 14 );
4227         if ( out->bv_val == NULL ) {
4228                 ch_free( out );
4229                 return LBER_ERROR_MEMORY;
4230         }
4231
4232         sprintf( out->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4233                 parts[1], parts[2] + 1, parts[3] + 1,
4234                 parts[4], parts[5], parts[6] );
4235         out->bv_len = 13;
4236         *normalized = out;
4237
4238         return LDAP_SUCCESS;
4239 }
4240
4241 static int
4242 utcTimeValidate(
4243         Syntax *syntax,
4244         struct berval *in )
4245 {
4246         int parts[9];
4247
4248         return check_time_syntax(in, 1, parts);
4249 }
4250
4251 static int
4252 generalizedTimeValidate(
4253         Syntax *syntax,
4254         struct berval *in )
4255 {
4256         int parts[9];
4257
4258         return check_time_syntax(in, 0, parts);
4259 }
4260
4261 static int
4262 generalizedTimeNormalize(
4263         Syntax *syntax,
4264         struct berval *val,
4265         struct berval **normalized )
4266 {
4267         struct berval *out;
4268         int parts[9], rc;
4269
4270         rc = check_time_syntax(val, 0, parts);
4271         if (rc != LDAP_SUCCESS) {
4272                 return rc;
4273         }
4274
4275         *normalized = NULL;
4276         out = ch_malloc( sizeof(struct berval) );
4277         if( out == NULL ) {
4278                 return LBER_ERROR_MEMORY;
4279         }
4280
4281         out->bv_val = ch_malloc( 16 );
4282         if ( out->bv_val == NULL ) {
4283                 ch_free( out );
4284                 return LBER_ERROR_MEMORY;
4285         }
4286
4287         sprintf( out->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4288                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4289                 parts[4], parts[5], parts[6] );
4290         out->bv_len = 15;
4291         *normalized = out;
4292
4293         return LDAP_SUCCESS;
4294 }
4295
4296 static int
4297 nisNetgroupTripleValidate(
4298         Syntax *syntax,
4299         struct berval *val )
4300 {
4301         char *p, *e;
4302         int commas = 0;
4303
4304         if ( val->bv_len == 0 ) {
4305                 return LDAP_INVALID_SYNTAX;
4306         }
4307
4308         p = (char *)val->bv_val;
4309         e = p + val->bv_len;
4310
4311         if ( *p != '(' /*')'*/ ) {
4312                 return LDAP_INVALID_SYNTAX;
4313         }
4314
4315         for ( p++; ( p < e ) && ( *p != ')' ); p++ ) {
4316                 if ( *p == ',' ) {
4317                         commas++;
4318                         if ( commas > 2 ) {
4319                                 return LDAP_INVALID_SYNTAX;
4320                         }
4321
4322                 } else if ( !ATTR_CHAR( *p ) ) {
4323                         return LDAP_INVALID_SYNTAX;
4324                 }
4325         }
4326
4327         if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4328                 return LDAP_INVALID_SYNTAX;
4329         }
4330
4331         p++;
4332
4333         if (p != e) {
4334                 return LDAP_INVALID_SYNTAX;
4335         }
4336
4337         return LDAP_SUCCESS;
4338 }
4339
4340 static int
4341 bootParameterValidate(
4342         Syntax *syntax,
4343         struct berval *val )
4344 {
4345         char *p, *e;
4346
4347         if ( val->bv_len == 0 ) {
4348                 return LDAP_INVALID_SYNTAX;
4349         }
4350
4351         p = (char *)val->bv_val;
4352         e = p + val->bv_len;
4353
4354         /* key */
4355         for (; ( p < e ) && ( *p != '=' ); p++ ) {
4356                 if ( !ATTR_CHAR( *p ) ) {
4357                         return LDAP_INVALID_SYNTAX;
4358                 }
4359         }
4360
4361         if ( *p != '=' ) {
4362                 return LDAP_INVALID_SYNTAX;
4363         }
4364
4365         /* server */
4366         for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4367                 if ( !ATTR_CHAR( *p ) ) {
4368                         return LDAP_INVALID_SYNTAX;
4369                 }
4370         }
4371
4372         if ( *p != ':' ) {
4373                 return LDAP_INVALID_SYNTAX;
4374         }
4375
4376         /* path */
4377         for ( p++; p < e; p++ ) {
4378                 if ( !ATTR_CHAR( *p ) ) {
4379                         return LDAP_INVALID_SYNTAX;
4380                 }
4381         }
4382
4383         return LDAP_SUCCESS;
4384 }
4385
4386 struct syntax_defs_rec {
4387         char *sd_desc;
4388         int sd_flags;
4389         slap_syntax_validate_func *sd_validate;
4390         slap_syntax_transform_func *sd_normalize;
4391         slap_syntax_transform_func *sd_pretty;
4392 #ifdef SLAPD_BINARY_CONVERSION
4393         slap_syntax_transform_func *sd_ber2str;
4394         slap_syntax_transform_func *sd_str2ber;
4395 #endif
4396 };
4397
4398 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4399 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4400
4401 struct syntax_defs_rec syntax_defs[] = {
4402         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")",
4403                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4404         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4405                 0, NULL, NULL, NULL},
4406         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4407                 0, NULL, NULL, NULL},
4408         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")",
4409                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4410         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_NOT_H_R ")",
4411                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4412         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4413                 0, bitStringValidate, bitStringNormalize, NULL },
4414         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4415                 0, booleanValidate, NULL, NULL},
4416         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4417                 X_BINARY X_NOT_H_R ")",
4418                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4419         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4420                 X_BINARY X_NOT_H_R ")",
4421                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4422         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4423                 X_BINARY X_NOT_H_R ")",
4424                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4425         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4426                 0, countryStringValidate, IA5StringNormalize, NULL},
4427         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4428                 0, dnValidate, dnNormalize, dnPretty},
4429         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4430                 0, NULL, NULL, NULL},
4431         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4432                 0, NULL, NULL, NULL},
4433         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4434                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4435         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4436                 0, NULL, NULL, NULL},
4437         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4438                 0, NULL, NULL, NULL},
4439         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4440                 0, NULL, NULL, NULL},
4441         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4442                 0, NULL, NULL, NULL},
4443         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4444                 0, NULL, NULL, NULL},
4445         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4446                 0, printablesStringValidate, IA5StringNormalize, NULL},
4447         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4448                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4449         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4450                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4451         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4452                 0, NULL, NULL, NULL},
4453         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4454                 0, IA5StringValidate, IA5StringNormalize, NULL},
4455         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4456                 0, integerValidate, integerNormalize, NULL},
4457         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4458                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4459         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4460                 0, NULL, NULL, NULL},
4461         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4462                 0, NULL, NULL, NULL},
4463         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4464                 0, NULL, NULL, NULL},
4465         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4466                 0, NULL, NULL, NULL},
4467         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4468                 0, NULL, NULL, NULL},
4469         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4470                 0, nameUIDValidate, nameUIDNormalize, NULL},
4471         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4472                 0, NULL, NULL, NULL},
4473         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4474                 0, numericStringValidate, numericStringNormalize, NULL},
4475         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4476                 0, NULL, NULL, NULL},
4477         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4478                 0, oidValidate, NULL, NULL},
4479         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4480                 0, IA5StringValidate, IA5StringNormalize, NULL},
4481         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4482                 0, blobValidate, NULL, NULL},
4483         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4484                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4485         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4486                 0, NULL, NULL, NULL},
4487         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4488                 0, NULL, NULL, NULL},
4489         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4490                 0, printableStringValidate, IA5StringNormalize, NULL},
4491         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4492                 X_BINARY X_NOT_H_R ")",
4493                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4494         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4495                 0, printableStringValidate, IA5StringNormalize, NULL},
4496         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4497                 0, NULL, NULL, NULL},
4498         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4499                 0, printablesStringValidate, IA5StringNormalize, NULL},
4500         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4501                 0, utcTimeValidate, utcTimeNormalize, NULL},
4502         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4503                 0, NULL, NULL, NULL},
4504         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4505                 0, NULL, NULL, NULL},
4506         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4507                 0, NULL, NULL, NULL},
4508         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4509                 0, NULL, NULL, NULL},
4510         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4511                 0, NULL, NULL, NULL},
4512
4513         /* RFC 2307 NIS Syntaxes */
4514         {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Netgroup Triple' )",
4515                 0, nisNetgroupTripleValidate, NULL, NULL},
4516         {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
4517                 0, bootParameterValidate, NULL, NULL},
4518
4519 #ifdef HAVE_TLS
4520         /* From PKIX */
4521         /* These OIDs are not published yet, but will be in the next
4522          * I-D for PKIX LDAPv3 schema as have been advanced by David
4523          * Chadwick in private mail.
4524          */
4525         {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4526                 0, NULL, NULL, NULL},
4527 #endif
4528
4529         /* OpenLDAP Experimental Syntaxes */
4530         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4531                 SLAP_SYNTAX_HIDE,
4532                 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4533                 NULL, NULL},
4534
4535         /* needs updating */
4536         {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4537                 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4538
4539         /* OpenLDAP Void Syntax */
4540         {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4541                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4542         {NULL, 0, NULL, NULL, NULL}
4543 };
4544
4545 struct mrule_defs_rec {
4546         char *                                          mrd_desc;
4547         slap_mask_t                                     mrd_usage;
4548         slap_mr_convert_func *          mrd_convert;
4549         slap_mr_normalize_func *        mrd_normalize;
4550         slap_mr_match_func *            mrd_match;
4551         slap_mr_indexer_func *          mrd_indexer;
4552         slap_mr_filter_func *           mrd_filter;
4553
4554         char *                                          mrd_associated;
4555 };
4556
4557 /*
4558  * Other matching rules in X.520 that we do not use (yet):
4559  *
4560  * 2.5.13.9             numericStringOrderingMatch
4561  * 2.5.13.15    integerOrderingMatch
4562  * 2.5.13.18    octetStringOrderingMatch
4563  * 2.5.13.19    octetStringSubstringsMatch
4564  * 2.5.13.25    uTCTimeMatch
4565  * 2.5.13.26    uTCTimeOrderingMatch
4566  * 2.5.13.31    directoryStringFirstComponentMatch
4567  * 2.5.13.32    wordMatch
4568  * 2.5.13.33    keywordMatch
4569  * 2.5.13.35    certificateMatch
4570  * 2.5.13.36    certificatePairExactMatch
4571  * 2.5.13.37    certificatePairMatch
4572  * 2.5.13.38    certificateListExactMatch
4573  * 2.5.13.39    certificateListMatch
4574  * 2.5.13.40    algorithmIdentifierMatch
4575  * 2.5.13.41    storedPrefixMatch
4576  * 2.5.13.42    attributeCertificateMatch
4577  * 2.5.13.43    readerAndKeyIDMatch
4578  * 2.5.13.44    attributeIntegrityMatch
4579  */
4580
4581 struct mrule_defs_rec mrule_defs[] = {
4582         /*
4583          * EQUALITY matching rules must be listed after associated APPROX
4584          * matching rules.  So, we list all APPROX matching rules first.
4585          */
4586         {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4587                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4588                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4589                 NULL, NULL,
4590                 directoryStringApproxMatch,
4591                 directoryStringApproxIndexer, 
4592                 directoryStringApproxFilter,
4593                 NULL},
4594
4595         {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4596                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4597                 SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4598                 NULL, NULL,
4599                 IA5StringApproxMatch,
4600                 IA5StringApproxIndexer, 
4601                 IA5StringApproxFilter,
4602                 NULL},
4603
4604         /*
4605          * Other matching rules
4606          */
4607         
4608         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4609                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4610                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4611                 NULL, NULL,
4612                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4613                 NULL},
4614
4615         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4616                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4617                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4618                 NULL, NULL,
4619                 dnMatch, dnIndexer, dnFilter,
4620                 NULL},
4621
4622         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4623                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4624                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4625                 NULL, NULL,
4626                 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4627                 directoryStringApproxMatchOID },
4628
4629         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4630                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4631                 SLAP_MR_ORDERING,
4632                 NULL, NULL,
4633                 caseIgnoreOrderingMatch, NULL, NULL,
4634                 NULL},
4635
4636         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4637                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4638                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4639                 NULL, NULL,
4640                 caseExactIgnoreSubstringsMatch,
4641                 caseExactIgnoreSubstringsIndexer,
4642                 caseExactIgnoreSubstringsFilter,
4643                 NULL},
4644
4645         {"( 2.5.13.5 NAME 'caseExactMatch' "
4646                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4647                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4648                 NULL, NULL,
4649                 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4650                 directoryStringApproxMatchOID },
4651
4652         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4653                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4654                 SLAP_MR_ORDERING,
4655                 NULL, NULL,
4656                 caseExactOrderingMatch, NULL, NULL,
4657                 NULL},
4658
4659         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4660                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4661                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4662                 NULL, NULL,
4663                 caseExactIgnoreSubstringsMatch,
4664                 caseExactIgnoreSubstringsIndexer,
4665                 caseExactIgnoreSubstringsFilter,
4666                 NULL},
4667
4668         {"( 2.5.13.8 NAME 'numericStringMatch' "
4669                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4670                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4671                 NULL, NULL,
4672                 caseIgnoreIA5Match,
4673                 caseIgnoreIA5Indexer,
4674                 caseIgnoreIA5Filter,
4675                 NULL},
4676
4677         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4678                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4679                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4680                 NULL, NULL,
4681                 caseIgnoreIA5SubstringsMatch,
4682                 caseIgnoreIA5SubstringsIndexer,
4683                 caseIgnoreIA5SubstringsFilter,
4684                 NULL},
4685
4686         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4687                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4688                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4689                 NULL, NULL,
4690                 caseIgnoreListMatch, NULL, NULL,
4691                 NULL},
4692
4693         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4694                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4695                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4696                 NULL, NULL,
4697                 caseIgnoreListSubstringsMatch, NULL, NULL,
4698                 NULL},
4699
4700         {"( 2.5.13.13 NAME 'booleanMatch' "
4701                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4702                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4703                 NULL, NULL,
4704                 booleanMatch, NULL, NULL,
4705                 NULL},
4706
4707         {"( 2.5.13.14 NAME 'integerMatch' "
4708                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4709                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4710                 NULL, NULL,
4711                 integerMatch, integerIndexer, integerFilter,
4712                 NULL},
4713
4714         {"( 2.5.13.16 NAME 'bitStringMatch' "
4715                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4716                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4717                 NULL, NULL,
4718                 bitStringMatch, bitStringIndexer, bitStringFilter,
4719                 NULL},
4720
4721         {"( 2.5.13.17 NAME 'octetStringMatch' "
4722                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4723                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4724                 NULL, NULL,
4725                 octetStringMatch, octetStringIndexer, octetStringFilter,
4726                 NULL},
4727
4728         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4729                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4730                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4731                 NULL, NULL,
4732                 telephoneNumberMatch,
4733                 telephoneNumberIndexer,
4734                 telephoneNumberFilter,
4735                 NULL},
4736
4737         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4738                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4739                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4740                 NULL, NULL,
4741                 telephoneNumberSubstringsMatch,
4742                 telephoneNumberSubstringsIndexer,
4743                 telephoneNumberSubstringsFilter,
4744                 NULL},
4745
4746         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4747                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4748                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4749                 NULL, NULL,
4750                 NULL, NULL, NULL,
4751                 NULL},
4752
4753         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4754                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4755                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4756                 NULL, NULL,
4757                 uniqueMemberMatch, NULL, NULL,
4758                 NULL},
4759
4760         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4761                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4762                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4763                 NULL, NULL,
4764                 protocolInformationMatch, NULL, NULL,
4765                 NULL},
4766
4767         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4768                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4769                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4770                 NULL, NULL,
4771                 generalizedTimeMatch, NULL, NULL,
4772                 NULL},
4773
4774         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4775                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4776                 SLAP_MR_ORDERING,
4777                 NULL, NULL,
4778                 generalizedTimeOrderingMatch, NULL, NULL,
4779                 NULL},
4780
4781         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4782                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4783                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4784                 NULL, NULL,
4785                 integerFirstComponentMatch, NULL, NULL,
4786                 NULL},
4787
4788         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4789                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4790                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4791                 NULL, NULL,
4792                 objectIdentifierFirstComponentMatch, NULL, NULL,
4793                 NULL},
4794
4795 #ifdef HAVE_TLS
4796         {"( 2.5.13.34 NAME 'certificateExactMatch' "
4797                 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4798                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4799                 certificateExactConvert, NULL,
4800                 certificateExactMatch,
4801                 certificateExactIndexer, certificateExactFilter,
4802                 NULL},
4803 #endif
4804
4805         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4806                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4807                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4808                 NULL, NULL,
4809                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4810                 IA5StringApproxMatchOID },
4811
4812         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4813                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4814                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4815                 NULL, NULL,
4816                 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4817                 IA5StringApproxMatchOID },
4818
4819         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4820                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4821                 SLAP_MR_SUBSTR,
4822                 NULL, NULL,
4823                 caseIgnoreIA5SubstringsMatch,
4824                 caseIgnoreIA5SubstringsIndexer,
4825                 caseIgnoreIA5SubstringsFilter,
4826                 NULL},
4827
4828         {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4829                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4830                 SLAP_MR_SUBSTR,
4831                 NULL, NULL,
4832                 caseExactIA5SubstringsMatch,
4833                 caseExactIA5SubstringsIndexer,
4834                 caseExactIA5SubstringsFilter,
4835                 NULL},
4836
4837         /* needs updating */
4838         {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4839                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4840                 SLAP_MR_EQUALITY,
4841                 NULL, NULL,
4842                 authPasswordMatch, NULL, NULL,
4843                 NULL},
4844
4845         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4846                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4847                 SLAP_MR_EQUALITY,
4848                 NULL, NULL,
4849                 OpenLDAPaciMatch, NULL, NULL,
4850                 NULL},
4851
4852         {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4853                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4854                 SLAP_MR_EXT,
4855                 NULL, NULL,
4856                 integerBitAndMatch, NULL, NULL,
4857                 NULL},
4858
4859         {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4860                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4861                 SLAP_MR_EXT,
4862                 NULL, NULL,
4863                 integerBitOrMatch, NULL, NULL,
4864                 NULL},
4865
4866         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4867 };
4868
4869 int
4870 schema_init( void )
4871 {
4872         int             res;
4873         int             i;
4874
4875         /* we should only be called once (from main) */
4876         assert( schema_init_done == 0 );
4877
4878         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4879                 res = register_syntax( syntax_defs[i].sd_desc,
4880                         syntax_defs[i].sd_flags,
4881                         syntax_defs[i].sd_validate,
4882                         syntax_defs[i].sd_normalize,
4883                         syntax_defs[i].sd_pretty
4884 #ifdef SLAPD_BINARY_CONVERSION
4885                         ,
4886                         syntax_defs[i].sd_ber2str,
4887                         syntax_defs[i].sd_str2ber
4888 #endif
4889                 );
4890
4891                 if ( res ) {
4892                         fprintf( stderr, "schema_init: Error registering syntax %s\n",
4893                                  syntax_defs[i].sd_desc );
4894                         return LDAP_OTHER;
4895                 }
4896         }
4897
4898         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4899                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4900                         fprintf( stderr,
4901                                 "schema_init: Ingoring unusable matching rule %s\n",
4902                                  mrule_defs[i].mrd_desc );
4903                         continue;
4904                 }
4905
4906                 res = register_matching_rule(
4907                         mrule_defs[i].mrd_desc,
4908                         mrule_defs[i].mrd_usage,
4909                         mrule_defs[i].mrd_convert,
4910                         mrule_defs[i].mrd_normalize,
4911                         mrule_defs[i].mrd_match,
4912                         mrule_defs[i].mrd_indexer,
4913                         mrule_defs[i].mrd_filter,
4914                         mrule_defs[i].mrd_associated );
4915
4916                 if ( res ) {
4917                         fprintf( stderr,
4918                                 "schema_init: Error registering matching rule %s\n",
4919                                  mrule_defs[i].mrd_desc );
4920                         return LDAP_OTHER;
4921                 }
4922         }
4923         schema_init_done = 1;
4924         return LDAP_SUCCESS;
4925 }
4926
4927 void
4928 schema_destroy( void )
4929 {
4930         oc_destroy();
4931         at_destroy();
4932         mr_destroy();
4933         syn_destroy();
4934 }