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