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