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