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