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