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