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