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