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