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