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