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