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