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