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