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