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