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