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