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