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