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