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