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