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