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