]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
b5ce9113f6c7c0a66a91008435f88352d0432fa8
[openldap] / servers / slapd / schema_init.c
1 /* schema_init.c - init builtin schema */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <limits.h>
12
13 #include <ac/ctype.h>
14 #include <ac/errno.h>
15 #include <ac/string.h>
16 #include <ac/socket.h>
17
18 #include "slap.h"
19 #include "ldap_pvt.h"
20 #include "lber_pvt.h"
21
22 #include "ldap_utf8.h"
23
24 #include "lutil_hash.h"
25 #define HASH_BYTES                              LUTIL_HASH_BYTES
26 #define HASH_CONTEXT                    lutil_HASH_CTX
27 #define HASH_Init(c)                    lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len)  lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c)                 lutil_HASHFinal(d,c)
30
31 /* recycled validatation routines */
32 #define berValidate                                             blobValidate
33
34 /* unimplemented pretters */
35 #define integerPretty                                   NULL
36
37 /* recycled matching routines */
38 #define bitStringMatch                                  octetStringMatch
39 #define numericStringMatch                              caseIgnoreIA5Match
40 #define objectIdentifierMatch                   caseIgnoreIA5Match
41 #define telephoneNumberMatch                    caseIgnoreIA5Match
42 #define telephoneNumberSubstringsMatch  caseIgnoreIA5SubstringsMatch
43 #define generalizedTimeMatch                    caseIgnoreIA5Match
44 #define generalizedTimeOrderingMatch    caseIgnoreIA5Match
45 #define uniqueMemberMatch                               dnMatch
46
47 /* approx matching rules */
48 #define directoryStringApproxMatchOID   "1.3.6.1.4.1.4203.666.4.4"
49 #define directoryStringApproxMatch      approxMatch
50 #define directoryStringApproxIndexer    approxIndexer
51 #define directoryStringApproxFilter     approxFilter
52 #define IA5StringApproxMatchOID                 "1.3.6.1.4.1.4203.666.4.5"
53 #define IA5StringApproxMatch                    approxMatch
54 #define IA5StringApproxIndexer                  approxIndexer
55 #define IA5StringApproxFilter                   approxFilter
56
57 /* orderring matching rules */
58 #define caseIgnoreOrderingMatch                 caseIgnoreMatch
59 #define caseExactOrderingMatch                  caseExactMatch
60
61 /* unimplemented matching routines */
62 #define caseIgnoreListMatch                             NULL
63 #define caseIgnoreListSubstringsMatch   NULL
64 #define protocolInformationMatch                NULL
65 #define integerFirstComponentMatch              NULL
66
67 #ifdef SLAPD_ACI_ENABLED
68 #define OpenLDAPaciMatch                                NULL
69 #endif
70 #ifdef SLAPD_AUTHPASSWD
71 #define authPasswordMatch                               NULL
72 #endif
73
74 /* recycled indexing/filtering routines */
75 #define dnIndexer                               caseExactIgnoreIndexer
76 #define dnFilter                                caseExactIgnoreFilter
77 #define bitStringFilter                 octetStringFilter
78 #define bitStringIndexer                octetStringIndexer
79
80 #define telephoneNumberIndexer                  caseIgnoreIA5Indexer
81 #define telephoneNumberFilter                   caseIgnoreIA5Filter
82 #define telephoneNumberSubstringsIndexer        caseIgnoreIA5SubstringsIndexer
83 #define telephoneNumberSubstringsFilter         caseIgnoreIA5SubstringsFilter
84
85 /* must match OIDs below */
86 #define caseExactMatchOID                       "2.5.13.5"
87 #define caseExactSubstringsMatchOID             "2.5.13.7"
88
89 static char *bvcasechr( struct berval *bv, int c, ber_len_t *len )
90 {
91         ber_len_t i;
92         int lower = TOLOWER( c );
93         int upper = TOUPPER( c );
94
95         if( c == 0 ) return NULL;
96         
97         for( i=0; i < bv->bv_len; i++ ) {
98                 if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
99                         *len = i;
100                         return &bv->bv_val[i];
101                 }
102         }
103
104         return NULL;
105 }
106
107 static int
108 octetStringMatch(
109         int *matchp,
110         slap_mask_t flags,
111         Syntax *syntax,
112         MatchingRule *mr,
113         struct berval *value,
114         void *assertedValue )
115 {
116         int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
117
118         if( match == 0 ) {
119                 match = memcmp( value->bv_val,
120                         ((struct berval *) assertedValue)->bv_val,
121                         value->bv_len );
122         }
123
124         *matchp = match;
125         return LDAP_SUCCESS;
126 }
127
128 /* Index generation function */
129 static int octetStringIndexer(
130         slap_mask_t use,
131         slap_mask_t flags,
132         Syntax *syntax,
133         MatchingRule *mr,
134         struct berval *prefix,
135         BerVarray values,
136         BerVarray *keysp )
137 {
138         int i;
139         size_t slen, mlen;
140         BerVarray keys;
141         HASH_CONTEXT   HASHcontext;
142         unsigned char   HASHdigest[HASH_BYTES];
143         struct berval digest;
144         digest.bv_val = HASHdigest;
145         digest.bv_len = sizeof(HASHdigest);
146
147         for( i=0; values[i].bv_val != NULL; i++ ) {
148                 /* just count them */
149         }
150
151         /* we should have at least one value at this point */
152         assert( i > 0 );
153
154         keys = ch_malloc( sizeof( struct berval ) * (i+1) );
155
156         slen = syntax->ssyn_oidlen;
157         mlen = mr->smr_oidlen;
158
159         for( i=0; values[i].bv_val != NULL; i++ ) {
160                 HASH_Init( &HASHcontext );
161                 if( prefix != NULL && prefix->bv_len > 0 ) {
162                         HASH_Update( &HASHcontext,
163                                 prefix->bv_val, prefix->bv_len );
164                 }
165                 HASH_Update( &HASHcontext,
166                         syntax->ssyn_oid, slen );
167                 HASH_Update( &HASHcontext,
168                         mr->smr_oid, mlen );
169                 HASH_Update( &HASHcontext,
170                         values[i].bv_val, values[i].bv_len );
171                 HASH_Final( HASHdigest, &HASHcontext );
172
173                 ber_dupbv( &keys[i], &digest );
174         }
175
176         keys[i].bv_val = NULL;
177
178         *keysp = keys;
179
180         return LDAP_SUCCESS;
181 }
182
183 /* Index generation function */
184 static int octetStringFilter(
185         slap_mask_t use,
186         slap_mask_t flags,
187         Syntax *syntax,
188         MatchingRule *mr,
189         struct berval *prefix,
190         void * assertValue,
191         BerVarray *keysp )
192 {
193         size_t slen, mlen;
194         BerVarray keys;
195         HASH_CONTEXT   HASHcontext;
196         unsigned char   HASHdigest[HASH_BYTES];
197         struct berval *value = (struct berval *) assertValue;
198         struct berval digest;
199         digest.bv_val = HASHdigest;
200         digest.bv_len = sizeof(HASHdigest);
201
202         slen = syntax->ssyn_oidlen;
203         mlen = mr->smr_oidlen;
204
205         keys = ch_malloc( sizeof( struct berval ) * 2 );
206
207         HASH_Init( &HASHcontext );
208         if( prefix != NULL && prefix->bv_len > 0 ) {
209                 HASH_Update( &HASHcontext,
210                         prefix->bv_val, prefix->bv_len );
211         }
212         HASH_Update( &HASHcontext,
213                 syntax->ssyn_oid, slen );
214         HASH_Update( &HASHcontext,
215                 mr->smr_oid, mlen );
216         HASH_Update( &HASHcontext,
217                 value->bv_val, value->bv_len );
218         HASH_Final( HASHdigest, &HASHcontext );
219
220         ber_dupbv( keys, &digest );
221         keys[1].bv_val = NULL;
222
223         *keysp = keys;
224
225         return LDAP_SUCCESS;
226 }
227
228 static int
229 nameUIDValidate(
230         Syntax *syntax,
231         struct berval *in )
232 {
233         int rc;
234         struct berval dn;
235
236         if( in->bv_len == 0 ) return LDAP_SUCCESS;
237
238         ber_dupbv( &dn, in );
239         if( !dn.bv_val ) return LDAP_OTHER;
240
241         if( dn.bv_val[dn.bv_len-1] == 'B'
242                 && dn.bv_val[dn.bv_len-2] == '\'' )
243         {
244                 /* assume presence of optional UID */
245                 ber_len_t i;
246
247                 for(i=dn.bv_len-3; i>1; i--) {
248                         if( dn.bv_val[i] != '0' &&      dn.bv_val[i] != '1' ) {
249                                 break;
250                         }
251                 }
252                 if( dn.bv_val[i] != '\'' ||
253                     dn.bv_val[i-1] != '#' ) {
254                         ber_memfree( dn.bv_val );
255                         return LDAP_INVALID_SYNTAX;
256                 }
257
258                 /* trim the UID to allow use of dnValidate */
259                 dn.bv_val[i-1] = '\0';
260                 dn.bv_len = i-1;
261         }
262
263         rc = dnValidate( NULL, &dn );
264
265         ber_memfree( &dn );
266         return rc;
267 }
268
269 static int
270 nameUIDNormalize(
271         Syntax *syntax,
272         struct berval *val,
273         struct berval *normalized )
274 {
275         struct berval out;
276         int rc;
277
278         ber_dupbv( &out, val );
279         if( out.bv_len != 0 ) {
280                 ber_len_t dnlen;
281                 char *uid = NULL;
282                 ber_len_t uidlen = 0;
283
284                 if( out.bv_val[out.bv_len-1] == '\'' ) {
285                         /* assume presence of optional UID */
286                         uid = strrchr( out.bv_val, '#' );
287
288                         if( uid == NULL ) {
289                                 free( out.bv_val );
290                                 return LDAP_INVALID_SYNTAX;
291                         }
292
293                         uidlen = out.bv_len - (uid - out.bv_val);
294                         /* temporarily trim the UID */
295                         *uid = '\0';
296                         out.bv_len -= uidlen;
297                 }
298
299 #ifdef USE_DN_NORMALIZE
300                 rc = dnNormalize2( NULL, &out, normalized );
301 #else
302                 rc = dnPretty2( NULL, &out, normalized );
303 #endif
304
305                 if( rc != LDAP_SUCCESS ) {
306                         free( out.bv_val );
307                         return LDAP_INVALID_SYNTAX;
308                 }
309
310                 dnlen = normalized->bv_len;
311
312                 if( uidlen ) {
313                         struct berval b2;
314                         b2.bv_val = ch_malloc(dnlen + uidlen + 1);
315                         AC_MEMCPY( b2.bv_val, normalized->bv_val, dnlen );
316
317                         /* restore the separator */
318                         *uid = '#';
319                         /* shift the UID */
320                         AC_MEMCPY( normalized->bv_val+dnlen, uid, uidlen );
321                         b2.bv_len = dnlen + uidlen;
322                         normalized->bv_val[dnlen+uidlen] = '\0';
323                         free(normalized->bv_val);
324                         *normalized = b2;
325                 }
326                 free( out.bv_val );
327         }
328
329         return LDAP_SUCCESS;
330 }
331
332 static int
333 inValidate(
334         Syntax *syntax,
335         struct berval *in )
336 {
337         /* any value allowed */
338         return LDAP_OTHER;
339 }
340
341 static int
342 blobValidate(
343         Syntax *syntax,
344         struct berval *in )
345 {
346         /* any value allowed */
347         return LDAP_SUCCESS;
348 }
349
350 static int
351 bitStringValidate(
352         Syntax *syntax,
353         struct berval *in )
354 {
355         ber_len_t i;
356
357         /* very unforgiving validation, requires no normalization
358          * before simplistic matching
359          */
360         if( in->bv_len < 3 ) {
361                 return LDAP_INVALID_SYNTAX;
362         }
363
364         /*
365          * rfc 2252 section 6.3 Bit String
366          * bitstring = "'" *binary-digit "'"
367          * binary-digit = "0" / "1"
368          * example: '0101111101'B
369          */
370         
371         if( in->bv_val[0] != '\'' ||
372                 in->bv_val[in->bv_len-2] != '\'' ||
373                 in->bv_val[in->bv_len-1] != 'B' )
374         {
375                 return LDAP_INVALID_SYNTAX;
376         }
377
378         for( i=in->bv_len-3; i>0; i-- ) {
379                 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
380                         return LDAP_INVALID_SYNTAX;
381                 }
382         }
383
384         return LDAP_SUCCESS;
385 }
386
387 static int
388 bitStringNormalize(
389         Syntax *syntax,
390         struct berval *val,
391         struct berval *normalized )
392 {
393         /*
394          * A normalized bitString is has no extaneous (leading) zero bits.
395          * That is, '00010'B is normalized to '10'B
396          * However, as a special case, '0'B requires no normalization.
397          */
398         char *p;
399
400         /* start at the first bit */
401         p = &val->bv_val[1];
402
403         /* Find the first non-zero bit */
404         while ( *p == '0' ) p++;
405
406         if( *p == '\'' ) {
407                 /* no non-zero bits */
408                 ber_str2bv( "\'0\'B", sizeof("\'0\'B") - 1, 1, normalized );
409                 goto done;
410         }
411
412         normalized->bv_val = ch_malloc( val->bv_len + 1 );
413
414         normalized->bv_val[0] = '\'';
415         normalized->bv_len = 1;
416
417         for( ; *p != '\0'; p++ ) {
418                 normalized->bv_val[normalized->bv_len++] = *p;
419         }
420
421         normalized->bv_val[normalized->bv_len] = '\0';
422
423 done:
424         return LDAP_SUCCESS;
425 }
426
427 /*
428  * Handling boolean syntax and matching is quite rigid.
429  * A more flexible approach would be to allow a variety
430  * of strings to be normalized and prettied into TRUE
431  * and FALSE.
432  */
433 static int
434 booleanValidate(
435         Syntax *syntax,
436         struct berval *in )
437 {
438         /* very unforgiving validation, requires no normalization
439          * before simplistic matching
440          */
441
442         if( in->bv_len == 4 ) {
443                 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
444                         return LDAP_SUCCESS;
445                 }
446         } else if( in->bv_len == 5 ) {
447                 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
448                         return LDAP_SUCCESS;
449                 }
450         }
451
452         return LDAP_INVALID_SYNTAX;
453 }
454
455 static int
456 booleanMatch(
457         int *matchp,
458         slap_mask_t flags,
459         Syntax *syntax,
460         MatchingRule *mr,
461         struct berval *value,
462         void *assertedValue )
463 {
464         /* simplistic matching allowed by rigid validation */
465         struct berval *asserted = (struct berval *) assertedValue;
466         *matchp = value->bv_len != asserted->bv_len;
467         return LDAP_SUCCESS;
468 }
469
470 static int
471 UTF8StringValidate(
472         Syntax *syntax,
473         struct berval *in )
474 {
475         ber_len_t count;
476         int len;
477         unsigned char *u = in->bv_val;
478
479         if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
480
481         for( count = in->bv_len; count > 0; count-=len, u+=len ) {
482                 /* get the length indicated by the first byte */
483                 len = LDAP_UTF8_CHARLEN2( u, len );
484
485                 /* very basic checks */
486                 switch( len ) {
487                         case 6:
488                                 if( (u[5] & 0xC0) != 0x80 ) {
489                                         return LDAP_INVALID_SYNTAX;
490                                 }
491                         case 5:
492                                 if( (u[4] & 0xC0) != 0x80 ) {
493                                         return LDAP_INVALID_SYNTAX;
494                                 }
495                         case 4:
496                                 if( (u[3] & 0xC0) != 0x80 ) {
497                                         return LDAP_INVALID_SYNTAX;
498                                 }
499                         case 3:
500                                 if( (u[2] & 0xC0 )!= 0x80 ) {
501                                         return LDAP_INVALID_SYNTAX;
502                                 }
503                         case 2:
504                                 if( (u[1] & 0xC0) != 0x80 ) {
505                                         return LDAP_INVALID_SYNTAX;
506                                 }
507                         case 1:
508                                 /* CHARLEN already validated it */
509                                 break;
510                         default:
511                                 return LDAP_INVALID_SYNTAX;
512                 }
513
514                 /* make sure len corresponds with the offset
515                         to the next character */
516                 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
517         }
518
519         if( count != 0 ) return LDAP_INVALID_SYNTAX;
520
521         return LDAP_SUCCESS;
522 }
523
524 static int
525 UTF8StringNormalize(
526         Syntax *syntax,
527         struct berval *val,
528         struct berval *normalized )
529 {
530         char *p, *q, *s, *e;
531         int len = 0;
532
533         p = val->bv_val;
534
535         /* Ignore initial whitespace */
536         /* All space is ASCII. All ASCII is 1 byte */
537         for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
538
539         ber_mem2bv( p, val->bv_len - (p - val->bv_val), 1, normalized );
540         e = normalized->bv_val + val->bv_len - (p - val->bv_val);
541
542         assert( normalized->bv_val );
543
544         p = q = normalized->bv_val;
545         s = NULL;
546
547         while ( p < e ) {
548                 q += len;
549                 if ( ASCII_SPACE( *p ) ) {
550                         s = q - len;
551                         len = 1;
552                         *q = *p++;
553
554                         /* Ignore the extra whitespace */
555                         while ( ASCII_SPACE( *p ) ) {
556                                 p++;
557                         }
558                 } else {
559                         len = LDAP_UTF8_COPY(q,p);
560                         s=NULL;
561                         p+=len;
562                 }
563         }
564
565         assert( normalized->bv_val < p );
566         assert( q+len <= p );
567
568         /* cannot start with a space */
569         assert( !ASCII_SPACE(normalized->bv_val[0]) );
570
571         /*
572          * If the string ended in space, backup the pointer one
573          * position.  One is enough because the above loop collapsed
574          * all whitespace to a single space.
575          */
576
577         if ( s != NULL ) {
578                 len = q - s;
579                 q = s;
580         }
581
582         /* cannot end with a space */
583         assert( !ASCII_SPACE( *q ) );
584
585         q += len;
586
587         /* null terminate */
588         *q = '\0';
589
590         normalized->bv_len = q - normalized->bv_val;
591
592         return LDAP_SUCCESS;
593 }
594
595 /* Returns Unicode canonically normalized copy of a substring assertion
596  * Skipping attribute description */
597 static SubstringsAssertion *
598 UTF8SubstringsassertionNormalize(
599         SubstringsAssertion *sa,
600         unsigned casefold )
601 {
602         SubstringsAssertion *nsa;
603         int i;
604
605         nsa = (SubstringsAssertion *)ch_calloc( 1, sizeof(SubstringsAssertion) );
606         if( nsa == NULL ) {
607                 return NULL;
608         }
609
610         if( sa->sa_initial.bv_val != NULL ) {
611                 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
612                 if( nsa->sa_initial.bv_val == NULL ) {
613                         goto err;
614                 }
615         }
616
617         if( sa->sa_any != NULL ) {
618                 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
619                         /* empty */
620                 }
621                 nsa->sa_any = (struct berval *)ch_malloc( (i + 1) * sizeof(struct berval) );
622                 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
623                         UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i], 
624                                         casefold );
625                         if( nsa->sa_any[i].bv_val == NULL ) {
626                                 goto err;
627                         }
628                 }
629                 nsa->sa_any[i].bv_val = NULL;
630         }
631
632         if( sa->sa_final.bv_val != NULL ) {
633                 UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
634                 if( nsa->sa_final.bv_val == NULL ) {
635                         goto err;
636                 }
637         }
638
639         return nsa;
640
641 err:
642         if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
643         if ( nsa->sa_any )ber_bvarray_free( nsa->sa_any );
644         if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
645         ch_free( nsa );
646         return NULL;
647 }
648
649 #ifndef SLAPD_APPROX_OLDSINGLESTRING
650
651 #if defined(SLAPD_APPROX_INITIALS)
652 #define SLAPD_APPROX_DELIMITER "._ "
653 #define SLAPD_APPROX_WORDLEN 2
654 #else
655 #define SLAPD_APPROX_DELIMITER " "
656 #define SLAPD_APPROX_WORDLEN 1
657 #endif
658
659 static int
660 approxMatch(
661         int *matchp,
662         slap_mask_t flags,
663         Syntax *syntax,
664         MatchingRule *mr,
665         struct berval *value,
666         void *assertedValue )
667 {
668         struct berval *nval, *assertv;
669         char *val, **values, **words, *c;
670         int i, count, len, nextchunk=0, nextavail=0;
671
672         /* Yes, this is necessary */
673         nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
674         if( nval == NULL ) {
675                 *matchp = 1;
676                 return LDAP_SUCCESS;
677         }
678
679         /* Yes, this is necessary */
680         assertv = UTF8bvnormalize( ((struct berval *)assertedValue), NULL, LDAP_UTF8_APPROX );
681         if( assertv == NULL ) {
682                 ber_bvfree( nval );
683                 *matchp = 1;
684                 return LDAP_SUCCESS;
685         }
686
687         /* Isolate how many words there are */
688         for ( c = nval->bv_val, count = 1; *c; c++ ) {
689                 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
690                 if ( c == NULL ) break;
691                 *c = '\0';
692                 count++;
693         }
694
695         /* Get a phonetic copy of each word */
696         words = (char **)ch_malloc( count * sizeof(char *) );
697         values = (char **)ch_malloc( count * sizeof(char *) );
698         for ( c = nval->bv_val, i = 0;  i < count; i++, c += strlen(c) + 1 ) {
699                 words[i] = c;
700                 values[i] = phonetic(c);
701         }
702
703         /* Work through the asserted value's words, to see if at least some
704            of the words are there, in the same order. */
705         len = 0;
706         while ( (ber_len_t) nextchunk < assertv->bv_len ) {
707                 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
708                 if( len == 0 ) {
709                         nextchunk++;
710                         continue;
711                 }
712 #if defined(SLAPD_APPROX_INITIALS)
713                 else if( len == 1 ) {
714                         /* Single letter words need to at least match one word's initial */
715                         for( i=nextavail; i<count; i++ )
716                                 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
717                                         nextavail=i+1;
718                                         break;
719                                 }
720                 }
721 #endif
722                 else {
723                         /* Isolate the next word in the asserted value and phonetic it */
724                         assertv->bv_val[nextchunk+len] = '\0';
725                         val = phonetic( assertv->bv_val + nextchunk );
726
727                         /* See if this phonetic chunk is in the remaining words of *value */
728                         for( i=nextavail; i<count; i++ ){
729                                 if( !strcmp( val, values[i] ) ){
730                                         nextavail = i+1;
731                                         break;
732                                 }
733                         }
734                         ch_free( val );
735                 }
736
737                 /* This chunk in the asserted value was NOT within the *value. */
738                 if( i >= count ) {
739                         nextavail=-1;
740                         break;
741                 }
742
743                 /* Go on to the next word in the asserted value */
744                 nextchunk += len+1;
745         }
746
747         /* If some of the words were seen, call it a match */
748         if( nextavail > 0 ) {
749                 *matchp = 0;
750         }
751         else {
752                 *matchp = 1;
753         }
754
755         /* Cleanup allocs */
756         ber_bvfree( assertv );
757         for( i=0; i<count; i++ ) {
758                 ch_free( values[i] );
759         }
760         ch_free( values );
761         ch_free( words );
762         ber_bvfree( nval );
763
764         return LDAP_SUCCESS;
765 }
766
767 static int 
768 approxIndexer(
769         slap_mask_t use,
770         slap_mask_t flags,
771         Syntax *syntax,
772         MatchingRule *mr,
773         struct berval *prefix,
774         BerVarray values,
775         BerVarray *keysp )
776 {
777         char *c;
778         int i,j, len, wordcount, keycount=0;
779         struct berval *newkeys;
780         BerVarray keys=NULL;
781
782         for( j=0; values[j].bv_val != NULL; j++ ) {
783                 struct berval val = { 0, NULL };
784                 /* Yes, this is necessary */
785                 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
786                 assert( val.bv_val != NULL );
787
788                 /* Isolate how many words there are. There will be a key for each */
789                 for( wordcount = 0, c = val.bv_val; *c; c++) {
790                         len = strcspn(c, SLAPD_APPROX_DELIMITER);
791                         if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
792                         c+= len;
793                         if (*c == '\0') break;
794                         *c = '\0';
795                 }
796
797                 /* Allocate/increase storage to account for new keys */
798                 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1) 
799                         * sizeof(struct berval) );
800                 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
801                 if( keys ) ch_free( keys );
802                 keys = newkeys;
803
804                 /* Get a phonetic copy of each word */
805                 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
806                         len = strlen( c );
807                         if( len < SLAPD_APPROX_WORDLEN ) continue;
808                         ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
809                         keycount++;
810                         i++;
811                 }
812
813                 ber_memfree( val.bv_val );
814         }
815         keys[keycount].bv_val = NULL;
816         *keysp = keys;
817
818         return LDAP_SUCCESS;
819 }
820
821 static int 
822 approxFilter(
823         slap_mask_t use,
824         slap_mask_t flags,
825         Syntax *syntax,
826         MatchingRule *mr,
827         struct berval *prefix,
828         void * assertValue,
829         BerVarray *keysp )
830 {
831         char *c;
832         int i, count, len;
833         struct berval *val;
834         BerVarray keys;
835
836         /* Yes, this is necessary */
837         val = UTF8bvnormalize( ((struct berval *)assertValue), NULL, LDAP_UTF8_APPROX );
838         if( val == NULL || val->bv_val == NULL ) {
839                 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
840                 keys[0].bv_val = NULL;
841                 *keysp = keys;
842                 ber_bvfree( val );
843                 return LDAP_SUCCESS;
844         }
845
846         /* Isolate how many words there are. There will be a key for each */
847         for( count = 0,c = val->bv_val; *c; c++) {
848                 len = strcspn(c, SLAPD_APPROX_DELIMITER);
849                 if( len >= SLAPD_APPROX_WORDLEN ) count++;
850                 c+= len;
851                 if (*c == '\0') break;
852                 *c = '\0';
853         }
854
855         /* Allocate storage for new keys */
856         keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
857
858         /* Get a phonetic copy of each word */
859         for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
860                 len = strlen(c);
861                 if( len < SLAPD_APPROX_WORDLEN ) continue;
862                 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
863                 i++;
864         }
865
866         ber_bvfree( val );
867
868         keys[count].bv_val = NULL;
869         *keysp = keys;
870
871         return LDAP_SUCCESS;
872 }
873
874
875 #else
876 /* No other form of Approximate Matching is defined */
877
878 static int
879 approxMatch(
880         int *matchp,
881         slap_mask_t flags,
882         Syntax *syntax,
883         MatchingRule *mr,
884         struct berval *value,
885         void *assertedValue )
886 {
887         char *vapprox, *avapprox;
888         char *s, *t;
889
890         /* Yes, this is necessary */
891         s = UTF8normalize( value, UTF8_NOCASEFOLD );
892         if( s == NULL ) {
893                 *matchp = 1;
894                 return LDAP_SUCCESS;
895         }
896
897         /* Yes, this is necessary */
898         t = UTF8normalize( ((struct berval *)assertedValue),
899                            UTF8_NOCASEFOLD );
900         if( t == NULL ) {
901                 free( s );
902                 *matchp = -1;
903                 return LDAP_SUCCESS;
904         }
905
906         vapprox = phonetic( strip8bitChars( s ) );
907         avapprox = phonetic( strip8bitChars( t ) );
908
909         free( s );
910         free( t );
911
912         *matchp = strcmp( vapprox, avapprox );
913
914         ch_free( vapprox );
915         ch_free( avapprox );
916
917         return LDAP_SUCCESS;
918 }
919
920 static int 
921 approxIndexer(
922         slap_mask_t use,
923         slap_mask_t flags,
924         Syntax *syntax,
925         MatchingRule *mr,
926         struct berval *prefix,
927         BerVarray values,
928         BerVarray *keysp )
929 {
930         int i;
931         BerVarray *keys;
932         char *s;
933
934         for( i=0; values[i].bv_val != NULL; i++ ) {
935                 /* empty - just count them */
936         }
937
938         /* we should have at least one value at this point */
939         assert( i > 0 );
940
941         keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
942
943         /* Copy each value and run it through phonetic() */
944         for( i=0; values[i].bv_val != NULL; i++ ) {
945                 /* Yes, this is necessary */
946                 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
947
948                 /* strip 8-bit chars and run through phonetic() */
949                 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
950                 free( s );
951         }
952         keys[i].bv_val = NULL;
953
954         *keysp = keys;
955         return LDAP_SUCCESS;
956 }
957
958
959 static int 
960 approxFilter(
961         slap_mask_t use,
962         slap_mask_t flags,
963         Syntax *syntax,
964         MatchingRule *mr,
965         struct berval *prefix,
966         void * assertValue,
967         BerVarray *keysp )
968 {
969         BerVarray keys;
970         char *s;
971
972         keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
973
974         /* Yes, this is necessary */
975         s = UTF8normalize( ((struct berval *)assertValue),
976                              UTF8_NOCASEFOLD );
977         if( s == NULL ) {
978                 keys[0] = NULL;
979         } else {
980                 /* strip 8-bit chars and run through phonetic() */
981                 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
982                 free( s );
983                 keys[1] = NULL;
984         }
985
986         *keysp = keys;
987         return LDAP_SUCCESS;
988 }
989 #endif
990
991
992 static int
993 caseExactMatch(
994         int *matchp,
995         slap_mask_t flags,
996         Syntax *syntax,
997         MatchingRule *mr,
998         struct berval *value,
999         void *assertedValue )
1000 {
1001         *matchp = UTF8bvnormcmp( value, (struct berval *) assertedValue, LDAP_UTF8_NOCASEFOLD );
1002         return LDAP_SUCCESS;
1003 }
1004
1005 static int
1006 caseExactIgnoreSubstringsMatch(
1007         int *matchp,
1008         slap_mask_t flags,
1009         Syntax *syntax,
1010         MatchingRule *mr,
1011         struct berval *value,
1012         void *assertedValue )
1013 {
1014         int match = 0;
1015         SubstringsAssertion *sub = NULL;
1016         struct berval left = { 0, NULL };
1017         int i;
1018         ber_len_t inlen=0;
1019         char *nav = NULL;
1020         unsigned casefold;
1021
1022         casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
1023                 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1024
1025         if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1026                 match = 1;
1027                 goto done;
1028         }
1029         nav = left.bv_val;
1030
1031         sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1032         if( sub == NULL ) {
1033                 match = -1;
1034                 goto done;
1035         }
1036
1037         /* Add up asserted input length */
1038         if( sub->sa_initial.bv_val ) {
1039                 inlen += sub->sa_initial.bv_len;
1040         }
1041         if( sub->sa_any ) {
1042                 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1043                         inlen += sub->sa_any[i].bv_len;
1044                 }
1045         }
1046         if( sub->sa_final.bv_val ) {
1047                 inlen += sub->sa_final.bv_len;
1048         }
1049
1050         if( sub->sa_initial.bv_val ) {
1051                 if( inlen > left.bv_len ) {
1052                         match = 1;
1053                         goto done;
1054                 }
1055
1056                 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1057                         sub->sa_initial.bv_len );
1058
1059                 if( match != 0 ) {
1060                         goto done;
1061                 }
1062
1063                 left.bv_val += sub->sa_initial.bv_len;
1064                 left.bv_len -= sub->sa_initial.bv_len;
1065                 inlen -= sub->sa_initial.bv_len;
1066         }
1067
1068         if( sub->sa_final.bv_val ) {
1069                 if( inlen > left.bv_len ) {
1070                         match = 1;
1071                         goto done;
1072                 }
1073
1074                 match = memcmp( sub->sa_final.bv_val,
1075                         &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1076                         sub->sa_final.bv_len );
1077
1078                 if( match != 0 ) {
1079                         goto done;
1080                 }
1081
1082                 left.bv_len -= sub->sa_final.bv_len;
1083                 inlen -= sub->sa_final.bv_len;
1084         }
1085
1086         if( sub->sa_any ) {
1087                 for(i=0; sub->sa_any[i].bv_val; i++) {
1088                         ber_len_t idx;
1089                         char *p;
1090
1091 retry:
1092                         if( inlen > left.bv_len ) {
1093                                 /* not enough length */
1094                                 match = 1;
1095                                 goto done;
1096                         }
1097
1098                         if( sub->sa_any[i].bv_len == 0 ) {
1099                                 continue;
1100                         }
1101
1102                         p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1103                         if ( p == NULL ) {
1104                                 match = 1;
1105                                 goto done;
1106                         }
1107
1108                         idx = p - left.bv_val;
1109
1110                         if( idx >= left.bv_len ) {
1111                                 /* this shouldn't happen */
1112                                 free( nav );
1113                                 if ( sub->sa_final.bv_val )
1114                                         ch_free( sub->sa_final.bv_val );
1115                                 if ( sub->sa_any )
1116                                         ber_bvarray_free( sub->sa_any );
1117                                 if ( sub->sa_initial.bv_val )
1118                                         ch_free( sub->sa_initial.bv_val );
1119                                 ch_free( sub );
1120                                 return LDAP_OTHER;
1121                         }
1122
1123                         left.bv_val = p;
1124                         left.bv_len -= idx;
1125
1126                         if( sub->sa_any[i].bv_len > left.bv_len ) {
1127                                 /* not enough left */
1128                                 match = 1;
1129                                 goto done;
1130                         }
1131
1132                         match = memcmp( left.bv_val,
1133                                 sub->sa_any[i].bv_val,
1134                                 sub->sa_any[i].bv_len );
1135
1136                         if( match != 0 ) {
1137                                 left.bv_val++;
1138                                 left.bv_len--;
1139                                 goto retry;
1140                         }
1141
1142                         left.bv_val += sub->sa_any[i].bv_len;
1143                         left.bv_len -= sub->sa_any[i].bv_len;
1144                         inlen -= sub->sa_any[i].bv_len;
1145                 }
1146         }
1147
1148 done:
1149         free( nav );
1150         if( sub != NULL ) {
1151                 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1152                 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1153                 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1154                 ch_free( sub );
1155         }
1156         *matchp = match;
1157         return LDAP_SUCCESS;
1158 }
1159
1160 /* Index generation function */
1161 static int caseExactIgnoreIndexer(
1162         slap_mask_t use,
1163         slap_mask_t flags,
1164         Syntax *syntax,
1165         MatchingRule *mr,
1166         struct berval *prefix,
1167         BerVarray values,
1168         BerVarray *keysp )
1169 {
1170         int i;
1171         unsigned casefold;
1172         size_t slen, mlen;
1173         BerVarray keys;
1174         HASH_CONTEXT   HASHcontext;
1175         unsigned char   HASHdigest[HASH_BYTES];
1176         struct berval digest;
1177         digest.bv_val = HASHdigest;
1178         digest.bv_len = sizeof(HASHdigest);
1179
1180         for( i=0; values[i].bv_val != NULL; i++ ) {
1181                 /* empty - just count them */
1182         }
1183
1184         /* we should have at least one value at this point */
1185         assert( i > 0 );
1186
1187         keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1188
1189         slen = syntax->ssyn_oidlen;
1190         mlen = mr->smr_oidlen;
1191
1192         casefold = strcmp( mr->smr_oid, caseExactMatchOID )
1193                 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1194
1195         for( i=0; values[i].bv_val != NULL; i++ ) {
1196                 struct berval value;
1197                 UTF8bvnormalize( &values[i], &value, casefold );
1198
1199                 HASH_Init( &HASHcontext );
1200                 if( prefix != NULL && prefix->bv_len > 0 ) {
1201                         HASH_Update( &HASHcontext,
1202                                 prefix->bv_val, prefix->bv_len );
1203                 }
1204                 HASH_Update( &HASHcontext,
1205                         syntax->ssyn_oid, slen );
1206                 HASH_Update( &HASHcontext,
1207                         mr->smr_oid, mlen );
1208                 HASH_Update( &HASHcontext,
1209                         value.bv_val, value.bv_len );
1210                 HASH_Final( HASHdigest, &HASHcontext );
1211
1212                 free( value.bv_val );
1213
1214                 ber_dupbv( &keys[i], &digest );
1215         }
1216
1217         keys[i].bv_val = NULL;
1218         *keysp = keys;
1219         return LDAP_SUCCESS;
1220 }
1221
1222 /* Index generation function */
1223 static int caseExactIgnoreFilter(
1224         slap_mask_t use,
1225         slap_mask_t flags,
1226         Syntax *syntax,
1227         MatchingRule *mr,
1228         struct berval *prefix,
1229         void * assertValue,
1230         BerVarray *keysp )
1231 {
1232         unsigned casefold;
1233         size_t slen, mlen;
1234         BerVarray keys;
1235         HASH_CONTEXT   HASHcontext;
1236         unsigned char   HASHdigest[HASH_BYTES];
1237         struct berval value = { 0, NULL };
1238         struct berval digest;
1239
1240         digest.bv_val = HASHdigest;
1241         digest.bv_len = sizeof(HASHdigest);
1242
1243         slen = syntax->ssyn_oidlen;
1244         mlen = mr->smr_oidlen;
1245
1246         casefold = strcmp( mr->smr_oid, caseExactMatchOID )
1247                 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1248
1249         UTF8bvnormalize( (struct berval *) assertValue, &value, casefold );
1250         /* This usually happens if filter contains bad UTF8 */
1251         if( value.bv_val == NULL ) {
1252                 keys = ch_malloc( sizeof( struct berval ) );
1253                 keys[0].bv_val = NULL;
1254                 return LDAP_SUCCESS;
1255         }
1256
1257         keys = ch_malloc( sizeof( struct berval ) * 2 );
1258
1259         HASH_Init( &HASHcontext );
1260         if( prefix != NULL && prefix->bv_len > 0 ) {
1261                 HASH_Update( &HASHcontext,
1262                         prefix->bv_val, prefix->bv_len );
1263         }
1264         HASH_Update( &HASHcontext,
1265                 syntax->ssyn_oid, slen );
1266         HASH_Update( &HASHcontext,
1267                 mr->smr_oid, mlen );
1268         HASH_Update( &HASHcontext,
1269                 value.bv_val, value.bv_len );
1270         HASH_Final( HASHdigest, &HASHcontext );
1271
1272         ber_dupbv( keys, &digest );
1273         keys[1].bv_val = NULL;
1274
1275         free( value.bv_val );
1276
1277         *keysp = keys;
1278         return LDAP_SUCCESS;
1279 }
1280
1281 /* Substrings Index generation function */
1282 static int caseExactIgnoreSubstringsIndexer(
1283         slap_mask_t use,
1284         slap_mask_t flags,
1285         Syntax *syntax,
1286         MatchingRule *mr,
1287         struct berval *prefix,
1288         BerVarray values,
1289         BerVarray *keysp )
1290 {
1291         unsigned casefold;
1292         ber_len_t i, nkeys;
1293         size_t slen, mlen;
1294         BerVarray keys;
1295         BerVarray nvalues;
1296
1297         HASH_CONTEXT   HASHcontext;
1298         unsigned char   HASHdigest[HASH_BYTES];
1299         struct berval digest;
1300         digest.bv_val = HASHdigest;
1301         digest.bv_len = sizeof(HASHdigest);
1302
1303         nkeys=0;
1304
1305         for( i=0; values[i].bv_val != NULL; i++ ) {
1306                 /* empty - just count them */
1307         }
1308
1309         /* we should have at least one value at this point */
1310         assert( i > 0 );
1311
1312         casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
1313                 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1314
1315         nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1316         for( i=0; values[i].bv_val != NULL; i++ ) {
1317                 UTF8bvnormalize( &values[i], &nvalues[i], casefold );
1318         }
1319         nvalues[i].bv_val = NULL;
1320         values = nvalues;
1321
1322         for( i=0; values[i].bv_val != NULL; i++ ) {
1323                 /* count number of indices to generate */
1324                 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1325                         continue;
1326                 }
1327
1328                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1329                         if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1330                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1331                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1332                         } else {
1333                                 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1334                         }
1335                 }
1336
1337                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1338                         if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1339                                 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1340                         }
1341                 }
1342
1343                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
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
1353         if( nkeys == 0 ) {
1354                 /* no keys to generate */
1355                 *keysp = NULL;
1356                 ber_bvarray_free( nvalues );
1357                 return LDAP_SUCCESS;
1358         }
1359
1360         keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1361
1362         slen = syntax->ssyn_oidlen;
1363         mlen = mr->smr_oidlen;
1364
1365         nkeys=0;
1366         for( i=0; values[i].bv_val != NULL; i++ ) {
1367                 ber_len_t j,max;
1368
1369                 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1370
1371                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1372                         ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1373                 {
1374                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
1375                         max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1376
1377                         for( j=0; j<max; j++ ) {
1378                                 HASH_Init( &HASHcontext );
1379                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1380                                         HASH_Update( &HASHcontext,
1381                                                 prefix->bv_val, prefix->bv_len );
1382                                 }
1383
1384                                 HASH_Update( &HASHcontext,
1385                                         &pre, sizeof( pre ) );
1386                                 HASH_Update( &HASHcontext,
1387                                         syntax->ssyn_oid, slen );
1388                                 HASH_Update( &HASHcontext,
1389                                         mr->smr_oid, mlen );
1390                                 HASH_Update( &HASHcontext,
1391                                         &values[i].bv_val[j],
1392                                         SLAP_INDEX_SUBSTR_MAXLEN );
1393                                 HASH_Final( HASHdigest, &HASHcontext );
1394
1395                                 ber_dupbv( &keys[nkeys++], &digest );
1396                         }
1397                 }
1398
1399                 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1400                         ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1401
1402                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1403                         char pre;
1404
1405                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1406                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1407                                 HASH_Init( &HASHcontext );
1408                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1409                                         HASH_Update( &HASHcontext,
1410                                                 prefix->bv_val, prefix->bv_len );
1411                                 }
1412                                 HASH_Update( &HASHcontext,
1413                                         &pre, sizeof( pre ) );
1414                                 HASH_Update( &HASHcontext,
1415                                         syntax->ssyn_oid, slen );
1416                                 HASH_Update( &HASHcontext,
1417                                         mr->smr_oid, mlen );
1418                                 HASH_Update( &HASHcontext,
1419                                         values[i].bv_val, j );
1420                                 HASH_Final( HASHdigest, &HASHcontext );
1421
1422                                 ber_dupbv( &keys[nkeys++], &digest );
1423                         }
1424
1425                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1426                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1427                                 HASH_Init( &HASHcontext );
1428                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1429                                         HASH_Update( &HASHcontext,
1430                                                 prefix->bv_val, prefix->bv_len );
1431                                 }
1432                                 HASH_Update( &HASHcontext,
1433                                         &pre, sizeof( pre ) );
1434                                 HASH_Update( &HASHcontext,
1435                                         syntax->ssyn_oid, slen );
1436                                 HASH_Update( &HASHcontext,
1437                                         mr->smr_oid, mlen );
1438                                 HASH_Update( &HASHcontext,
1439                                         &values[i].bv_val[values[i].bv_len-j], j );
1440                                 HASH_Final( HASHdigest, &HASHcontext );
1441
1442                                 ber_dupbv( &keys[nkeys++], &digest );
1443                         }
1444
1445                 }
1446
1447         }
1448
1449         if( nkeys > 0 ) {
1450                 keys[nkeys].bv_val = NULL;
1451                 *keysp = keys;
1452         } else {
1453                 ch_free( keys );
1454                 *keysp = NULL;
1455         }
1456
1457         ber_bvarray_free( nvalues );
1458
1459         return LDAP_SUCCESS;
1460 }
1461
1462 static int caseExactIgnoreSubstringsFilter(
1463         slap_mask_t use,
1464         slap_mask_t flags,
1465         Syntax *syntax,
1466         MatchingRule *mr,
1467         struct berval *prefix,
1468         void * assertValue,
1469         BerVarray *keysp )
1470 {
1471         SubstringsAssertion *sa;
1472         char pre;
1473         unsigned casefold;
1474         ber_len_t nkeys = 0;
1475         size_t slen, mlen, klen;
1476         BerVarray keys;
1477         HASH_CONTEXT   HASHcontext;
1478         unsigned char   HASHdigest[HASH_BYTES];
1479         struct berval *value;
1480         struct berval digest;
1481
1482         casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
1483                 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1484
1485         sa = UTF8SubstringsassertionNormalize( assertValue, casefold );
1486         if( sa == NULL ) {
1487                 *keysp = NULL;
1488                 return LDAP_SUCCESS;
1489         }
1490
1491         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1492                 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1493         {
1494                 nkeys++;
1495         }
1496
1497         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1498                 ber_len_t i;
1499                 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1500                         if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1501                                 /* don't bother accounting for stepping */
1502                                 nkeys += sa->sa_any[i].bv_len -
1503                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1504                         }
1505                 }
1506         }
1507
1508         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1509                 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1510         {
1511                 nkeys++;
1512         }
1513
1514         if( nkeys == 0 ) {
1515                 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1516                 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1517                 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1518                 ch_free( sa );
1519                 *keysp = NULL;
1520                 return LDAP_SUCCESS;
1521         }
1522
1523         digest.bv_val = HASHdigest;
1524         digest.bv_len = sizeof(HASHdigest);
1525
1526         slen = syntax->ssyn_oidlen;
1527         mlen = mr->smr_oidlen;
1528
1529         keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1530         nkeys = 0;
1531
1532         if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1533                 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1534         {
1535                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1536                 value = &sa->sa_initial;
1537
1538                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1539                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1540
1541                 HASH_Init( &HASHcontext );
1542                 if( prefix != NULL && prefix->bv_len > 0 ) {
1543                         HASH_Update( &HASHcontext,
1544                                 prefix->bv_val, prefix->bv_len );
1545                 }
1546                 HASH_Update( &HASHcontext,
1547                         &pre, sizeof( pre ) );
1548                 HASH_Update( &HASHcontext,
1549                         syntax->ssyn_oid, slen );
1550                 HASH_Update( &HASHcontext,
1551                         mr->smr_oid, mlen );
1552                 HASH_Update( &HASHcontext,
1553                         value->bv_val, klen );
1554                 HASH_Final( HASHdigest, &HASHcontext );
1555
1556                 ber_dupbv( &keys[nkeys++], &digest );
1557         }
1558
1559         if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1560                 ber_len_t i, j;
1561                 pre = SLAP_INDEX_SUBSTR_PREFIX;
1562                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1563
1564                 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1565                         if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1566                                 continue;
1567                         }
1568
1569                         value = &sa->sa_any[i];
1570
1571                         for(j=0;
1572                                 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1573                                 j += SLAP_INDEX_SUBSTR_STEP )
1574                         {
1575                                 HASH_Init( &HASHcontext );
1576                                 if( prefix != NULL && prefix->bv_len > 0 ) {
1577                                         HASH_Update( &HASHcontext,
1578                                                 prefix->bv_val, prefix->bv_len );
1579                                 }
1580                                 HASH_Update( &HASHcontext,
1581                                         &pre, sizeof( pre ) );
1582                                 HASH_Update( &HASHcontext,
1583                                         syntax->ssyn_oid, slen );
1584                                 HASH_Update( &HASHcontext,
1585                                         mr->smr_oid, mlen );
1586                                 HASH_Update( &HASHcontext,
1587                                         &value->bv_val[j], klen ); 
1588                                 HASH_Final( HASHdigest, &HASHcontext );
1589
1590                                 ber_dupbv( &keys[nkeys++], &digest );
1591                         }
1592
1593                 }
1594         }
1595
1596         if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1597                 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1598         {
1599                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1600                 value = &sa->sa_final;
1601
1602                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1603                         ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1604
1605                 HASH_Init( &HASHcontext );
1606                 if( prefix != NULL && prefix->bv_len > 0 ) {
1607                         HASH_Update( &HASHcontext,
1608                                 prefix->bv_val, prefix->bv_len );
1609                 }
1610                 HASH_Update( &HASHcontext,
1611                         &pre, sizeof( pre ) );
1612                 HASH_Update( &HASHcontext,
1613                         syntax->ssyn_oid, slen );
1614                 HASH_Update( &HASHcontext,
1615                         mr->smr_oid, mlen );
1616                 HASH_Update( &HASHcontext,
1617                         &value->bv_val[value->bv_len-klen], klen );
1618                 HASH_Final( HASHdigest, &HASHcontext );
1619
1620                 ber_dupbv( &keys[nkeys++], &digest );
1621         }
1622
1623         if( nkeys > 0 ) {
1624                 keys[nkeys].bv_val = NULL;
1625                 *keysp = keys;
1626         } else {
1627                 ch_free( keys );
1628                 *keysp = NULL;
1629         }
1630         if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1631         if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1632         if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1633         ch_free( sa );
1634
1635         return LDAP_SUCCESS;
1636 }
1637
1638 static int
1639 caseIgnoreMatch(
1640         int *matchp,
1641         slap_mask_t flags,
1642         Syntax *syntax,
1643         MatchingRule *mr,
1644         struct berval *value,
1645         void *assertedValue )
1646 {
1647         *matchp = UTF8bvnormcmp( value, (struct berval *) assertedValue, LDAP_UTF8_CASEFOLD );
1648         return LDAP_SUCCESS;
1649 }
1650         
1651 static int
1652 oidValidate(
1653         Syntax *syntax,
1654         struct berval *val )
1655 {
1656         ber_len_t i;
1657
1658         if( val->bv_len == 0 ) {
1659                 /* disallow empty strings */
1660                 return LDAP_INVALID_SYNTAX;
1661         }
1662
1663         if( OID_LEADCHAR(val->bv_val[0]) ) {
1664                 int dot = 0;
1665                 for(i=1; i < val->bv_len; i++) {
1666                         if( OID_SEPARATOR( val->bv_val[i] ) ) {
1667                                 if( dot++ ) return 1;
1668                         } else if ( OID_CHAR( val->bv_val[i] ) ) {
1669                                 dot = 0;
1670                         } else {
1671                                 return LDAP_INVALID_SYNTAX;
1672                         }
1673                 }
1674
1675                 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1676
1677         } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1678                 for(i=1; i < val->bv_len; i++) {
1679                         if( !DESC_CHAR(val->bv_val[i] ) ) {
1680                                 return LDAP_INVALID_SYNTAX;
1681                         }
1682                 }
1683
1684                 return LDAP_SUCCESS;
1685         }
1686         
1687         return LDAP_INVALID_SYNTAX;
1688 }
1689
1690 static int
1691 integerMatch(
1692         int *matchp,
1693         slap_mask_t flags,
1694         Syntax *syntax,
1695         MatchingRule *mr,
1696         struct berval *value,
1697         void *assertedValue )
1698 {
1699         char *v, *av;
1700         int vsign=0, avsign=0;
1701         struct berval *asserted;
1702         ber_len_t vlen, avlen;
1703
1704
1705         /* Start off pessimistic */
1706         *matchp = 1;
1707
1708         /* Skip past leading spaces/zeros, and get the sign of the *value number */
1709         v = value->bv_val;
1710         vlen = value->bv_len;
1711         while( vlen ) {
1712                 if( ASCII_SPACE(*v) || ( *v == '0' )) {
1713                         /* empty -- skip spaces */
1714                 }
1715                 else if ( *v == '+' ) {
1716                         vsign = 1;
1717                 }
1718                 else if ( *v == '-' ) {
1719                         vsign = -1;
1720                 }
1721                 else if ( ASCII_DIGIT(*v) ) {
1722                         if ( vsign == 0 ) vsign = 1;
1723                         vsign *= 2;
1724                         break;
1725                 }
1726                 v++;
1727                 vlen--;
1728         }
1729
1730         /* Skip past leading spaces/zeros, and get the sign of the *assertedValue
1731            number */
1732         asserted = (struct berval *) assertedValue;
1733         av = asserted->bv_val;
1734         avlen = asserted->bv_len;
1735         while( avlen ) {
1736                 if( ASCII_SPACE(*av) || ( *av == '0' )) {
1737                         /* empty -- skip spaces */
1738                 }
1739                 else if ( *av == '+' ) {
1740                         avsign = 1;
1741                 }
1742                 else if ( *av == '-' ) {
1743                         avsign = -1;
1744                 }
1745                 else if ( ASCII_DIGIT(*av) ) {
1746                         if ( avsign == 0 ) avsign = 1;
1747                         avsign *= 2;
1748                         break;
1749                 }
1750                 av++;
1751                 avlen--;
1752         }
1753
1754         /* The two ?sign vars are now one of :
1755            -2  negative non-zero number
1756            -1  -0   \
1757             0   0   collapse these three to 0
1758            +1  +0   /
1759            +2  positive non-zero number
1760         */
1761         if ( abs( vsign ) == 1 ) vsign = 0;
1762         if ( abs( avsign ) == 1 ) avsign = 0;
1763
1764         if( vsign != avsign ) return LDAP_SUCCESS;
1765
1766         /* Check the significant digits */
1767         while( vlen && avlen ) {
1768                 if( *v != *av ) break;
1769                 v++;
1770                 vlen--;
1771                 av++;
1772                 avlen--;
1773         }
1774
1775         /* If all digits compared equal, the numbers are equal */
1776         if(( vlen == 0 ) && ( avlen == 0 )) {
1777                 *matchp = 0;
1778         }
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_str2upper( 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_str2upper( 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_str2upper( 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_str2upper( 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_str2upper( 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_str2upper( 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 static int
3930 utcTimeNormalize(
3931         Syntax *syntax,
3932         struct berval *val,
3933         struct berval *normalized )
3934 {
3935         int parts[9], rc;
3936
3937         rc = check_time_syntax(val, 1, parts);
3938         if (rc != LDAP_SUCCESS) {
3939                 return rc;
3940         }
3941
3942         normalized->bv_val = ch_malloc( 14 );
3943         if ( normalized->bv_val == NULL ) {
3944                 return LBER_ERROR_MEMORY;
3945         }
3946
3947         sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3948                 parts[1], parts[2] + 1, parts[3] + 1,
3949                 parts[4], parts[5], parts[6] );
3950         normalized->bv_len = 13;
3951
3952         return LDAP_SUCCESS;
3953 }
3954
3955 static int
3956 utcTimeValidate(
3957         Syntax *syntax,
3958         struct berval *in )
3959 {
3960         int parts[9];
3961
3962         return check_time_syntax(in, 1, parts);
3963 }
3964
3965 static int
3966 generalizedTimeValidate(
3967         Syntax *syntax,
3968         struct berval *in )
3969 {
3970         int parts[9];
3971
3972         return check_time_syntax(in, 0, parts);
3973 }
3974
3975 static int
3976 generalizedTimeNormalize(
3977         Syntax *syntax,
3978         struct berval *val,
3979         struct berval *normalized )
3980 {
3981         int parts[9], rc;
3982
3983         rc = check_time_syntax(val, 0, parts);
3984         if (rc != LDAP_SUCCESS) {
3985                 return rc;
3986         }
3987
3988         normalized->bv_val = ch_malloc( 16 );
3989         if ( normalized->bv_val == NULL ) {
3990                 return LBER_ERROR_MEMORY;
3991         }
3992
3993         sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
3994                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
3995                 parts[4], parts[5], parts[6] );
3996         normalized->bv_len = 15;
3997
3998         return LDAP_SUCCESS;
3999 }
4000
4001 static int
4002 nisNetgroupTripleValidate(
4003         Syntax *syntax,
4004         struct berval *val )
4005 {
4006         char *p, *e;
4007         int commas = 0;
4008
4009         if ( val->bv_len == 0 ) {
4010                 return LDAP_INVALID_SYNTAX;
4011         }
4012
4013         p = (char *)val->bv_val;
4014         e = p + val->bv_len;
4015
4016         if ( *p != '(' /*')'*/ ) {
4017                 return LDAP_INVALID_SYNTAX;
4018         }
4019
4020         for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4021                 if ( *p == ',' ) {
4022                         commas++;
4023                         if ( commas > 2 ) {
4024                                 return LDAP_INVALID_SYNTAX;
4025                         }
4026
4027                 } else if ( !ATTR_CHAR( *p ) ) {
4028                         return LDAP_INVALID_SYNTAX;
4029                 }
4030         }
4031
4032         if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4033                 return LDAP_INVALID_SYNTAX;
4034         }
4035
4036         p++;
4037
4038         if (p != e) {
4039                 return LDAP_INVALID_SYNTAX;
4040         }
4041
4042         return LDAP_SUCCESS;
4043 }
4044
4045 static int
4046 bootParameterValidate(
4047         Syntax *syntax,
4048         struct berval *val )
4049 {
4050         char *p, *e;
4051
4052         if ( val->bv_len == 0 ) {
4053                 return LDAP_INVALID_SYNTAX;
4054         }
4055
4056         p = (char *)val->bv_val;
4057         e = p + val->bv_len;
4058
4059         /* key */
4060         for (; ( p < e ) && ( *p != '=' ); p++ ) {
4061                 if ( !ATTR_CHAR( *p ) ) {
4062                         return LDAP_INVALID_SYNTAX;
4063                 }
4064         }
4065
4066         if ( *p != '=' ) {
4067                 return LDAP_INVALID_SYNTAX;
4068         }
4069
4070         /* server */
4071         for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4072                 if ( !ATTR_CHAR( *p ) ) {
4073                         return LDAP_INVALID_SYNTAX;
4074                 }
4075         }
4076
4077         if ( *p != ':' ) {
4078                 return LDAP_INVALID_SYNTAX;
4079         }
4080
4081         /* path */
4082         for ( p++; p < e; p++ ) {
4083                 if ( !ATTR_CHAR( *p ) ) {
4084                         return LDAP_INVALID_SYNTAX;
4085                 }
4086         }
4087
4088         return LDAP_SUCCESS;
4089 }
4090
4091 static struct syntax_defs_rec {
4092         char *sd_desc;
4093 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4094 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4095         int sd_flags;
4096         slap_syntax_validate_func *sd_validate;
4097         slap_syntax_transform_func *sd_normalize;
4098         slap_syntax_transform_func *sd_pretty;
4099 #ifdef SLAPD_BINARY_CONVERSION
4100         slap_syntax_transform_func *sd_ber2str;
4101         slap_syntax_transform_func *sd_str2ber;
4102 #endif
4103 } syntax_defs[] = {
4104         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4105                 X_BINARY X_NOT_H_R ")",
4106                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4107         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4108                 0, NULL, NULL, NULL},
4109         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4110                 0, NULL, NULL, NULL},
4111         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4112                 X_NOT_H_R ")",
4113                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4114         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4115                 X_NOT_H_R ")",
4116                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4117         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4118                 0, bitStringValidate, bitStringNormalize, NULL },
4119         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4120                 0, booleanValidate, NULL, NULL},
4121         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4122                 X_BINARY X_NOT_H_R ")",
4123                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4124         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4125                 X_BINARY X_NOT_H_R ")",
4126                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4127         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4128                 X_BINARY X_NOT_H_R ")",
4129                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4130         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4131                 0, countryStringValidate, IA5StringNormalize, NULL},
4132         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4133                 0, dnValidate, dnNormalize2, dnPretty2},
4134         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4135                 0, NULL, NULL, NULL},
4136         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4137                 0, NULL, NULL, NULL},
4138         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4139                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4140         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4141                 0, NULL, NULL, NULL},
4142         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4143                 0, NULL, NULL, NULL},
4144         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4145                 0, NULL, NULL, NULL},
4146         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4147                 0, NULL, NULL, NULL},
4148         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4149                 0, NULL, NULL, NULL},
4150         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4151                 0, printablesStringValidate, IA5StringNormalize, NULL},
4152         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4153                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4154         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4155                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4156         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4157                 0, NULL, NULL, NULL},
4158         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4159                 0, IA5StringValidate, IA5StringNormalize, NULL},
4160         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4161                 0, integerValidate, integerNormalize, NULL},
4162         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4163                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4164         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4165                 0, NULL, NULL, NULL},
4166         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4167                 0, NULL, NULL, NULL},
4168         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4169                 0, NULL, NULL, NULL},
4170         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4171                 0, NULL, NULL, NULL},
4172         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4173                 0, NULL, NULL, NULL},
4174         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4175                 0, nameUIDValidate, nameUIDNormalize, NULL},
4176         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4177                 0, NULL, NULL, NULL},
4178         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4179                 0, numericStringValidate, numericStringNormalize, NULL},
4180         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4181                 0, NULL, NULL, NULL},
4182         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4183                 0, oidValidate, NULL, NULL},
4184         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4185                 0, IA5StringValidate, IA5StringNormalize, NULL},
4186         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4187                 0, blobValidate, NULL, NULL},
4188         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4189                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4190         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4191                 0, NULL, NULL, NULL},
4192         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4193                 0, NULL, NULL, NULL},
4194         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4195                 0, printableStringValidate, IA5StringNormalize, NULL},
4196         {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4197                 X_BINARY X_NOT_H_R ")",
4198                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4199         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4200                 X_BINARY X_NOT_H_R ")",
4201                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4202         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4203                 0, printableStringValidate, IA5StringNormalize, NULL},
4204         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4205                 0, NULL, NULL, NULL},
4206         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4207                 0, printablesStringValidate, IA5StringNormalize, NULL},
4208         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4209                 0, utcTimeValidate, utcTimeNormalize, NULL},
4210         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4211                 0, NULL, NULL, NULL},
4212         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4213                 0, NULL, NULL, NULL},
4214         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4215                 0, NULL, NULL, NULL},
4216         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4217                 0, NULL, NULL, NULL},
4218         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4219                 0, NULL, NULL, NULL},
4220
4221         /* RFC 2307 NIS Syntaxes */
4222         {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Netgroup Triple' )",
4223                 0, nisNetgroupTripleValidate, NULL, NULL},
4224         {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
4225                 0, bootParameterValidate, NULL, NULL},
4226
4227 #ifdef HAVE_TLS
4228         /* From PKIX */
4229         /* These OIDs are not published yet, but will be in the next
4230          * I-D for PKIX LDAPv3 schema as have been advanced by David
4231          * Chadwick in private mail.
4232          */
4233         {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4234                 0, NULL, NULL, NULL},
4235 #endif
4236
4237         /* OpenLDAP Experimental Syntaxes */
4238 #ifdef SLAPD_ACI_ENABLED
4239         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4240                 SLAP_SYNTAX_HIDE,
4241                 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4242                 NULL, NULL},
4243 #endif
4244
4245 #ifdef SLAPD_AUTHPASSWD
4246         /* needs updating */
4247         {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4248                 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4249 #endif
4250
4251         /* OpenLDAP Void Syntax */
4252         {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4253                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4254         {NULL, 0, NULL, NULL, NULL}
4255 };
4256
4257 /*
4258  * Other matching rules in X.520 that we do not use (yet):
4259  *
4260  * 2.5.13.9             numericStringOrderingMatch
4261  * 2.5.13.15    integerOrderingMatch
4262  * 2.5.13.18    octetStringOrderingMatch
4263  * 2.5.13.19    octetStringSubstringsMatch
4264  * 2.5.13.25    uTCTimeMatch
4265  * 2.5.13.26    uTCTimeOrderingMatch
4266  * 2.5.13.31    directoryStringFirstComponentMatch
4267  * 2.5.13.32    wordMatch
4268  * 2.5.13.33    keywordMatch
4269  * 2.5.13.35    certificateMatch
4270  * 2.5.13.36    certificatePairExactMatch
4271  * 2.5.13.37    certificatePairMatch
4272  * 2.5.13.38    certificateListExactMatch
4273  * 2.5.13.39    certificateListMatch
4274  * 2.5.13.40    algorithmIdentifierMatch
4275  * 2.5.13.41    storedPrefixMatch
4276  * 2.5.13.42    attributeCertificateMatch
4277  * 2.5.13.43    readerAndKeyIDMatch
4278  * 2.5.13.44    attributeIntegrityMatch
4279  */
4280 static struct mrule_defs_rec {
4281         char *                                          mrd_desc;
4282         slap_mask_t                                     mrd_usage;
4283         slap_mr_convert_func *          mrd_convert;
4284         slap_mr_normalize_func *        mrd_normalize;
4285         slap_mr_match_func *            mrd_match;
4286         slap_mr_indexer_func *          mrd_indexer;
4287         slap_mr_filter_func *           mrd_filter;
4288
4289         char *                                          mrd_associated;
4290 } mrule_defs[] = {
4291         /*
4292          * EQUALITY matching rules must be listed after associated APPROX
4293          * matching rules.  So, we list all APPROX matching rules first.
4294          */
4295         {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4296                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4297                 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4298                 NULL, NULL,
4299                 directoryStringApproxMatch,
4300                 directoryStringApproxIndexer, 
4301                 directoryStringApproxFilter,
4302                 NULL},
4303
4304         {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4305                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4306                 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4307                 NULL, NULL,
4308                 IA5StringApproxMatch,
4309                 IA5StringApproxIndexer, 
4310                 IA5StringApproxFilter,
4311                 NULL},
4312
4313         /*
4314          * Other matching rules
4315          */
4316         
4317         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4318                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4319                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4320                 NULL, NULL,
4321                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4322                 NULL},
4323
4324         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4325                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4326                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4327                 NULL, NULL,
4328                 dnMatch, dnIndexer, dnFilter,
4329                 NULL},
4330
4331         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4332                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4333                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4334                 NULL, NULL,
4335                 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4336                 directoryStringApproxMatchOID },
4337
4338         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4339                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4340                 SLAP_MR_ORDERING,
4341                 NULL, NULL,
4342                 caseIgnoreOrderingMatch, NULL, NULL,
4343                 NULL},
4344
4345         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4346                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4347                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4348                 NULL, NULL,
4349                 caseExactIgnoreSubstringsMatch,
4350                 caseExactIgnoreSubstringsIndexer,
4351                 caseExactIgnoreSubstringsFilter,
4352                 NULL},
4353
4354         {"( 2.5.13.5 NAME 'caseExactMatch' "
4355                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4356                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4357                 NULL, NULL,
4358                 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4359                 directoryStringApproxMatchOID },
4360
4361         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4362                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4363                 SLAP_MR_ORDERING,
4364                 NULL, NULL,
4365                 caseExactOrderingMatch, NULL, NULL,
4366                 NULL},
4367
4368         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4369                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4370                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4371                 NULL, NULL,
4372                 caseExactIgnoreSubstringsMatch,
4373                 caseExactIgnoreSubstringsIndexer,
4374                 caseExactIgnoreSubstringsFilter,
4375                 NULL},
4376
4377         {"( 2.5.13.8 NAME 'numericStringMatch' "
4378                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4379                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4380                 NULL, NULL,
4381                 caseIgnoreIA5Match,
4382                 caseIgnoreIA5Indexer,
4383                 caseIgnoreIA5Filter,
4384                 NULL},
4385
4386         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4387                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4388                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4389                 NULL, NULL,
4390                 caseIgnoreIA5SubstringsMatch,
4391                 caseIgnoreIA5SubstringsIndexer,
4392                 caseIgnoreIA5SubstringsFilter,
4393                 NULL},
4394
4395         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4396                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4397                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4398                 NULL, NULL,
4399                 caseIgnoreListMatch, NULL, NULL,
4400                 NULL},
4401
4402         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4403                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4404                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4405                 NULL, NULL,
4406                 caseIgnoreListSubstringsMatch, NULL, NULL,
4407                 NULL},
4408
4409         {"( 2.5.13.13 NAME 'booleanMatch' "
4410                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4411                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4412                 NULL, NULL,
4413                 booleanMatch, NULL, NULL,
4414                 NULL},
4415
4416         {"( 2.5.13.14 NAME 'integerMatch' "
4417                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4418                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4419                 NULL, NULL,
4420                 integerMatch, integerIndexer, integerFilter,
4421                 NULL},
4422
4423         {"( 2.5.13.16 NAME 'bitStringMatch' "
4424                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4425                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4426                 NULL, NULL,
4427                 bitStringMatch, bitStringIndexer, bitStringFilter,
4428                 NULL},
4429
4430         {"( 2.5.13.17 NAME 'octetStringMatch' "
4431                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4432                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4433                 NULL, NULL,
4434                 octetStringMatch, octetStringIndexer, octetStringFilter,
4435                 NULL},
4436
4437         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4438                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4439                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4440                 NULL, NULL,
4441                 telephoneNumberMatch,
4442                 telephoneNumberIndexer,
4443                 telephoneNumberFilter,
4444                 NULL},
4445
4446         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4447                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4448                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4449                 NULL, NULL,
4450                 telephoneNumberSubstringsMatch,
4451                 telephoneNumberSubstringsIndexer,
4452                 telephoneNumberSubstringsFilter,
4453                 NULL},
4454
4455         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4456                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4457                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4458                 NULL, NULL,
4459                 NULL, NULL, NULL,
4460                 NULL},
4461
4462         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4463                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4464                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4465                 NULL, NULL,
4466                 uniqueMemberMatch, NULL, NULL,
4467                 NULL},
4468
4469         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4470                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4471                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4472                 NULL, NULL,
4473                 protocolInformationMatch, NULL, NULL,
4474                 NULL},
4475
4476         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4477                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4478                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4479                 NULL, NULL,
4480                 generalizedTimeMatch, NULL, NULL,
4481                 NULL},
4482
4483         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4484                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4485                 SLAP_MR_ORDERING,
4486                 NULL, NULL,
4487                 generalizedTimeOrderingMatch, NULL, NULL,
4488                 NULL},
4489
4490         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4491                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4492                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4493                 NULL, NULL,
4494                 integerFirstComponentMatch, NULL, NULL,
4495                 NULL},
4496
4497         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4498                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4499                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4500                 NULL, NULL,
4501                 objectIdentifierFirstComponentMatch, NULL, NULL,
4502                 NULL},
4503
4504 #ifdef HAVE_TLS
4505         {"( 2.5.13.34 NAME 'certificateExactMatch' "
4506                 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4507                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4508                 certificateExactConvert, NULL,
4509                 certificateExactMatch,
4510                 certificateExactIndexer, certificateExactFilter,
4511                 NULL},
4512 #endif
4513
4514         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4515                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4516                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4517                 NULL, NULL,
4518                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4519                 IA5StringApproxMatchOID },
4520
4521         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4522                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4523                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4524                 NULL, NULL,
4525                 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4526                 IA5StringApproxMatchOID },
4527
4528         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4529                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4530                 SLAP_MR_SUBSTR,
4531                 NULL, NULL,
4532                 caseIgnoreIA5SubstringsMatch,
4533                 caseIgnoreIA5SubstringsIndexer,
4534                 caseIgnoreIA5SubstringsFilter,
4535                 NULL},
4536
4537         {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4538                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4539                 SLAP_MR_SUBSTR,
4540                 NULL, NULL,
4541                 caseExactIA5SubstringsMatch,
4542                 caseExactIA5SubstringsIndexer,
4543                 caseExactIA5SubstringsFilter,
4544                 NULL},
4545
4546 #ifdef SLAPD_AUTHPASSWD
4547         /* needs updating */
4548         {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4549                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4550                 SLAP_MR_EQUALITY,
4551                 NULL, NULL,
4552                 authPasswordMatch, NULL, NULL,
4553                 NULL},
4554 #endif
4555
4556 #ifdef SLAPD_ACI_ENABLED
4557         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4558                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4559                 SLAP_MR_EQUALITY,
4560                 NULL, NULL,
4561                 OpenLDAPaciMatch, NULL, NULL,
4562                 NULL},
4563 #endif
4564
4565         {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4566                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4567                 SLAP_MR_EXT,
4568                 NULL, NULL,
4569                 integerBitAndMatch, NULL, NULL,
4570                 NULL},
4571
4572         {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4573                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4574                 SLAP_MR_EXT,
4575                 NULL, NULL,
4576                 integerBitOrMatch, NULL, NULL,
4577                 NULL},
4578
4579         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4580 };
4581
4582 int
4583 slap_schema_init( void )
4584 {
4585         int             res;
4586         int             i;
4587
4588         /* we should only be called once (from main) */
4589         assert( schema_init_done == 0 );
4590
4591         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4592                 res = register_syntax( syntax_defs[i].sd_desc,
4593                         syntax_defs[i].sd_flags,
4594                         syntax_defs[i].sd_validate,
4595                         syntax_defs[i].sd_normalize,
4596                         syntax_defs[i].sd_pretty
4597 #ifdef SLAPD_BINARY_CONVERSION
4598                         ,
4599                         syntax_defs[i].sd_ber2str,
4600                         syntax_defs[i].sd_str2ber
4601 #endif
4602                 );
4603
4604                 if ( res ) {
4605                         fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4606                                  syntax_defs[i].sd_desc );
4607                         return LDAP_OTHER;
4608                 }
4609         }
4610
4611         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4612                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4613                         fprintf( stderr,
4614                                 "slap_schema_init: Ingoring unusable matching rule %s\n",
4615                                  mrule_defs[i].mrd_desc );
4616                         continue;
4617                 }
4618
4619                 res = register_matching_rule(
4620                         mrule_defs[i].mrd_desc,
4621                         mrule_defs[i].mrd_usage,
4622                         mrule_defs[i].mrd_convert,
4623                         mrule_defs[i].mrd_normalize,
4624                         mrule_defs[i].mrd_match,
4625                         mrule_defs[i].mrd_indexer,
4626                         mrule_defs[i].mrd_filter,
4627                         mrule_defs[i].mrd_associated );
4628
4629                 if ( res ) {
4630                         fprintf( stderr,
4631                                 "slap_schema_init: Error registering matching rule %s\n",
4632                                  mrule_defs[i].mrd_desc );
4633                         return LDAP_OTHER;
4634                 }
4635         }
4636
4637         res = slap_schema_load();
4638         schema_init_done = 1;
4639         return res;
4640 }
4641
4642 void
4643 schema_destroy( void )
4644 {
4645         oidm_destroy();
4646         oc_destroy();
4647         at_destroy();
4648         mr_destroy();
4649         syn_destroy();
4650 }