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