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