]> git.sur5r.net Git - openldap/blob - servers/slapd/schema_init.c
ITS#1712, rewritten dn_openssl2ldap(). Added dnDCEnormalize(), used by
[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 );
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         ber_mem2bv( p, val->bv_len - (p - val->bv_val), 1, normalized );
552         e = normalized->bv_val + val->bv_len - (p - val->bv_val);
553
554         assert( normalized->bv_len );
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         size_t slen, mlen;
2801         BerVarray keys;
2802         HASH_CONTEXT   HASHcontext;
2803         unsigned char   HASHdigest[HASH_BYTES];
2804         struct berval digest;
2805         digest.bv_val = HASHdigest;
2806         digest.bv_len = sizeof(HASHdigest);
2807
2808         /* we should have at least one value at this point */
2809         assert( values != NULL && values[0].bv_val != NULL );
2810
2811         for( i=0; values[i].bv_val != NULL; i++ ) {
2812                 /* just count them */
2813         }
2814
2815         keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2816
2817         slen = syntax->ssyn_oidlen;
2818         mlen = mr->smr_oidlen;
2819
2820         for( i=0; values[i].bv_val != NULL; i++ ) {
2821                 struct berval value;
2822                 ber_dupbv( &value, &values[i] );
2823                 ldap_pvt_str2lower( value.bv_val );
2824
2825                 HASH_Init( &HASHcontext );
2826                 if( prefix != NULL && prefix->bv_len > 0 ) {
2827                         HASH_Update( &HASHcontext,
2828                                 prefix->bv_val, prefix->bv_len );
2829                 }
2830                 HASH_Update( &HASHcontext,
2831                         syntax->ssyn_oid, slen );
2832                 HASH_Update( &HASHcontext,
2833                         mr->smr_oid, mlen );
2834                 HASH_Update( &HASHcontext,
2835                         value.bv_val, value.bv_len );
2836                 HASH_Final( HASHdigest, &HASHcontext );
2837
2838                 free( value.bv_val );
2839
2840                 ber_dupbv( &keys[i], &digest );
2841         }
2842
2843         keys[i].bv_val = NULL;
2844         *keysp = keys;
2845         return LDAP_SUCCESS;
2846 }
2847
2848 /* Index generation function */
2849 static int caseIgnoreIA5Filter(
2850         slap_mask_t use,
2851         slap_mask_t flags,
2852         Syntax *syntax,
2853         MatchingRule *mr,
2854         struct berval *prefix,
2855         void * assertValue,
2856         BerVarray *keysp )
2857 {
2858         size_t slen, mlen;
2859         BerVarray keys;
2860         HASH_CONTEXT   HASHcontext;
2861         unsigned char   HASHdigest[HASH_BYTES];
2862         struct berval value;
2863         struct berval digest;
2864         digest.bv_val = HASHdigest;
2865         digest.bv_len = sizeof(HASHdigest);
2866
2867         slen = syntax->ssyn_oidlen;
2868         mlen = mr->smr_oidlen;
2869
2870         ber_dupbv( &value, (struct berval *) assertValue );
2871         ldap_pvt_str2lower( value.bv_val );
2872
2873         keys = ch_malloc( sizeof( struct berval ) * 2 );
2874
2875         HASH_Init( &HASHcontext );
2876         if( prefix != NULL && prefix->bv_len > 0 ) {
2877                 HASH_Update( &HASHcontext,
2878                         prefix->bv_val, prefix->bv_len );
2879         }
2880         HASH_Update( &HASHcontext,
2881                 syntax->ssyn_oid, slen );
2882         HASH_Update( &HASHcontext,
2883                 mr->smr_oid, mlen );
2884         HASH_Update( &HASHcontext,
2885                 value.bv_val, value.bv_len );
2886         HASH_Final( HASHdigest, &HASHcontext );
2887
2888         ber_dupbv( &keys[0], &digest );
2889         keys[1].bv_val = NULL;
2890
2891         free( value.bv_val );
2892
2893         *keysp = keys;
2894
2895         return LDAP_SUCCESS;
2896 }
2897
2898 /* Substrings Index generation function */
2899 static int caseIgnoreIA5SubstringsIndexer(
2900         slap_mask_t use,
2901         slap_mask_t flags,
2902         Syntax *syntax,
2903         MatchingRule *mr,
2904         struct berval *prefix,
2905         BerVarray values,
2906         BerVarray *keysp )
2907 {
2908         ber_len_t i, nkeys;
2909         size_t slen, mlen;
2910         BerVarray keys;
2911         HASH_CONTEXT   HASHcontext;
2912         unsigned char   HASHdigest[HASH_BYTES];
2913         struct berval digest;
2914         digest.bv_val = HASHdigest;
2915         digest.bv_len = sizeof(HASHdigest);
2916
2917         /* we should have at least one value at this point */
2918         assert( values != NULL && values[0].bv_val != NULL );
2919
2920         nkeys=0;
2921         for( i=0; values[i].bv_val != NULL; i++ ) {
2922                 /* count number of indices to generate */
2923                 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2924                         continue;
2925                 }
2926
2927                 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2928                         if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2929                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2930                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2931                         } else {
2932                                 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2933                         }
2934                 }
2935
2936                 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2937                         if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2938                                 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2939                         }
2940                 }
2941
2942                 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2943                         if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2944                                 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2945                                         ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2946                         } else {
2947                                 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2948                         }
2949                 }
2950         }
2951
2952         if( nkeys == 0 ) {
2953                 /* no keys to generate */
2954                 *keysp = NULL;
2955                 return LDAP_SUCCESS;
2956         }
2957
2958         keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2959
2960         slen = syntax->ssyn_oidlen;
2961         mlen = mr->smr_oidlen;
2962
2963         nkeys=0;
2964         for( i=0; values[i].bv_val != NULL; i++ ) {
2965                 int j,max;
2966                 struct berval value;
2967
2968                 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2969
2970                 ber_dupbv( &value, &values[i] );
2971                 ldap_pvt_str2lower( value.bv_val );
2972
2973                 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2974                         ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2975                 {
2976                         char pre = SLAP_INDEX_SUBSTR_PREFIX;
2977                         max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2978
2979                         for( j=0; j<max; j++ ) {
2980                                 HASH_Init( &HASHcontext );
2981                                 if( prefix != NULL && prefix->bv_len > 0 ) {
2982                                         HASH_Update( &HASHcontext,
2983                                                 prefix->bv_val, prefix->bv_len );
2984                                 }
2985
2986                                 HASH_Update( &HASHcontext,
2987                                         &pre, sizeof( pre ) );
2988                                 HASH_Update( &HASHcontext,
2989                                         syntax->ssyn_oid, slen );
2990                                 HASH_Update( &HASHcontext,
2991                                         mr->smr_oid, mlen );
2992                                 HASH_Update( &HASHcontext,
2993                                         &value.bv_val[j],
2994                                         SLAP_INDEX_SUBSTR_MAXLEN );
2995                                 HASH_Final( HASHdigest, &HASHcontext );
2996
2997                                 ber_dupbv( &keys[nkeys++], &digest );
2998                         }
2999                 }
3000
3001                 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3002                         ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3003
3004                 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3005                         char pre;
3006
3007                         if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3008                                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3009                                 HASH_Init( &HASHcontext );
3010                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3011                                         HASH_Update( &HASHcontext,
3012                                                 prefix->bv_val, prefix->bv_len );
3013                                 }
3014                                 HASH_Update( &HASHcontext,
3015                                         &pre, sizeof( pre ) );
3016                                 HASH_Update( &HASHcontext,
3017                                         syntax->ssyn_oid, slen );
3018                                 HASH_Update( &HASHcontext,
3019                                         mr->smr_oid, mlen );
3020                                 HASH_Update( &HASHcontext,
3021                                         value.bv_val, j );
3022                                 HASH_Final( HASHdigest, &HASHcontext );
3023
3024                                 ber_dupbv( &keys[nkeys++], &digest );
3025                         }
3026
3027                         if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3028                                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3029                                 HASH_Init( &HASHcontext );
3030                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3031                                         HASH_Update( &HASHcontext,
3032                                                 prefix->bv_val, prefix->bv_len );
3033                                 }
3034                                 HASH_Update( &HASHcontext,
3035                                         &pre, sizeof( pre ) );
3036                                 HASH_Update( &HASHcontext,
3037                                         syntax->ssyn_oid, slen );
3038                                 HASH_Update( &HASHcontext,
3039                                         mr->smr_oid, mlen );
3040                                 HASH_Update( &HASHcontext,
3041                                         &value.bv_val[value.bv_len-j], j );
3042                                 HASH_Final( HASHdigest, &HASHcontext );
3043
3044                                 ber_dupbv( &keys[nkeys++], &digest );
3045                         }
3046
3047                 }
3048
3049                 free( value.bv_val );
3050         }
3051
3052         if( nkeys > 0 ) {
3053                 keys[nkeys].bv_val = NULL;
3054                 *keysp = keys;
3055         } else {
3056                 ch_free( keys );
3057                 *keysp = NULL;
3058         }
3059
3060         return LDAP_SUCCESS;
3061 }
3062
3063 static int caseIgnoreIA5SubstringsFilter(
3064         slap_mask_t use,
3065         slap_mask_t flags,
3066         Syntax *syntax,
3067         MatchingRule *mr,
3068         struct berval *prefix,
3069         void * assertValue,
3070         BerVarray *keysp )
3071 {
3072         SubstringsAssertion *sa = assertValue;
3073         char pre;
3074         ber_len_t nkeys = 0;
3075         size_t slen, mlen, klen;
3076         BerVarray keys;
3077         HASH_CONTEXT   HASHcontext;
3078         unsigned char   HASHdigest[HASH_BYTES];
3079         struct berval value;
3080         struct berval digest;
3081
3082         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3083                 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3084         {
3085                 nkeys++;
3086         }
3087
3088         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3089                 ber_len_t i;
3090                 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3091                         if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3092                                 /* don't bother accounting for stepping */
3093                                 nkeys += sa->sa_any[i].bv_len -
3094                                         ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3095                         }
3096                 }
3097         }
3098
3099         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3100                 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3101         {
3102                 nkeys++;
3103         }
3104
3105         if( nkeys == 0 ) {
3106                 *keysp = NULL;
3107                 return LDAP_SUCCESS;
3108         }
3109
3110         digest.bv_val = HASHdigest;
3111         digest.bv_len = sizeof(HASHdigest);
3112
3113         slen = syntax->ssyn_oidlen;
3114         mlen = mr->smr_oidlen;
3115
3116         keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3117         nkeys = 0;
3118
3119         if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3120                 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3121         {
3122                 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3123                 ber_dupbv( &value, &sa->sa_initial );
3124                 ldap_pvt_str2lower( value.bv_val );
3125
3126                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3127                         ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3128
3129                 HASH_Init( &HASHcontext );
3130                 if( prefix != NULL && prefix->bv_len > 0 ) {
3131                         HASH_Update( &HASHcontext,
3132                                 prefix->bv_val, prefix->bv_len );
3133                 }
3134                 HASH_Update( &HASHcontext,
3135                         &pre, sizeof( pre ) );
3136                 HASH_Update( &HASHcontext,
3137                         syntax->ssyn_oid, slen );
3138                 HASH_Update( &HASHcontext,
3139                         mr->smr_oid, mlen );
3140                 HASH_Update( &HASHcontext,
3141                         value.bv_val, klen );
3142                 HASH_Final( HASHdigest, &HASHcontext );
3143
3144                 free( value.bv_val );
3145                 ber_dupbv( &keys[nkeys++], &digest );
3146         }
3147
3148         if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3149                 ber_len_t i, j;
3150                 pre = SLAP_INDEX_SUBSTR_PREFIX;
3151                 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3152
3153                 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3154                         if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3155                                 continue;
3156                         }
3157
3158                         ber_dupbv( &value, &sa->sa_any[i] );
3159                         ldap_pvt_str2lower( value.bv_val );
3160
3161                         for(j=0;
3162                                 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3163                                 j += SLAP_INDEX_SUBSTR_STEP )
3164                         {
3165                                 HASH_Init( &HASHcontext );
3166                                 if( prefix != NULL && prefix->bv_len > 0 ) {
3167                                         HASH_Update( &HASHcontext,
3168                                                 prefix->bv_val, prefix->bv_len );
3169                                 }
3170                                 HASH_Update( &HASHcontext,
3171                                         &pre, sizeof( pre ) );
3172                                 HASH_Update( &HASHcontext,
3173                                         syntax->ssyn_oid, slen );
3174                                 HASH_Update( &HASHcontext,
3175                                         mr->smr_oid, mlen );
3176                                 HASH_Update( &HASHcontext,
3177                                         &value.bv_val[j], klen );
3178                                 HASH_Final( HASHdigest, &HASHcontext );
3179
3180                                 ber_dupbv( &keys[nkeys++], &digest );
3181                         }
3182
3183                         free( value.bv_val );
3184                 }
3185         }
3186
3187         if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3188                 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3189         {
3190                 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3191                 ber_dupbv( &value, &sa->sa_final );
3192                 ldap_pvt_str2lower( value.bv_val );
3193
3194                 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3195                         ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3196
3197                 HASH_Init( &HASHcontext );
3198                 if( prefix != NULL && prefix->bv_len > 0 ) {
3199                         HASH_Update( &HASHcontext,
3200                                 prefix->bv_val, prefix->bv_len );
3201                 }
3202                 HASH_Update( &HASHcontext,
3203                         &pre, sizeof( pre ) );
3204                 HASH_Update( &HASHcontext,
3205                         syntax->ssyn_oid, slen );
3206                 HASH_Update( &HASHcontext,
3207                         mr->smr_oid, mlen );
3208                 HASH_Update( &HASHcontext,
3209                         &value.bv_val[value.bv_len-klen], klen );
3210                 HASH_Final( HASHdigest, &HASHcontext );
3211
3212                 free( value.bv_val );
3213                 ber_dupbv( &keys[nkeys++], &digest );
3214         }
3215
3216         if( nkeys > 0 ) {
3217                 keys[nkeys].bv_val = NULL;
3218                 *keysp = keys;
3219         } else {
3220                 ch_free( keys );
3221                 *keysp = NULL;
3222         }
3223
3224         return LDAP_SUCCESS;
3225 }
3226         
3227 static int
3228 numericStringValidate(
3229         Syntax *syntax,
3230         struct berval *in )
3231 {
3232         ber_len_t i;
3233
3234         for(i=0; i < in->bv_len; i++) {
3235                 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3236                         return LDAP_INVALID_SYNTAX;
3237                 }
3238         }
3239
3240         return LDAP_SUCCESS;
3241 }
3242
3243 static int
3244 numericStringNormalize(
3245         Syntax *syntax,
3246         struct berval *val,
3247         struct berval *normalized )
3248 {
3249         /* removal all spaces */
3250         char *p, *q;
3251
3252         normalized->bv_val = ch_malloc( val->bv_len + 1 );
3253
3254         p = val->bv_val;
3255         q = normalized->bv_val;
3256
3257         while ( *p ) {
3258                 if ( ASCII_SPACE( *p ) ) {
3259                         /* Ignore whitespace */
3260                         p++;
3261                 } else {
3262                         *q++ = *p++;
3263                 }
3264         }
3265
3266         /* we should have copied no more then is in val */
3267         assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3268
3269         /* null terminate */
3270         *q = '\0';
3271
3272         normalized->bv_len = q - normalized->bv_val;
3273
3274         return LDAP_SUCCESS;
3275 }
3276
3277 static int
3278 objectIdentifierFirstComponentMatch(
3279         int *matchp,
3280         slap_mask_t flags,
3281         Syntax *syntax,
3282         MatchingRule *mr,
3283         struct berval *value,
3284         void *assertedValue )
3285 {
3286         int rc = LDAP_SUCCESS;
3287         int match;
3288         struct berval *asserted = (struct berval *) assertedValue;
3289         ber_len_t i;
3290         struct berval oid;
3291
3292         if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3293                 return LDAP_INVALID_SYNTAX;
3294         }
3295
3296         /* trim leading white space */
3297         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3298                 /* empty */
3299         }
3300
3301         /* grab next word */
3302         oid.bv_val = &value->bv_val[i];
3303         oid.bv_len = value->bv_len - i;
3304         for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3305                 /* empty */
3306         }
3307         oid.bv_len = i;
3308
3309         /* insert attributeTypes, objectclass check here */
3310         if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3311                 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3312
3313         } else {
3314                 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3315                         MatchingRule *asserted_mr = mr_bvfind( asserted );
3316                         MatchingRule *stored_mr = mr_bvfind( &oid );
3317
3318                         if( asserted_mr == NULL ) {
3319                                 rc = SLAPD_COMPARE_UNDEFINED;
3320                         } else {
3321                                 match = asserted_mr != stored_mr;
3322                         }
3323
3324                 } else if ( !strcmp( syntax->ssyn_oid,
3325                         SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3326                 {
3327                         AttributeType *asserted_at = at_bvfind( asserted );
3328                         AttributeType *stored_at = at_bvfind( &oid );
3329
3330                         if( asserted_at == NULL ) {
3331                                 rc = SLAPD_COMPARE_UNDEFINED;
3332                         } else {
3333                                 match = asserted_at != stored_at;
3334                         }
3335
3336                 } else if ( !strcmp( syntax->ssyn_oid,
3337                         SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3338                 {
3339                         ObjectClass *asserted_oc = oc_bvfind( asserted );
3340                         ObjectClass *stored_oc = oc_bvfind( &oid );
3341
3342                         if( asserted_oc == NULL ) {
3343                                 rc = SLAPD_COMPARE_UNDEFINED;
3344                         } else {
3345                                 match = asserted_oc != stored_oc;
3346                         }
3347                 }
3348         }
3349
3350 #ifdef NEW_LOGGING
3351         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3352                    "objectIdentifierFirstComponentMatch: %d\n    %s\n    %s\n",
3353                    match, value->bv_val, asserted->bv_val ));
3354 #else
3355         Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3356                 "%d\n\t\"%s\"\n\t\"%s\"\n",
3357                 match, value->bv_val, asserted->bv_val );
3358 #endif
3359
3360
3361         if( rc == LDAP_SUCCESS ) *matchp = match;
3362         return rc;
3363 }
3364
3365 static int
3366 integerBitAndMatch(
3367         int *matchp,
3368         slap_mask_t flags,
3369         Syntax *syntax,
3370         MatchingRule *mr,
3371         struct berval *value,
3372         void *assertedValue )
3373 {
3374         long lValue, lAssertedValue;
3375
3376         /* safe to assume integers are NUL terminated? */
3377         lValue = strtoul(value->bv_val, NULL, 10);
3378         if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3379                 return LDAP_CONSTRAINT_VIOLATION;
3380
3381         lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3382         if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3383                 return LDAP_CONSTRAINT_VIOLATION;
3384
3385         *matchp = (lValue & lAssertedValue);
3386         return LDAP_SUCCESS;
3387 }
3388
3389 static int
3390 integerBitOrMatch(
3391         int *matchp,
3392         slap_mask_t flags,
3393         Syntax *syntax,
3394         MatchingRule *mr,
3395         struct berval *value,
3396         void *assertedValue )
3397 {
3398         long lValue, lAssertedValue;
3399
3400         /* safe to assume integers are NUL terminated? */
3401         lValue = strtoul(value->bv_val, NULL, 10);
3402         if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3403                 return LDAP_CONSTRAINT_VIOLATION;
3404
3405         lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3406         if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3407                 return LDAP_CONSTRAINT_VIOLATION;
3408
3409         *matchp = (lValue | lAssertedValue);
3410         return LDAP_SUCCESS;
3411 }
3412
3413 #ifdef HAVE_TLS
3414 #include <openssl/x509.h>
3415 #include <openssl/err.h>
3416 char digit[] = "0123456789";
3417
3418 /*
3419  * Next function returns a string representation of a ASN1_INTEGER.
3420  * It works for unlimited lengths.
3421  */
3422
3423 static struct berval *
3424 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3425 {
3426         char buf[256];
3427         char *p;
3428   
3429         /* We work backwards, make it fill from the end of buf */
3430         p = buf + sizeof(buf) - 1;
3431         *p = '\0';
3432
3433         if ( a == NULL || a->length == 0 ) {
3434                 *--p = '0';
3435         } else {
3436                 int i;
3437                 int n = a->length;
3438                 int base = 0;
3439                 unsigned int *copy;
3440
3441                 /* We want to preserve the original */
3442                 copy = ch_malloc(n*sizeof(unsigned int));
3443                 for (i = 0; i<n; i++) {
3444                         copy[i] = a->data[i];
3445                 }
3446
3447                 /* 
3448                  * base indicates the index of the most significant
3449                  * byte that might be nonzero.  When it goes off the
3450                  * end, we now there is nothing left to do.
3451                  */
3452                 while (base < n) {
3453                         unsigned int carry;
3454
3455                         carry = 0;
3456                         for (i = base; i<n; i++ ) {
3457                                 copy[i] += carry*256;
3458                                 carry = copy[i] % 10;
3459                                 copy[i] /= 10;
3460                         }
3461                         if (p <= buf+1) {
3462                                 /*
3463                                  * Way too large, we need to leave
3464                                  * room for sign if negative
3465                                  */
3466                                 free(copy);
3467                                 return NULL;
3468                         }
3469                         *--p = digit[carry];
3470                         if (copy[base] == 0)
3471                                 base++;
3472                 }
3473                 free(copy);
3474         }
3475
3476         if ( a->type == V_ASN1_NEG_INTEGER ) {
3477                 *--p = '-';
3478         }
3479
3480         return ber_str2bv( p, 0, 1, bv );
3481 }
3482
3483 /* Get a DN in RFC2253 format from a X509_NAME internal struct */
3484 int
3485 dn_openssl2ldap(X509_NAME *name, struct berval *out)
3486 {
3487         char buf[2048], *p;
3488
3489         p = X509_NAME_oneline( name, buf, sizeof( buf ) );
3490         return dnDCEnormalize( p, out );
3491 }
3492
3493 /*
3494  * Given a certificate in DER format, extract the corresponding
3495  * assertion value for certificateExactMatch
3496  */
3497 static int
3498 certificateExactConvert(
3499         struct berval * in,
3500         struct berval * out )
3501 {
3502         X509 *xcert;
3503         unsigned char *p = in->bv_val;
3504         struct berval serial;
3505         struct berval issuer_dn;
3506
3507         xcert = d2i_X509(NULL, &p, in->bv_len);
3508         if ( !xcert ) {
3509 #ifdef NEW_LOGGING
3510                 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3511                            "certificateExactConvert: error parsing cert: %s\n",
3512                            ERR_error_string(ERR_get_error(),NULL)));
3513 #else
3514                 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3515                        "error parsing cert: %s\n",
3516                        ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3517 #endif
3518                 return LDAP_INVALID_SYNTAX;
3519         }
3520
3521         if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3522                 X509_free(xcert);
3523                 return LDAP_INVALID_SYNTAX;
3524         }
3525         if ( dn_openssl2ldap(X509_get_issuer_name(xcert), &issuer_dn ) != LDAP_SUCCESS ) {
3526                 X509_free(xcert);
3527                 ber_memfree(serial.bv_val);
3528                 return LDAP_INVALID_SYNTAX;
3529         }
3530
3531         X509_free(xcert);
3532
3533         out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3534         out->bv_val = ch_malloc(out->bv_len);
3535         p = out->bv_val;
3536         AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3537         p += serial.bv_len;
3538         AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3539         p += 3;
3540         AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3541         p += issuer_dn.bv_len;
3542         *p++ = '\0';
3543
3544 #ifdef NEW_LOGGING
3545         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3546                    "certificateExactConvert: \n %s\n",
3547                    out->bv_val));
3548 #else
3549         Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3550                 "\n\t\"%s\"\n",
3551                 out->bv_val, NULL, NULL );
3552 #endif
3553
3554         ber_memfree(serial.bv_val);
3555         ber_memfree(issuer_dn.bv_val);
3556
3557         return LDAP_SUCCESS;
3558 }
3559
3560 static int
3561 serial_and_issuer_parse(
3562         struct berval *assertion,
3563         struct berval *serial,
3564         struct berval *issuer_dn
3565 )
3566 {
3567         char *begin;
3568         char *end;
3569         char *p;
3570         struct berval bv;
3571
3572         begin = assertion->bv_val;
3573         end = assertion->bv_val+assertion->bv_len-1;
3574         for (p=begin; p<=end && *p != '$'; p++)
3575                 ;
3576         if ( p > end )
3577                 return LDAP_INVALID_SYNTAX;
3578
3579         /* p now points at the $ sign, now use begin and end to delimit the
3580            serial number */
3581         while (ASCII_SPACE(*begin))
3582                 begin++;
3583         end = p-1;
3584         while (ASCII_SPACE(*end))
3585                 end--;
3586
3587         bv.bv_len = end-begin+1;
3588         bv.bv_val = begin;
3589         ber_dupbv(serial, &bv);
3590
3591         /* now extract the issuer, remember p was at the dollar sign */
3592         if ( issuer_dn ) {
3593                 begin = p+1;
3594                 end = assertion->bv_val+assertion->bv_len-1;
3595                 while (ASCII_SPACE(*begin))
3596                         begin++;
3597                 /* should we trim spaces at the end too? is it safe always? */
3598
3599                 bv.bv_len = end-begin+1;
3600                 bv.bv_val = begin;
3601                 dnNormalize2( NULL, &bv, issuer_dn );
3602         }
3603
3604         return LDAP_SUCCESS;
3605 }
3606
3607 static int
3608 certificateExactMatch(
3609         int *matchp,
3610         slap_mask_t flags,
3611         Syntax *syntax,
3612         MatchingRule *mr,
3613         struct berval *value,
3614         void *assertedValue )
3615 {
3616         X509 *xcert;
3617         unsigned char *p = value->bv_val;
3618         struct berval serial;
3619         struct berval issuer_dn;
3620         struct berval asserted_serial;
3621         struct berval asserted_issuer_dn;
3622         int ret;
3623
3624         xcert = d2i_X509(NULL, &p, value->bv_len);
3625         if ( !xcert ) {
3626 #ifdef NEW_LOGGING
3627                 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3628                            "certificateExactMatch: error parsing cert: %s\n",
3629                            ERR_error_string(ERR_get_error(),NULL)));
3630 #else
3631                 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3632                        "error parsing cert: %s\n",
3633                        ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3634 #endif
3635                 return LDAP_INVALID_SYNTAX;
3636         }
3637
3638         asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3639         dn_openssl2ldap(X509_get_issuer_name(xcert), &issuer_dn);
3640
3641         X509_free(xcert);
3642
3643         serial_and_issuer_parse(assertedValue,
3644                                 &asserted_serial,
3645                                 &asserted_issuer_dn);
3646
3647         ret = integerMatch(
3648                 matchp,
3649                 flags,
3650                 slap_schema.si_syn_integer,
3651                 slap_schema.si_mr_integerMatch,
3652                 &serial,
3653                 &asserted_serial);
3654         if ( ret == LDAP_SUCCESS ) {
3655                 if ( *matchp == 0 ) {
3656                         /* We need to normalize everything for dnMatch */
3657                         ret = dnMatch(
3658                                 matchp,
3659                                 flags,
3660                                 slap_schema.si_syn_distinguishedName,
3661                                 slap_schema.si_mr_distinguishedNameMatch,
3662                                 &issuer_dn,
3663                                 &asserted_issuer_dn);
3664                 }
3665         }
3666
3667 #ifdef NEW_LOGGING
3668         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3669                    "certificateExactMatch: %d\n  %s $ %s\n       %s $   %s\n",
3670                    *matchp, serial.bv_val, issuer_dn.bv_val,
3671                    asserted_serial.bv_val, asserted_issuer_dn.bv_val));
3672 #else
3673         Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3674                 "%d\n\t\"%s $ %s\"\n",
3675                 *matchp, serial.bv_val, issuer_dn.bv_val );
3676         Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3677                 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3678                 NULL );
3679 #endif
3680
3681         ber_memfree(serial.bv_val);
3682         ber_memfree(issuer_dn.bv_val);
3683         ber_memfree(asserted_serial.bv_val);
3684         ber_memfree(asserted_issuer_dn.bv_val);
3685
3686         return ret;
3687 }
3688
3689 /* 
3690  * Index generation function
3691  * We just index the serials, in most scenarios the issuer DN is one of
3692  * a very small set of values.
3693  */
3694 static int certificateExactIndexer(
3695         slap_mask_t use,
3696         slap_mask_t flags,
3697         Syntax *syntax,
3698         MatchingRule *mr,
3699         struct berval *prefix,
3700         BerVarray values,
3701         BerVarray *keysp )
3702 {
3703         int i;
3704         BerVarray keys;
3705         X509 *xcert;
3706         unsigned char *p;
3707         struct berval serial;
3708
3709         /* we should have at least one value at this point */
3710         assert( values != NULL && values[0].bv_val != NULL );
3711
3712         for( i=0; values[i].bv_val != NULL; i++ ) {
3713                 /* empty -- just count them */
3714         }
3715
3716         keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3717
3718         for( i=0; values[i].bv_val != NULL; i++ ) {
3719                 p = values[i].bv_val;
3720                 xcert = d2i_X509(NULL, &p, values[i].bv_len);
3721                 if ( !xcert ) {
3722 #ifdef NEW_LOGGING
3723                         LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3724                             "certificateExactIndexer: error parsing cert: %s\n",
3725                                 ERR_error_string(ERR_get_error(),NULL)));
3726 #else
3727                         Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3728                                "error parsing cert: %s\n",
3729                                ERR_error_string(ERR_get_error(),NULL),
3730                                NULL, NULL );
3731 #endif
3732                         /* Do we leak keys on error? */
3733                         return LDAP_INVALID_SYNTAX;
3734                 }
3735
3736                 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3737                 X509_free(xcert);
3738                 integerNormalize( slap_schema.si_syn_integer,
3739                                   &serial,
3740                                   &keys[i] );
3741                 ber_memfree(serial.bv_val);
3742 #ifdef NEW_LOGGING
3743                 LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
3744                            "certificateExactIndexer: returning: %s\n",
3745                            keys[i].bv_val));
3746 #else
3747                 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3748                        "returning: %s\n",
3749                        keys[i].bv_val,
3750                        NULL, NULL );
3751 #endif
3752         }
3753
3754         keys[i].bv_val = NULL;
3755         *keysp = keys;
3756         return LDAP_SUCCESS;
3757 }
3758
3759 /* Index generation function */
3760 /* We think this is always called with a value in matching rule syntax */
3761 static int certificateExactFilter(
3762         slap_mask_t use,
3763         slap_mask_t flags,
3764         Syntax *syntax,
3765         MatchingRule *mr,
3766         struct berval *prefix,
3767         void * assertValue,
3768         BerVarray *keysp )
3769 {
3770         BerVarray keys;
3771         struct berval asserted_serial;
3772
3773         serial_and_issuer_parse(assertValue,
3774                                 &asserted_serial,
3775                                 NULL);
3776
3777         keys = ch_malloc( sizeof( struct berval ) * 2 );
3778         integerNormalize( syntax, &asserted_serial, &keys[0] );
3779         keys[1].bv_val = NULL;
3780         *keysp = keys;
3781
3782         ber_memfree(asserted_serial.bv_val);
3783         return LDAP_SUCCESS;
3784 }
3785 #endif
3786
3787 static int
3788 check_time_syntax (struct berval *val,
3789         int start,
3790         int *parts)
3791 {
3792         static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3793         static int mdays[2][12] = {
3794                 /* non-leap years */
3795                 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3796                 /* leap years */
3797                 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3798         };
3799         char *p, *e;
3800         int part, c, tzoffset, leapyear = 0 ;
3801
3802         if( val->bv_len == 0 ) {
3803                 return LDAP_INVALID_SYNTAX;
3804         }
3805
3806         p = (char *)val->bv_val;
3807         e = p + val->bv_len;
3808
3809         /* Ignore initial whitespace */
3810         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3811                 p++;
3812         }
3813
3814         if (e - p < 13 - (2 * start)) {
3815                 return LDAP_INVALID_SYNTAX;
3816         }
3817
3818         for (part = 0; part < 9; part++) {
3819                 parts[part] = 0;
3820         }
3821
3822         for (part = start; part < 7; part++) {
3823                 c = *p;
3824                 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3825                         part++;
3826                         break;
3827                 }
3828                 p++;
3829                 c -= '0';
3830                 if (p == e) {
3831                         return LDAP_INVALID_SYNTAX;
3832                 }
3833                 if (c < 0 || c > 9) {
3834                         return LDAP_INVALID_SYNTAX;
3835                 }
3836                 parts[part] = c;
3837
3838                 c = *p++ - '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] *= 10;
3846                 parts[part] += c;
3847
3848                 if (part == 2 || part == 3) {
3849                         parts[part]--;
3850                 }
3851                 if (parts[part] < 0) {
3852                         return LDAP_INVALID_SYNTAX;
3853                 }
3854                 if (parts[part] > ceiling[part]) {
3855                         return LDAP_INVALID_SYNTAX;
3856                 }
3857         }
3858
3859         /* leapyear check for the Gregorian calendar (year>1581) */
3860         if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
3861                 ((parts[0] % 4 == 0) && (parts[1] == 0)))
3862         {
3863                 leapyear = 1;
3864         }
3865
3866         if (parts[3] > mdays[leapyear][parts[2]]) {
3867                 return LDAP_INVALID_SYNTAX;
3868         }
3869         
3870         c = *p++;
3871         if (c == 'Z') {
3872                 tzoffset = 0; /* UTC */
3873         } else if (c != '+' && c != '-') {
3874                 return LDAP_INVALID_SYNTAX;
3875         } else {
3876                 if (c == '-') {
3877                         tzoffset = -1;
3878                 } else /* c == '+' */ {
3879                         tzoffset = 1;
3880                 }
3881
3882                 if (p > e - 4) {
3883                         return LDAP_INVALID_SYNTAX;
3884                 }
3885
3886                 for (part = 7; part < 9; part++) {
3887                         c = *p++ - '0';
3888                         if (c < 0 || c > 9) {
3889                                 return LDAP_INVALID_SYNTAX;
3890                         }
3891                         parts[part] = c;
3892
3893                         c = *p++ - '0';
3894                         if (c < 0 || c > 9) {
3895                                 return LDAP_INVALID_SYNTAX;
3896                         }
3897                         parts[part] *= 10;
3898                         parts[part] += c;
3899                         if (parts[part] < 0 || parts[part] > ceiling[part]) {
3900                                 return LDAP_INVALID_SYNTAX;
3901                         }
3902                 }
3903         }
3904
3905         /* Ignore trailing whitespace */
3906         while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3907                 p++;
3908         }
3909         if (p != e) {
3910                 return LDAP_INVALID_SYNTAX;
3911         }
3912
3913         switch ( tzoffset ) {
3914         case -1: /* negativ offset to UTC, ie west of Greenwich  */
3915                 parts[4] += parts[7];
3916                 parts[5] += parts[8];
3917                 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
3918                         if (part != 3) {
3919                                 c = ceiling[part];
3920                         } else {
3921                                 c = mdays[leapyear][parts[2]];
3922                         }
3923                         if (parts[part] > c) {
3924                                 parts[part] -= c + 1;
3925                                 parts[part - 1]++;
3926                         }
3927                 }
3928                 break;
3929         case 1: /* positive offset to UTC, ie east of Greenwich */
3930                 parts[4] -= parts[7];
3931                 parts[5] -= parts[8];
3932                 for (part = 6; --part > 0; ) {
3933                         if (part != 3) {
3934                                 c = ceiling[part];
3935                         } else {
3936                                 /* first arg to % needs to be non negativ */
3937                                 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
3938                         }
3939                         if (parts[part] < 0) {
3940                                 parts[part] += c + 1;
3941                                 parts[part - 1]--;
3942                         }
3943                 }
3944                 break;
3945         case 0: /* already UTC */
3946                 break;
3947         }
3948
3949         return LDAP_SUCCESS;
3950 }
3951
3952 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3953 static int
3954 utcTimeNormalize(
3955         Syntax *syntax,
3956         struct berval *val,
3957         struct berval *normalized )
3958 {
3959         int parts[9], rc;
3960
3961         rc = check_time_syntax(val, 1, parts);
3962         if (rc != LDAP_SUCCESS) {
3963                 return rc;
3964         }
3965
3966         normalized->bv_val = ch_malloc( 14 );
3967         if ( normalized->bv_val == NULL ) {
3968                 return LBER_ERROR_MEMORY;
3969         }
3970
3971         sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
3972                 parts[1], parts[2] + 1, parts[3] + 1,
3973                 parts[4], parts[5], parts[6] );
3974         normalized->bv_len = 13;
3975
3976         return LDAP_SUCCESS;
3977 }
3978 #endif
3979
3980 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
3981 static int
3982 utcTimeValidate(
3983         Syntax *syntax,
3984         struct berval *in )
3985 {
3986         int parts[9];
3987
3988         return check_time_syntax(in, 1, parts);
3989 }
3990 #endif
3991
3992 static int
3993 generalizedTimeValidate(
3994         Syntax *syntax,
3995         struct berval *in )
3996 {
3997         int parts[9];
3998
3999         return check_time_syntax(in, 0, parts);
4000 }
4001
4002 static int
4003 generalizedTimeNormalize(
4004         Syntax *syntax,
4005         struct berval *val,
4006         struct berval *normalized )
4007 {
4008         int parts[9], rc;
4009
4010         rc = check_time_syntax(val, 0, parts);
4011         if (rc != LDAP_SUCCESS) {
4012                 return rc;
4013         }
4014
4015         normalized->bv_val = ch_malloc( 16 );
4016         if ( normalized->bv_val == NULL ) {
4017                 return LBER_ERROR_MEMORY;
4018         }
4019
4020         sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4021                 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4022                 parts[4], parts[5], parts[6] );
4023         normalized->bv_len = 15;
4024
4025         return LDAP_SUCCESS;
4026 }
4027
4028 static int
4029 nisNetgroupTripleValidate(
4030         Syntax *syntax,
4031         struct berval *val )
4032 {
4033         char *p, *e;
4034         int commas = 0;
4035
4036         if ( val->bv_len == 0 ) {
4037                 return LDAP_INVALID_SYNTAX;
4038         }
4039
4040         p = (char *)val->bv_val;
4041         e = p + val->bv_len;
4042
4043         if ( *p != '(' /*')'*/ ) {
4044                 return LDAP_INVALID_SYNTAX;
4045         }
4046
4047         for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4048                 if ( *p == ',' ) {
4049                         commas++;
4050                         if ( commas > 2 ) {
4051                                 return LDAP_INVALID_SYNTAX;
4052                         }
4053
4054                 } else if ( !ATTR_CHAR( *p ) ) {
4055                         return LDAP_INVALID_SYNTAX;
4056                 }
4057         }
4058
4059         if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4060                 return LDAP_INVALID_SYNTAX;
4061         }
4062
4063         p++;
4064
4065         if (p != e) {
4066                 return LDAP_INVALID_SYNTAX;
4067         }
4068
4069         return LDAP_SUCCESS;
4070 }
4071
4072 static int
4073 bootParameterValidate(
4074         Syntax *syntax,
4075         struct berval *val )
4076 {
4077         char *p, *e;
4078
4079         if ( val->bv_len == 0 ) {
4080                 return LDAP_INVALID_SYNTAX;
4081         }
4082
4083         p = (char *)val->bv_val;
4084         e = p + val->bv_len;
4085
4086         /* key */
4087         for (; ( p < e ) && ( *p != '=' ); p++ ) {
4088                 if ( !ATTR_CHAR( *p ) ) {
4089                         return LDAP_INVALID_SYNTAX;
4090                 }
4091         }
4092
4093         if ( *p != '=' ) {
4094                 return LDAP_INVALID_SYNTAX;
4095         }
4096
4097         /* server */
4098         for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4099                 if ( !ATTR_CHAR( *p ) ) {
4100                         return LDAP_INVALID_SYNTAX;
4101                 }
4102         }
4103
4104         if ( *p != ':' ) {
4105                 return LDAP_INVALID_SYNTAX;
4106         }
4107
4108         /* path */
4109         for ( p++; p < e; p++ ) {
4110                 if ( !ATTR_CHAR( *p ) ) {
4111                         return LDAP_INVALID_SYNTAX;
4112                 }
4113         }
4114
4115         return LDAP_SUCCESS;
4116 }
4117
4118 static struct syntax_defs_rec {
4119         char *sd_desc;
4120 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4121 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4122         int sd_flags;
4123         slap_syntax_validate_func *sd_validate;
4124         slap_syntax_transform_func *sd_normalize;
4125         slap_syntax_transform_func *sd_pretty;
4126 #ifdef SLAPD_BINARY_CONVERSION
4127         slap_syntax_transform_func *sd_ber2str;
4128         slap_syntax_transform_func *sd_str2ber;
4129 #endif
4130 } syntax_defs[] = {
4131         {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4132                 X_BINARY X_NOT_H_R ")",
4133                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4134         {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4135                 0, NULL, NULL, NULL},
4136         {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4137                 0, NULL, NULL, NULL},
4138         {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4139                 X_NOT_H_R ")",
4140                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4141         {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4142                 X_NOT_H_R ")",
4143                 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4144         {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4145                 0, bitStringValidate, bitStringNormalize, NULL },
4146         {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4147                 0, booleanValidate, NULL, NULL},
4148         {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4149                 X_BINARY X_NOT_H_R ")",
4150                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4151         {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4152                 X_BINARY X_NOT_H_R ")",
4153                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4154         {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4155                 X_BINARY X_NOT_H_R ")",
4156                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4157         {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4158                 0, countryStringValidate, IA5StringNormalize, NULL},
4159         {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4160                 0, dnValidate, dnNormalize2, dnPretty2},
4161         {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4162                 0, NULL, NULL, NULL},
4163         {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4164                 0, NULL, NULL, NULL},
4165         {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4166                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4167         {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4168                 0, NULL, NULL, NULL},
4169         {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4170                 0, NULL, NULL, NULL},
4171         {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4172                 0, NULL, NULL, NULL},
4173         {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4174                 0, NULL, NULL, NULL},
4175         {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4176                 0, NULL, NULL, NULL},
4177         {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4178                 0, printablesStringValidate, telephoneNumberNormalize, NULL},
4179         {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4180                 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4181         {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4182                 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4183         {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4184                 0, NULL, NULL, NULL},
4185         {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4186                 0, IA5StringValidate, IA5StringNormalize, NULL},
4187         {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4188                 0, integerValidate, integerNormalize, NULL},
4189         {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4190                 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4191         {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4192                 0, NULL, NULL, NULL},
4193         {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4194                 0, NULL, NULL, NULL},
4195         {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4196                 0, NULL, NULL, NULL},
4197         {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4198                 0, NULL, NULL, NULL},
4199         {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4200                 0, NULL, NULL, NULL},
4201         {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4202                 0, nameUIDValidate, nameUIDNormalize, NULL},
4203         {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4204                 0, NULL, NULL, NULL},
4205         {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4206                 0, numericStringValidate, numericStringNormalize, NULL},
4207         {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4208                 0, NULL, NULL, NULL},
4209         {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4210                 0, oidValidate, NULL, NULL},
4211         {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4212                 0, IA5StringValidate, IA5StringNormalize, NULL},
4213         {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4214                 0, blobValidate, NULL, NULL},
4215         {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4216                 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4217         {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4218                 0, NULL, NULL, NULL},
4219         {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4220                 0, NULL, NULL, NULL},
4221         {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4222                 0, printableStringValidate, IA5StringNormalize, NULL},
4223         {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4224                 X_BINARY X_NOT_H_R ")",
4225                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4226         {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4227                 X_BINARY X_NOT_H_R ")",
4228                 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4229         {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4230                 0, printableStringValidate, telephoneNumberNormalize, NULL},
4231         {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4232                 0, NULL, NULL, NULL},
4233         {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4234                 0, printablesStringValidate, IA5StringNormalize, NULL},
4235 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4236         {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4237                 0, utcTimeValidate, utcTimeNormalize, NULL},
4238 #endif
4239         {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4240                 0, NULL, NULL, NULL},
4241         {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4242                 0, NULL, NULL, NULL},
4243         {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4244                 0, NULL, NULL, NULL},
4245         {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4246                 0, NULL, NULL, NULL},
4247         {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4248                 0, NULL, NULL, NULL},
4249
4250         /* RFC 2307 NIS Syntaxes */
4251         {"( 1.3.6.1.1.1.0.0  DESC 'RFC2307 NIS Netgroup Triple' )",
4252                 0, nisNetgroupTripleValidate, NULL, NULL},
4253         {"( 1.3.6.1.1.1.0.1  DESC 'RFC2307 Boot Parameter' )",
4254                 0, bootParameterValidate, NULL, NULL},
4255
4256 #ifdef HAVE_TLS
4257         /* From PKIX */
4258         /* These OIDs are not published yet, but will be in the next
4259          * I-D for PKIX LDAPv3 schema as have been advanced by David
4260          * Chadwick in private mail.
4261          */
4262         {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4263                 0, NULL, NULL, NULL},
4264 #endif
4265
4266         /* OpenLDAP Experimental Syntaxes */
4267 #ifdef SLAPD_ACI_ENABLED
4268         {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4269                 SLAP_SYNTAX_HIDE,
4270                 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4271                 NULL, NULL},
4272 #endif
4273
4274 #ifdef SLAPD_AUTHPASSWD
4275         /* needs updating */
4276         {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4277                 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4278 #endif
4279
4280         /* OpenLDAP Void Syntax */
4281         {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4282                 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4283         {NULL, 0, NULL, NULL, NULL}
4284 };
4285
4286 /*
4287  * Other matching rules in X.520 that we do not use (yet):
4288  *
4289  * 2.5.13.9             numericStringOrderingMatch
4290  * 2.5.13.18    octetStringOrderingMatch
4291  * 2.5.13.19    octetStringSubstringsMatch
4292  * 2.5.13.25    uTCTimeMatch
4293  * 2.5.13.26    uTCTimeOrderingMatch
4294  * 2.5.13.31    directoryStringFirstComponentMatch
4295  * 2.5.13.32    wordMatch
4296  * 2.5.13.33    keywordMatch
4297  * 2.5.13.35    certificateMatch
4298  * 2.5.13.36    certificatePairExactMatch
4299  * 2.5.13.37    certificatePairMatch
4300  * 2.5.13.38    certificateListExactMatch
4301  * 2.5.13.39    certificateListMatch
4302  * 2.5.13.40    algorithmIdentifierMatch
4303  * 2.5.13.41    storedPrefixMatch
4304  * 2.5.13.42    attributeCertificateMatch
4305  * 2.5.13.43    readerAndKeyIDMatch
4306  * 2.5.13.44    attributeIntegrityMatch
4307  */
4308 static struct mrule_defs_rec {
4309         char *                                          mrd_desc;
4310         slap_mask_t                                     mrd_usage;
4311         slap_mr_convert_func *          mrd_convert;
4312         slap_mr_normalize_func *        mrd_normalize;
4313         slap_mr_match_func *            mrd_match;
4314         slap_mr_indexer_func *          mrd_indexer;
4315         slap_mr_filter_func *           mrd_filter;
4316
4317         char *                                          mrd_associated;
4318 } mrule_defs[] = {
4319         /*
4320          * EQUALITY matching rules must be listed after associated APPROX
4321          * matching rules.  So, we list all APPROX matching rules first.
4322          */
4323         {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4324                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4325                 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4326                 NULL, NULL,
4327                 directoryStringApproxMatch,
4328                 directoryStringApproxIndexer, 
4329                 directoryStringApproxFilter,
4330                 NULL},
4331
4332         {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4333                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4334                 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4335                 NULL, NULL,
4336                 IA5StringApproxMatch,
4337                 IA5StringApproxIndexer, 
4338                 IA5StringApproxFilter,
4339                 NULL},
4340
4341         /*
4342          * Other matching rules
4343          */
4344         
4345         {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4346                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4347                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4348                 NULL, NULL,
4349                 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4350                 NULL},
4351
4352         {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4353                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4354                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4355                 NULL, NULL,
4356                 dnMatch, dnIndexer, dnFilter,
4357                 NULL},
4358
4359         {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4360                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4361                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4362                 NULL, NULL,
4363                 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4364                 directoryStringApproxMatchOID },
4365
4366         {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4367                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4368                 SLAP_MR_ORDERING,
4369                 NULL, NULL,
4370                 caseIgnoreOrderingMatch, NULL, NULL,
4371                 NULL},
4372
4373         {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4374                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4375                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4376                 NULL, NULL,
4377                 caseExactIgnoreSubstringsMatch,
4378                 caseExactIgnoreSubstringsIndexer,
4379                 caseExactIgnoreSubstringsFilter,
4380                 NULL},
4381
4382         {"( 2.5.13.5 NAME 'caseExactMatch' "
4383                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4384                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4385                 NULL, NULL,
4386                 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4387                 directoryStringApproxMatchOID },
4388
4389         {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4390                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4391                 SLAP_MR_ORDERING,
4392                 NULL, NULL,
4393                 caseExactOrderingMatch, NULL, NULL,
4394                 NULL},
4395
4396         {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4397                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4398                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4399                 NULL, NULL,
4400                 caseExactIgnoreSubstringsMatch,
4401                 caseExactIgnoreSubstringsIndexer,
4402                 caseExactIgnoreSubstringsFilter,
4403                 NULL},
4404
4405         {"( 2.5.13.8 NAME 'numericStringMatch' "
4406                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4407                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4408                 NULL, NULL,
4409                 caseIgnoreIA5Match,
4410                 caseIgnoreIA5Indexer,
4411                 caseIgnoreIA5Filter,
4412                 NULL},
4413
4414         {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4415                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4416                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4417                 NULL, NULL,
4418                 caseIgnoreIA5SubstringsMatch,
4419                 caseIgnoreIA5SubstringsIndexer,
4420                 caseIgnoreIA5SubstringsFilter,
4421                 NULL},
4422
4423         {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4424                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4425                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4426                 NULL, NULL,
4427                 caseIgnoreListMatch, NULL, NULL,
4428                 NULL},
4429
4430         {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4431                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4432                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4433                 NULL, NULL,
4434                 caseIgnoreListSubstringsMatch, NULL, NULL,
4435                 NULL},
4436
4437         {"( 2.5.13.13 NAME 'booleanMatch' "
4438                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4439                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4440                 NULL, NULL,
4441                 booleanMatch, NULL, NULL,
4442                 NULL},
4443
4444         {"( 2.5.13.14 NAME 'integerMatch' "
4445                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4446                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4447                 NULL, NULL,
4448                 integerMatch, integerIndexer, integerFilter,
4449                 NULL},
4450
4451         {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4452                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4453                 SLAP_MR_ORDERING,
4454                 NULL, NULL,
4455                 integerOrderingMatch, NULL, NULL,
4456                 NULL},
4457
4458         {"( 2.5.13.16 NAME 'bitStringMatch' "
4459                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4460                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4461                 NULL, NULL,
4462                 bitStringMatch, bitStringIndexer, bitStringFilter,
4463                 NULL},
4464
4465         {"( 2.5.13.17 NAME 'octetStringMatch' "
4466                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4467                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4468                 NULL, NULL,
4469                 octetStringMatch, octetStringIndexer, octetStringFilter,
4470                 NULL},
4471
4472         {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4473                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4474                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4475                 NULL, NULL,
4476                 telephoneNumberMatch,
4477                 telephoneNumberIndexer,
4478                 telephoneNumberFilter,
4479                 NULL},
4480
4481         {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4482                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4483                 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4484                 NULL, NULL,
4485                 telephoneNumberSubstringsMatch,
4486                 telephoneNumberSubstringsIndexer,
4487                 telephoneNumberSubstringsFilter,
4488                 NULL},
4489
4490         {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4491                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4492                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4493                 NULL, NULL,
4494                 NULL, NULL, NULL,
4495                 NULL},
4496
4497         {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4498                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4499                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4500                 NULL, NULL,
4501                 uniqueMemberMatch, NULL, NULL,
4502                 NULL},
4503
4504         {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4505                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4506                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4507                 NULL, NULL,
4508                 protocolInformationMatch, NULL, NULL,
4509                 NULL},
4510
4511         {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4512                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4513                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4514                 NULL, NULL,
4515                 generalizedTimeMatch, NULL, NULL,
4516                 NULL},
4517
4518         {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4519                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4520                 SLAP_MR_ORDERING,
4521                 NULL, NULL,
4522                 generalizedTimeOrderingMatch, NULL, NULL,
4523                 NULL},
4524
4525         {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4526                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4527                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4528                 NULL, NULL,
4529                 integerFirstComponentMatch, NULL, NULL,
4530                 NULL},
4531
4532         {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4533                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4534                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4535                 NULL, NULL,
4536                 objectIdentifierFirstComponentMatch, NULL, NULL,
4537                 NULL},
4538
4539 #ifdef HAVE_TLS
4540         {"( 2.5.13.34 NAME 'certificateExactMatch' "
4541                 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4542                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4543                 certificateExactConvert, NULL,
4544                 certificateExactMatch,
4545                 certificateExactIndexer, certificateExactFilter,
4546                 NULL},
4547 #endif
4548
4549         {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4550                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4551                 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4552                 NULL, NULL,
4553                 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4554                 IA5StringApproxMatchOID },
4555
4556         {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4557                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4558                 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4559                 NULL, NULL,
4560                 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4561                 IA5StringApproxMatchOID },
4562
4563         {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4564                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4565                 SLAP_MR_SUBSTR,
4566                 NULL, NULL,
4567                 caseIgnoreIA5SubstringsMatch,
4568                 caseIgnoreIA5SubstringsIndexer,
4569                 caseIgnoreIA5SubstringsFilter,
4570                 NULL},
4571
4572         {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4573                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4574                 SLAP_MR_SUBSTR,
4575                 NULL, NULL,
4576                 caseExactIA5SubstringsMatch,
4577                 caseExactIA5SubstringsIndexer,
4578                 caseExactIA5SubstringsFilter,
4579                 NULL},
4580
4581 #ifdef SLAPD_AUTHPASSWD
4582         /* needs updating */
4583         {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4584                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4585                 SLAP_MR_EQUALITY,
4586                 NULL, NULL,
4587                 authPasswordMatch, NULL, NULL,
4588                 NULL},
4589 #endif
4590
4591 #ifdef SLAPD_ACI_ENABLED
4592         {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4593                 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4594                 SLAP_MR_EQUALITY,
4595                 NULL, NULL,
4596                 OpenLDAPaciMatch, NULL, NULL,
4597                 NULL},
4598 #endif
4599
4600         {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4601                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4602                 SLAP_MR_EXT,
4603                 NULL, NULL,
4604                 integerBitAndMatch, NULL, NULL,
4605                 NULL},
4606
4607         {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4608                 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4609                 SLAP_MR_EXT,
4610                 NULL, NULL,
4611                 integerBitOrMatch, NULL, NULL,
4612                 NULL},
4613
4614         {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4615 };
4616
4617 int
4618 slap_schema_init( void )
4619 {
4620         int             res;
4621         int             i;
4622
4623         /* we should only be called once (from main) */
4624         assert( schema_init_done == 0 );
4625
4626         for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4627                 res = register_syntax( syntax_defs[i].sd_desc,
4628                         syntax_defs[i].sd_flags,
4629                         syntax_defs[i].sd_validate,
4630                         syntax_defs[i].sd_normalize,
4631                         syntax_defs[i].sd_pretty
4632 #ifdef SLAPD_BINARY_CONVERSION
4633                         ,
4634                         syntax_defs[i].sd_ber2str,
4635                         syntax_defs[i].sd_str2ber
4636 #endif
4637                 );
4638
4639                 if ( res ) {
4640                         fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4641                                  syntax_defs[i].sd_desc );
4642                         return LDAP_OTHER;
4643                 }
4644         }
4645
4646         for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4647                 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4648                         fprintf( stderr,
4649                                 "slap_schema_init: Ingoring unusable matching rule %s\n",
4650                                  mrule_defs[i].mrd_desc );
4651                         continue;
4652                 }
4653
4654                 res = register_matching_rule(
4655                         mrule_defs[i].mrd_desc,
4656                         mrule_defs[i].mrd_usage,
4657                         mrule_defs[i].mrd_convert,
4658                         mrule_defs[i].mrd_normalize,
4659                         mrule_defs[i].mrd_match,
4660                         mrule_defs[i].mrd_indexer,
4661                         mrule_defs[i].mrd_filter,
4662                         mrule_defs[i].mrd_associated );
4663
4664                 if ( res ) {
4665                         fprintf( stderr,
4666                                 "slap_schema_init: Error registering matching rule %s\n",
4667                                  mrule_defs[i].mrd_desc );
4668                         return LDAP_OTHER;
4669                 }
4670         }
4671
4672         for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4673                 *mr_ptr[i].mr = mr_find( mr_ptr[i].oid );
4674
4675         res = slap_schema_load();
4676         schema_init_done = 1;
4677         return res;
4678 }
4679
4680 void
4681 schema_destroy( void )
4682 {
4683         int i;
4684         oidm_destroy();
4685         oc_destroy();
4686         at_destroy();
4687         for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4688                 *mr_ptr[i].mr = NULL;
4689         mr_destroy();
4690         syn_destroy();
4691 }