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