1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
15 #include <ac/string.h>
16 #include <ac/socket.h>
22 #include "ldap_utf8.h"
24 #include "lutil_hash.h"
25 #define HASH_BYTES LUTIL_HASH_BYTES
26 #define HASH_CONTEXT lutil_HASH_CTX
27 #define HASH_Init(c) lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
33 #define SLAP_MR_DN_FOLD (0)
35 #define xUTF8StringNormalize NULL
36 #define xIA5StringNormalize NULL
37 #define xtelephoneNumberNormalize NULL
38 #define xgeneralizedTimeNormalize NULL
39 #define xintegerNormalize NULL
40 #define xnumericStringNormalize NULL
41 #define xnameUIDNormalize NULL
43 #define distinguishedNameMatch dnMatch
44 #define distinguishedNameIndexer octetStringIndexer
45 #define distinguishedNameFilter octetStringFilter
47 #define uniqueMemberMatch dnMatch
49 #define objectIdentifierMatch octetStringMatch
50 #define objectIdentifierIndexer octetStringIndexer
51 #define objectIdentifierFilter octetStringFilter
53 #define bitStringMatch octetStringMatch
54 #define bitStringIndexer octetStringIndexer
55 #define bitStringFilter octetStringFilter
57 #define integerMatch NULL
58 #define integerOrderingMatch NULL
59 #define integerIndexer NULL
60 #define integerFilter NULL
62 #define generalizedTimeMatch NULL
63 #define generalizedTimeOrderingMatch NULL
65 #define caseIgnoreMatch octetStringMatch
66 #define caseIgnoreOrderingMatch octetStringOrderingMatch
67 #define caseIgnoreIndexer octetStringIndexer
68 #define caseIgnoreFilter octetStringFilter
70 #define caseIgnoreSubstringsMatch NULL
71 #define caseIgnoreSubstringsIndexer NULL
72 #define caseIgnoreSubstringsFilter NULL
74 #define caseExactMatch octetStringMatch
75 #define caseExactOrderingMatch octetStringOrderingMatch
76 #define caseExactIndexer octetStringIndexer
77 #define caseExactFilter octetStringFilter
79 #define caseExactSubstringsMatch NULL
80 #define caseExactSubstringsIndexer NULL
81 #define caseExactSubstringsFilter NULL
83 #define caseExactIA5Match octetStringMatch
84 #define caseExactIA5Indexer octetStringIndexer
85 #define caseExactIA5Filter octetStringFilter
87 #define caseExactIA5SubstringsMatch NULL
88 #define caseExactIA5SubstringsIndexer NULL
89 #define caseExactIA5SubstringsFilter NULL
91 #define caseIgnoreIA5Match octetStringMatch
92 #define caseIgnoreIA5Indexer octetStringIndexer
93 #define caseIgnoreIA5Filter octetStringFilter
95 #define caseIgnoreIA5SubstringsMatch caseExactIA5SubstringsMatch
96 #define caseIgnoreIA5SubstringsIndexer caseExactIA5SubstringsIndexer
97 #define caseIgnoreIA5SubstringsFilter caseExactIA5SubstringsFilter
99 #define numericStringMatch octetStringMatch
100 #define numericStringIndexer octetStringIndexer
101 #define numericStringFilter octetStringFilter
103 #define numericStringSubstringsMatch caseExactIA5SubstringsMatch
104 #define numericStringSubstringsIndexer caseExactIA5SubstringsIndexer
105 #define numericStringSubstringsFilter caseExactIA5SubstringsFilter
107 #define telephoneNumberMatch octetStringMatch
108 #define telephoneNumberIndexer octetStringIndexer
109 #define telephoneNumberFilter octetStringFilter
111 #define telephoneNumberSubstringsMatch caseExactIA5SubstringsMatch
112 #define telephoneNumberSubstringsIndexer caseExactIA5SubstringsIndexer
113 #define telephoneNumberSubstringsFilter caseExactIA5SubstringsFilter
117 /* validatation routines */
118 #define berValidate blobValidate
120 /* (new) normalization routines */
121 #define caseExactNormalize NULL
122 #define caseExactIA5Normalize NULL
123 #define caseIgnoreNormalize NULL
124 #define caseIgnoreIA5Normalize NULL
125 #define distinguishedNameNormalize NULL
126 #define integerNormalize NULL
127 #define integerFirstComponentNormalize NULL
128 #define numericStringNormalize NULL
129 #define objectIdentifierNormalize NULL
130 #define objectIdentifierFirstComponentNormalize NULL
131 #define generalizedTimeNormalize NULL
132 #define uniqueMemberNormalize NULL
133 #define bitStringNormalize NULL
134 #define telephoneNumberNormalize NULL
136 /* approx matching rules */
138 #define directoryStringApproxMatchOID NULL
139 #define IA5StringApproxMatchOID NULL
141 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
142 #define directoryStringApproxMatch approxMatch
143 #define directoryStringApproxIndexer approxIndexer
144 #define directoryStringApproxFilter approxFilter
145 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
146 #define IA5StringApproxMatch approxMatch
147 #define IA5StringApproxIndexer approxIndexer
148 #define IA5StringApproxFilter approxFilter
153 /* matching routines */
154 #define bitStringMatch octetStringMatch
155 #define bitStringIndexer octetStringIndexer
156 #define bitStringFilter octetStringFilter
158 #define numericStringMatch caseIgnoreIA5Match
159 #define numericStringIndexer NULL
160 #define numericStringFilter NULL
161 #define numericStringSubstringsIndexer NULL
162 #define numericStringSubstringsFilter NULL
164 #define objectIdentifierMatch octetStringMatch
165 #define objectIdentifierIndexer caseIgnoreIA5Indexer
166 #define objectIdentifierFilter caseIgnoreIA5Filter
168 #define generalizedTimeMatch caseIgnoreIA5Match
169 #define generalizedTimeOrderingMatch caseIgnoreIA5Match
171 #define uniqueMemberMatch dnMatch
172 #define numericStringSubstringsMatch NULL
174 #define caseExactIndexer caseExactIgnoreIndexer
175 #define caseExactFilter caseExactIgnoreFilter
176 #define caseExactOrderingMatch caseExactMatch
177 #define caseExactSubstringsMatch caseExactIgnoreSubstringsMatch
178 #define caseExactSubstringsIndexer caseExactIgnoreSubstringsIndexer
179 #define caseExactSubstringsFilter caseExactIgnoreSubstringsFilter
180 #define caseIgnoreIndexer caseExactIgnoreIndexer
181 #define caseIgnoreFilter caseExactIgnoreFilter
182 #define caseIgnoreOrderingMatch caseIgnoreMatch
183 #define caseIgnoreSubstringsMatch caseExactIgnoreSubstringsMatch
184 #define caseIgnoreSubstringsIndexer caseExactIgnoreSubstringsIndexer
185 #define caseIgnoreSubstringsFilter caseExactIgnoreSubstringsFilter
187 #define integerOrderingMatch integerMatch
188 #define integerFirstComponentMatch integerMatch
190 #define distinguishedNameMatch dnMatch
191 #define distinguishedNameIndexer caseExactIgnoreIndexer
192 #define distinguishedNameFilter caseExactIgnoreFilter
194 #define telephoneNumberMatch caseIgnoreIA5Match
195 #define telephoneNumberSubstringsMatch caseIgnoreIA5SubstringsMatch
196 #define telephoneNumberIndexer caseIgnoreIA5Indexer
197 #define telephoneNumberFilter caseIgnoreIA5Filter
198 #define telephoneNumberSubstringsIndexer caseIgnoreIA5SubstringsIndexer
199 #define telephoneNumberSubstringsFilter caseIgnoreIA5SubstringsFilter
203 static char *bvcasechr( struct berval *bv, unsigned char c, ber_len_t *len )
206 char lower = TOLOWER( c );
207 char upper = TOUPPER( c );
209 if( c == 0 ) return NULL;
211 for( i=0; i < bv->bv_len; i++ ) {
212 if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
214 return &bv->bv_val[i];
227 struct berval *value,
228 void *assertedValue )
230 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
233 match = memcmp( value->bv_val,
234 ((struct berval *) assertedValue)->bv_val,
243 octetStringOrderingMatch(
248 struct berval *value,
249 void *assertedValue )
251 ber_len_t v_len = value->bv_len;
252 ber_len_t av_len = ((struct berval *) assertedValue)->bv_len;
254 int match = memcmp( value->bv_val,
255 ((struct berval *) assertedValue)->bv_val,
256 (v_len < av_len ? v_len : av_len) );
258 if( match == 0 ) match = v_len - av_len;
264 /* Index generation function */
265 int octetStringIndexer(
270 struct berval *prefix,
277 HASH_CONTEXT HASHcontext;
278 unsigned char HASHdigest[HASH_BYTES];
279 struct berval digest;
280 digest.bv_val = HASHdigest;
281 digest.bv_len = sizeof(HASHdigest);
283 for( i=0; values[i].bv_val != NULL; i++ ) {
284 /* just count them */
287 /* we should have at least one value at this point */
290 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
292 slen = syntax->ssyn_oidlen;
293 mlen = mr->smr_oidlen;
295 for( i=0; values[i].bv_val != NULL; i++ ) {
296 HASH_Init( &HASHcontext );
297 if( prefix != NULL && prefix->bv_len > 0 ) {
298 HASH_Update( &HASHcontext,
299 prefix->bv_val, prefix->bv_len );
301 HASH_Update( &HASHcontext,
302 syntax->ssyn_oid, slen );
303 HASH_Update( &HASHcontext,
305 HASH_Update( &HASHcontext,
306 values[i].bv_val, values[i].bv_len );
307 HASH_Final( HASHdigest, &HASHcontext );
309 ber_dupbv( &keys[i], &digest );
312 keys[i].bv_val = NULL;
320 /* Index generation function */
321 int octetStringFilter(
326 struct berval *prefix,
327 void * assertedValue,
332 HASH_CONTEXT HASHcontext;
333 unsigned char HASHdigest[HASH_BYTES];
334 struct berval *value = (struct berval *) assertedValue;
335 struct berval digest;
336 digest.bv_val = HASHdigest;
337 digest.bv_len = sizeof(HASHdigest);
339 slen = syntax->ssyn_oidlen;
340 mlen = mr->smr_oidlen;
342 keys = ch_malloc( sizeof( struct berval ) * 2 );
344 HASH_Init( &HASHcontext );
345 if( prefix != NULL && prefix->bv_len > 0 ) {
346 HASH_Update( &HASHcontext,
347 prefix->bv_val, prefix->bv_len );
349 HASH_Update( &HASHcontext,
350 syntax->ssyn_oid, slen );
351 HASH_Update( &HASHcontext,
353 HASH_Update( &HASHcontext,
354 value->bv_val, value->bv_len );
355 HASH_Final( HASHdigest, &HASHcontext );
357 ber_dupbv( keys, &digest );
358 keys[1].bv_val = NULL;
371 /* no value allowed */
372 return LDAP_INVALID_SYNTAX;
380 /* any value allowed */
391 /* very unforgiving validation, requires no normalization
392 * before simplistic matching
394 if( in->bv_len < 3 ) {
395 return LDAP_INVALID_SYNTAX;
399 * rfc 2252 section 6.3 Bit String
400 * bitstring = "'" *binary-digit "'"
401 * binary-digit = "0" / "1"
402 * example: '0101111101'B
405 if( in->bv_val[0] != '\'' ||
406 in->bv_val[in->bv_len-2] != '\'' ||
407 in->bv_val[in->bv_len-1] != 'B' )
409 return LDAP_INVALID_SYNTAX;
412 for( i=in->bv_len-3; i>0; i-- ) {
413 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
414 return LDAP_INVALID_SYNTAX;
429 if( in->bv_len == 0 ) return LDAP_SUCCESS;
431 ber_dupbv( &dn, in );
432 if( !dn.bv_val ) return LDAP_OTHER;
434 if( dn.bv_val[dn.bv_len-1] == 'B'
435 && dn.bv_val[dn.bv_len-2] == '\'' )
437 /* assume presence of optional UID */
440 for(i=dn.bv_len-3; i>1; i--) {
441 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
445 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
446 ber_memfree( dn.bv_val );
447 return LDAP_INVALID_SYNTAX;
450 /* trim the UID to allow use of dnValidate */
451 dn.bv_val[i-1] = '\0';
455 rc = dnValidate( NULL, &dn );
457 ber_memfree( dn.bv_val );
467 struct berval *normalized )
472 ber_dupbv( &out, val );
473 if( out.bv_len != 0 ) {
474 struct berval uid = { 0, NULL };
476 if( out.bv_val[out.bv_len-1] == 'B'
477 && out.bv_val[out.bv_len-2] == '\'' )
479 /* assume presence of optional UID */
480 uid.bv_val = strrchr( out.bv_val, '#' );
482 if( uid.bv_val == NULL ) {
484 return LDAP_INVALID_SYNTAX;
487 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
488 out.bv_len -= uid.bv_len--;
490 /* temporarily trim the UID */
491 *(uid.bv_val++) = '\0';
494 rc = dnNormalize2( NULL, &out, normalized );
496 if( rc != LDAP_SUCCESS ) {
498 return LDAP_INVALID_SYNTAX;
502 normalized->bv_val = ch_realloc( normalized->bv_val,
503 normalized->bv_len + uid.bv_len + sizeof("#") );
505 /* insert the separator */
506 normalized->bv_val[normalized->bv_len++] = '#';
509 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
510 uid.bv_val, uid.bv_len );
511 normalized->bv_len += uid.bv_len;
514 normalized->bv_val[normalized->bv_len] = '\0';
525 * Handling boolean syntax and matching is quite rigid.
526 * A more flexible approach would be to allow a variety
527 * of strings to be normalized and prettied into TRUE
535 /* very unforgiving validation, requires no normalization
536 * before simplistic matching
539 if( in->bv_len == 4 ) {
540 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
543 } else if( in->bv_len == 5 ) {
544 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
549 return LDAP_INVALID_SYNTAX;
558 struct berval *value,
559 void *assertedValue )
561 /* simplistic matching allowed by rigid validation */
562 struct berval *asserted = (struct berval *) assertedValue;
563 *matchp = value->bv_len != asserted->bv_len;
567 /*-------------------------------------------------------------------
568 LDAP/X.500 string syntax / matching rules have a few oddities. This
569 comment attempts to detail how slapd(8) treats them.
572 StringSyntax X.500 LDAP Matching
573 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
574 PrintableString subset subset i/e + ignore insignificant spaces
575 NumericString subset subset ignore all spaces
576 IA5String ASCII ASCII i/e + ignore insignificant spaces
577 TeletexString T.61 T.61 i/e + ignore insignificant spaces
579 TelephoneNumber subset subset i + ignore all spaces and "-"
581 See draft-ietf-ldapbis-strpro for details (once published).
585 In X.500(93), a directory string can be either a PrintableString,
586 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
587 In later versions, more CHOICEs were added. In all cases the string
590 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
592 For matching, there are both case ignore and exact rules. Both
593 also require that "insignificant" spaces be ignored.
594 spaces before the first non-space are ignored;
595 spaces after the last non-space are ignored;
596 spaces after a space are ignored.
597 Note: by these rules (and as clarified in X.520), a string of only
598 spaces is to be treated as if held one space, not empty (which
599 would be a syntax error).
602 In ASN.1, numeric string is just a string of digits and spaces
603 and could be empty. However, in X.500, all attribute values of
604 numeric string carry a non-empty constraint. For example:
606 internationalISDNNumber ATTRIBUTE ::= {
607 WITH SYNTAX InternationalISDNNumber
608 EQUALITY MATCHING RULE numericStringMatch
609 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
610 ID id-at-internationalISDNNumber }
611 InternationalISDNNumber ::=
612 NumericString (SIZE(1..ub-international-isdn-number))
614 Unforunately, some assertion values are don't carry the same
615 constraint (but its unclear how such an assertion could ever
616 be true). In LDAP, there is one syntax (numericString) not two
617 (numericString with constraint, numericString without constraint).
618 This should be treated as numericString with non-empty constraint.
619 Note that while someone may have no ISDN number, there are no ISDN
620 numbers which are zero length.
622 In matching, spaces are ignored.
625 In ASN.1, Printable string is just a string of printable characters
626 and can be empty. In X.500, semantics much like NumericString (see
627 serialNumber for a like example) excepting uses insignificant space
628 handling instead of ignore all spaces.
631 Basically same as PrintableString. There are no examples in X.500,
632 but same logic applies. So we require them to be non-empty as
635 -------------------------------------------------------------------*/
644 unsigned char *u = in->bv_val;
646 if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
648 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
649 /* get the length indicated by the first byte */
650 len = LDAP_UTF8_CHARLEN2( u, len );
652 /* very basic checks */
655 if( (u[5] & 0xC0) != 0x80 ) {
656 return LDAP_INVALID_SYNTAX;
659 if( (u[4] & 0xC0) != 0x80 ) {
660 return LDAP_INVALID_SYNTAX;
663 if( (u[3] & 0xC0) != 0x80 ) {
664 return LDAP_INVALID_SYNTAX;
667 if( (u[2] & 0xC0 )!= 0x80 ) {
668 return LDAP_INVALID_SYNTAX;
671 if( (u[1] & 0xC0) != 0x80 ) {
672 return LDAP_INVALID_SYNTAX;
675 /* CHARLEN already validated it */
678 return LDAP_INVALID_SYNTAX;
681 /* make sure len corresponds with the offset
682 to the next character */
683 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
686 if( count != 0 ) return LDAP_INVALID_SYNTAX;
694 xUTF8StringNormalize(
697 struct berval *normalized )
702 /* validator should have refused an empty string */
703 assert( val->bv_len );
707 /* Ignore initial whitespace */
708 /* All space is ASCII. All ASCII is 1 byte */
709 for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
711 normalized->bv_len = val->bv_len - (p - val->bv_val);
713 if( !normalized->bv_len ) {
714 ber_mem2bv( " ", 1, 1, normalized );
718 ber_mem2bv( p, normalized->bv_len, 1, normalized );
719 e = normalized->bv_val + normalized->bv_len;
721 assert( normalized->bv_val );
723 p = q = normalized->bv_val;
728 if ( ASCII_SPACE( *p ) ) {
733 /* Ignore the extra whitespace */
734 while ( ASCII_SPACE( *p ) ) {
738 len = LDAP_UTF8_COPY(q,p);
744 assert( normalized->bv_val <= p );
745 assert( q+len <= p );
747 /* cannot start with a space */
748 assert( !ASCII_SPACE( normalized->bv_val[0] ) );
751 * If the string ended in space, backup the pointer one
752 * position. One is enough because the above loop collapsed
753 * all whitespace to a single space.
761 /* cannot end with a space */
762 assert( !ASCII_SPACE( *q ) );
769 normalized->bv_len = q - normalized->bv_val;
774 /* Returns Unicode canonically normalized copy of a substring assertion
775 * Skipping attribute description */
776 static SubstringsAssertion *
777 UTF8SubstringsAssertionNormalize(
778 SubstringsAssertion *sa,
781 SubstringsAssertion *nsa;
784 nsa = (SubstringsAssertion *)SLAP_CALLOC( 1, sizeof(SubstringsAssertion) );
789 if( sa->sa_initial.bv_val != NULL ) {
790 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
791 if( nsa->sa_initial.bv_val == NULL ) {
796 if( sa->sa_any != NULL ) {
797 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
800 nsa->sa_any = (struct berval *)
801 SLAP_MALLOC( (i + 1) * sizeof(struct berval) );
802 if( nsa->sa_any == NULL ) {
806 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
807 UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
809 if( nsa->sa_any[i].bv_val == NULL ) {
813 nsa->sa_any[i].bv_val = NULL;
816 if( sa->sa_final.bv_val != NULL ) {
817 UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
818 if( nsa->sa_final.bv_val == NULL ) {
826 if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
827 if ( nsa->sa_any ) ber_bvarray_free( nsa->sa_any );
828 if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
833 #ifndef SLAPD_APPROX_OLDSINGLESTRING
835 #if defined(SLAPD_APPROX_INITIALS)
836 #define SLAPD_APPROX_DELIMITER "._ "
837 #define SLAPD_APPROX_WORDLEN 2
839 #define SLAPD_APPROX_DELIMITER " "
840 #define SLAPD_APPROX_WORDLEN 1
849 struct berval *value,
850 void *assertedValue )
852 struct berval *nval, *assertv;
853 char *val, **values, **words, *c;
854 int i, count, len, nextchunk=0, nextavail=0;
856 /* Yes, this is necessary */
857 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
863 /* Yes, this is necessary */
864 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
865 NULL, LDAP_UTF8_APPROX );
866 if( assertv == NULL ) {
872 /* Isolate how many words there are */
873 for ( c = nval->bv_val, count = 1; *c; c++ ) {
874 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
875 if ( c == NULL ) break;
880 /* Get a phonetic copy of each word */
881 words = (char **)ch_malloc( count * sizeof(char *) );
882 values = (char **)ch_malloc( count * sizeof(char *) );
883 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
885 values[i] = phonetic(c);
888 /* Work through the asserted value's words, to see if at least some
889 of the words are there, in the same order. */
891 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
892 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
897 #if defined(SLAPD_APPROX_INITIALS)
898 else if( len == 1 ) {
899 /* Single letter words need to at least match one word's initial */
900 for( i=nextavail; i<count; i++ )
901 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
908 /* Isolate the next word in the asserted value and phonetic it */
909 assertv->bv_val[nextchunk+len] = '\0';
910 val = phonetic( assertv->bv_val + nextchunk );
912 /* See if this phonetic chunk is in the remaining words of *value */
913 for( i=nextavail; i<count; i++ ){
914 if( !strcmp( val, values[i] ) ){
922 /* This chunk in the asserted value was NOT within the *value. */
928 /* Go on to the next word in the asserted value */
932 /* If some of the words were seen, call it a match */
933 if( nextavail > 0 ) {
941 ber_bvfree( assertv );
942 for( i=0; i<count; i++ ) {
943 ch_free( values[i] );
958 struct berval *prefix,
963 int i,j, len, wordcount, keycount=0;
964 struct berval *newkeys;
967 for( j=0; values[j].bv_val != NULL; j++ ) {
968 struct berval val = { 0, NULL };
969 /* Yes, this is necessary */
970 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
971 assert( val.bv_val != NULL );
973 /* Isolate how many words there are. There will be a key for each */
974 for( wordcount = 0, c = val.bv_val; *c; c++) {
975 len = strcspn(c, SLAPD_APPROX_DELIMITER);
976 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
978 if (*c == '\0') break;
982 /* Allocate/increase storage to account for new keys */
983 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
984 * sizeof(struct berval) );
985 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
986 if( keys ) ch_free( keys );
989 /* Get a phonetic copy of each word */
990 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
992 if( len < SLAPD_APPROX_WORDLEN ) continue;
993 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
998 ber_memfree( val.bv_val );
1000 keys[keycount].bv_val = NULL;
1003 return LDAP_SUCCESS;
1012 struct berval *prefix,
1013 void * assertedValue,
1021 /* Yes, this is necessary */
1022 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1023 NULL, LDAP_UTF8_APPROX );
1024 if( val == NULL || val->bv_val == NULL ) {
1025 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1026 keys[0].bv_val = NULL;
1029 return LDAP_SUCCESS;
1032 /* Isolate how many words there are. There will be a key for each */
1033 for( count = 0,c = val->bv_val; *c; c++) {
1034 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1035 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1037 if (*c == '\0') break;
1041 /* Allocate storage for new keys */
1042 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1044 /* Get a phonetic copy of each word */
1045 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1047 if( len < SLAPD_APPROX_WORDLEN ) continue;
1048 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1054 keys[count].bv_val = NULL;
1057 return LDAP_SUCCESS;
1062 /* No other form of Approximate Matching is defined */
1070 struct berval *value,
1071 void *assertedValue )
1073 char *vapprox, *avapprox;
1076 /* Yes, this is necessary */
1077 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1080 return LDAP_SUCCESS;
1083 /* Yes, this is necessary */
1084 t = UTF8normalize( ((struct berval *)assertedValue),
1089 return LDAP_SUCCESS;
1092 vapprox = phonetic( strip8bitChars( s ) );
1093 avapprox = phonetic( strip8bitChars( t ) );
1098 *matchp = strcmp( vapprox, avapprox );
1101 ch_free( avapprox );
1103 return LDAP_SUCCESS;
1112 struct berval *prefix,
1120 for( i=0; values[i].bv_val != NULL; i++ ) {
1121 /* empty - just count them */
1124 /* we should have at least one value at this point */
1127 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1129 /* Copy each value and run it through phonetic() */
1130 for( i=0; values[i].bv_val != NULL; i++ ) {
1131 /* Yes, this is necessary */
1132 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1134 /* strip 8-bit chars and run through phonetic() */
1135 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1138 keys[i].bv_val = NULL;
1141 return LDAP_SUCCESS;
1151 struct berval *prefix,
1152 void * assertedValue,
1158 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1160 /* Yes, this is necessary */
1161 s = UTF8normalize( ((struct berval *)assertedValue),
1166 /* strip 8-bit chars and run through phonetic() */
1167 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1173 return LDAP_SUCCESS;
1184 struct berval *value,
1185 void *assertedValue )
1187 *matchp = UTF8bvnormcmp( value,
1188 (struct berval *) assertedValue,
1189 LDAP_UTF8_NOCASEFOLD );
1190 return LDAP_SUCCESS;
1194 caseExactIgnoreSubstringsMatch(
1199 struct berval *value,
1200 void *assertedValue )
1203 SubstringsAssertion *sub = NULL;
1204 struct berval left = { 0, NULL };
1210 casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
1211 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1213 if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1219 sub = UTF8SubstringsAssertionNormalize( assertedValue, casefold );
1225 /* Add up asserted input length */
1226 if( sub->sa_initial.bv_val ) {
1227 inlen += sub->sa_initial.bv_len;
1230 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1231 inlen += sub->sa_any[i].bv_len;
1234 if( sub->sa_final.bv_val ) {
1235 inlen += sub->sa_final.bv_len;
1238 if( sub->sa_initial.bv_val ) {
1239 if( inlen > left.bv_len ) {
1244 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1245 sub->sa_initial.bv_len );
1251 left.bv_val += sub->sa_initial.bv_len;
1252 left.bv_len -= sub->sa_initial.bv_len;
1253 inlen -= sub->sa_initial.bv_len;
1256 if( sub->sa_final.bv_val ) {
1257 if( inlen > left.bv_len ) {
1262 match = memcmp( sub->sa_final.bv_val,
1263 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1264 sub->sa_final.bv_len );
1270 left.bv_len -= sub->sa_final.bv_len;
1271 inlen -= sub->sa_final.bv_len;
1275 for(i=0; sub->sa_any[i].bv_val; i++) {
1280 if( inlen > left.bv_len ) {
1281 /* not enough length */
1286 if( sub->sa_any[i].bv_len == 0 ) {
1290 p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1296 idx = p - left.bv_val;
1298 if( idx >= left.bv_len ) {
1299 /* this shouldn't happen */
1301 if ( sub->sa_final.bv_val )
1302 ch_free( sub->sa_final.bv_val );
1304 ber_bvarray_free( sub->sa_any );
1305 if ( sub->sa_initial.bv_val )
1306 ch_free( sub->sa_initial.bv_val );
1314 if( sub->sa_any[i].bv_len > left.bv_len ) {
1315 /* not enough left */
1320 match = memcmp( left.bv_val,
1321 sub->sa_any[i].bv_val,
1322 sub->sa_any[i].bv_len );
1330 left.bv_val += sub->sa_any[i].bv_len;
1331 left.bv_len -= sub->sa_any[i].bv_len;
1332 inlen -= sub->sa_any[i].bv_len;
1339 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1340 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1341 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1345 return LDAP_SUCCESS;
1348 /* Index generation function */
1349 static int caseExactIgnoreIndexer(
1354 struct berval *prefix,
1359 unsigned casefold,wasspace;
1362 HASH_CONTEXT HASHcontext;
1363 unsigned char HASHdigest[HASH_BYTES];
1364 struct berval digest;
1365 digest.bv_val = HASHdigest;
1366 digest.bv_len = sizeof(HASHdigest);
1368 for( i=0; values[i].bv_val != NULL; i++ ) {
1369 /* empty - just count them */
1372 /* we should have at least one value at this point */
1375 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1377 slen = syntax->ssyn_oidlen;
1378 mlen = mr->smr_oidlen;
1380 casefold = ( mr != slap_schema.si_mr_caseExactMatch )
1381 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1383 for( i=0; values[i].bv_val != NULL; i++ ) {
1384 struct berval value, nvalue;
1385 UTF8bvnormalize( &values[i], &value, casefold );
1387 /* collapse spaces (in place) */
1389 nvalue.bv_val = value.bv_val;
1392 for( j=0; j<value.bv_len; j++) {
1393 if ( ASCII_SPACE( value.bv_val[j] )) {
1394 if( wasspace++ == 0 ) {
1395 nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
1399 nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
1403 if( nvalue.bv_len == 0 ) {
1404 nvalue.bv_val = " ";
1405 nvalue.bv_len = sizeof(" ")-1;
1407 if( wasspace ) --nvalue.bv_len;
1408 nvalue.bv_val[nvalue.bv_len] = '\0';
1411 HASH_Init( &HASHcontext );
1412 if( prefix != NULL && prefix->bv_len > 0 ) {
1413 HASH_Update( &HASHcontext,
1414 prefix->bv_val, prefix->bv_len );
1416 HASH_Update( &HASHcontext,
1417 syntax->ssyn_oid, slen );
1418 HASH_Update( &HASHcontext,
1419 mr->smr_oid, mlen );
1420 HASH_Update( &HASHcontext,
1421 nvalue.bv_val, nvalue.bv_len );
1422 HASH_Final( HASHdigest, &HASHcontext );
1424 free( value.bv_val );
1425 ber_dupbv( &keys[i], &digest );
1428 keys[i].bv_val = NULL;
1430 return LDAP_SUCCESS;
1433 /* Index generation function */
1434 static int caseExactIgnoreFilter(
1439 struct berval *prefix,
1440 void * assertedValue,
1446 HASH_CONTEXT HASHcontext;
1447 unsigned char HASHdigest[HASH_BYTES];
1448 struct berval value = { 0, NULL };
1449 struct berval digest;
1451 digest.bv_val = HASHdigest;
1452 digest.bv_len = sizeof(HASHdigest);
1454 slen = syntax->ssyn_oidlen;
1455 mlen = mr->smr_oidlen;
1457 casefold = ( mr != slap_schema.si_mr_caseExactMatch )
1458 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1460 UTF8bvnormalize( (struct berval *) assertedValue, &value, casefold );
1461 /* This usually happens if filter contains bad UTF8 */
1462 if( value.bv_val == NULL ) {
1463 keys = ch_malloc( sizeof( struct berval ) );
1464 keys[0].bv_val = NULL;
1465 return LDAP_SUCCESS;
1468 keys = ch_malloc( sizeof( struct berval ) * 2 );
1470 HASH_Init( &HASHcontext );
1471 if( prefix != NULL && prefix->bv_len > 0 ) {
1472 HASH_Update( &HASHcontext,
1473 prefix->bv_val, prefix->bv_len );
1475 HASH_Update( &HASHcontext,
1476 syntax->ssyn_oid, slen );
1477 HASH_Update( &HASHcontext,
1478 mr->smr_oid, mlen );
1479 HASH_Update( &HASHcontext,
1480 value.bv_val, value.bv_len );
1481 HASH_Final( HASHdigest, &HASHcontext );
1483 ber_dupbv( keys, &digest );
1484 keys[1].bv_val = NULL;
1486 free( value.bv_val );
1489 return LDAP_SUCCESS;
1492 /* Substrings Index generation function */
1493 static int caseExactIgnoreSubstringsIndexer(
1498 struct berval *prefix,
1502 unsigned casefold, wasspace;
1503 ber_len_t i, j, nkeys;
1506 BerVarray tvalues, nvalues;
1508 HASH_CONTEXT HASHcontext;
1509 unsigned char HASHdigest[HASH_BYTES];
1510 struct berval digest;
1511 digest.bv_val = HASHdigest;
1512 digest.bv_len = sizeof(HASHdigest);
1516 for( i=0; values[i].bv_val != NULL; i++ ) {
1517 /* empty - just count them */
1520 /* we should have at least one value at this point */
1523 casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
1524 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1526 tvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1527 nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1529 for( i=0; values[i].bv_val != NULL; i++ ) {
1530 UTF8bvnormalize( &values[i], &tvalues[i], casefold );
1532 /* collapse spaces (in place) */
1533 nvalues[i].bv_len = 0;
1534 nvalues[i].bv_val = tvalues[i].bv_val;
1537 for( j=0; j<tvalues[i].bv_len; j++) {
1538 if ( ASCII_SPACE( tvalues[i].bv_val[j] )) {
1539 if( wasspace++ == 0 ) {
1540 nvalues[i].bv_val[nvalues[i].bv_len++] =
1541 tvalues[i].bv_val[j];
1545 nvalues[i].bv_val[nvalues[i].bv_len++] = tvalues[i].bv_val[j];
1549 if( nvalues[i].bv_len == 0 ) {
1550 nvalues[i].bv_val = " ";
1551 nvalues[i].bv_len = sizeof(" ")-1;
1553 if( wasspace ) --nvalues[i].bv_len;
1554 nvalues[i].bv_val[nvalues[i].bv_len] = '\0';
1558 tvalues[i].bv_val = NULL;
1559 nvalues[i].bv_val = NULL;
1562 for( i=0; values[i].bv_val != NULL; i++ ) {
1563 /* count number of indices to generate */
1564 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1568 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1569 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1570 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1571 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1573 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1577 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1578 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1579 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1583 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1584 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1585 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1586 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1588 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1594 /* no keys to generate */
1596 ber_bvarray_free( tvalues );
1598 return LDAP_SUCCESS;
1601 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1603 slen = syntax->ssyn_oidlen;
1604 mlen = mr->smr_oidlen;
1607 for( i=0; values[i].bv_val != NULL; i++ ) {
1610 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1612 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1613 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1615 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1616 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1618 for( j=0; j<max; j++ ) {
1619 HASH_Init( &HASHcontext );
1620 if( prefix != NULL && prefix->bv_len > 0 ) {
1621 HASH_Update( &HASHcontext,
1622 prefix->bv_val, prefix->bv_len );
1625 HASH_Update( &HASHcontext,
1626 &pre, sizeof( pre ) );
1627 HASH_Update( &HASHcontext,
1628 syntax->ssyn_oid, slen );
1629 HASH_Update( &HASHcontext,
1630 mr->smr_oid, mlen );
1631 HASH_Update( &HASHcontext,
1632 &values[i].bv_val[j],
1633 SLAP_INDEX_SUBSTR_MAXLEN );
1634 HASH_Final( HASHdigest, &HASHcontext );
1636 ber_dupbv( &keys[nkeys++], &digest );
1640 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1641 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1643 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1646 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1647 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1648 HASH_Init( &HASHcontext );
1649 if( prefix != NULL && prefix->bv_len > 0 ) {
1650 HASH_Update( &HASHcontext,
1651 prefix->bv_val, prefix->bv_len );
1653 HASH_Update( &HASHcontext,
1654 &pre, sizeof( pre ) );
1655 HASH_Update( &HASHcontext,
1656 syntax->ssyn_oid, slen );
1657 HASH_Update( &HASHcontext,
1658 mr->smr_oid, mlen );
1659 HASH_Update( &HASHcontext,
1660 values[i].bv_val, j );
1661 HASH_Final( HASHdigest, &HASHcontext );
1663 ber_dupbv( &keys[nkeys++], &digest );
1666 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1667 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1668 HASH_Init( &HASHcontext );
1669 if( prefix != NULL && prefix->bv_len > 0 ) {
1670 HASH_Update( &HASHcontext,
1671 prefix->bv_val, prefix->bv_len );
1673 HASH_Update( &HASHcontext,
1674 &pre, sizeof( pre ) );
1675 HASH_Update( &HASHcontext,
1676 syntax->ssyn_oid, slen );
1677 HASH_Update( &HASHcontext,
1678 mr->smr_oid, mlen );
1679 HASH_Update( &HASHcontext,
1680 &values[i].bv_val[values[i].bv_len-j], j );
1681 HASH_Final( HASHdigest, &HASHcontext );
1683 ber_dupbv( &keys[nkeys++], &digest );
1691 keys[nkeys].bv_val = NULL;
1698 ber_bvarray_free( tvalues );
1701 return LDAP_SUCCESS;
1704 static int caseExactIgnoreSubstringsFilter(
1709 struct berval *prefix,
1710 void * assertedValue,
1713 SubstringsAssertion *sa;
1716 ber_len_t nkeys = 0;
1717 size_t slen, mlen, klen;
1719 HASH_CONTEXT HASHcontext;
1720 unsigned char HASHdigest[HASH_BYTES];
1721 struct berval *value;
1722 struct berval digest;
1724 casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
1725 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1727 sa = UTF8SubstringsAssertionNormalize( assertedValue, casefold );
1730 return LDAP_SUCCESS;
1733 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1734 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1739 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1741 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1742 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1743 /* don't bother accounting for stepping */
1744 nkeys += sa->sa_any[i].bv_len -
1745 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1750 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1751 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1757 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1758 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1759 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1762 return LDAP_SUCCESS;
1765 digest.bv_val = HASHdigest;
1766 digest.bv_len = sizeof(HASHdigest);
1768 slen = syntax->ssyn_oidlen;
1769 mlen = mr->smr_oidlen;
1771 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1774 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1775 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1777 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1778 value = &sa->sa_initial;
1780 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1781 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1783 HASH_Init( &HASHcontext );
1784 if( prefix != NULL && prefix->bv_len > 0 ) {
1785 HASH_Update( &HASHcontext,
1786 prefix->bv_val, prefix->bv_len );
1788 HASH_Update( &HASHcontext,
1789 &pre, sizeof( pre ) );
1790 HASH_Update( &HASHcontext,
1791 syntax->ssyn_oid, slen );
1792 HASH_Update( &HASHcontext,
1793 mr->smr_oid, mlen );
1794 HASH_Update( &HASHcontext,
1795 value->bv_val, klen );
1796 HASH_Final( HASHdigest, &HASHcontext );
1798 ber_dupbv( &keys[nkeys++], &digest );
1801 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1803 pre = SLAP_INDEX_SUBSTR_PREFIX;
1804 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1806 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1807 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1811 value = &sa->sa_any[i];
1814 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1815 j += SLAP_INDEX_SUBSTR_STEP )
1817 HASH_Init( &HASHcontext );
1818 if( prefix != NULL && prefix->bv_len > 0 ) {
1819 HASH_Update( &HASHcontext,
1820 prefix->bv_val, prefix->bv_len );
1822 HASH_Update( &HASHcontext,
1823 &pre, sizeof( pre ) );
1824 HASH_Update( &HASHcontext,
1825 syntax->ssyn_oid, slen );
1826 HASH_Update( &HASHcontext,
1827 mr->smr_oid, mlen );
1828 HASH_Update( &HASHcontext,
1829 &value->bv_val[j], klen );
1830 HASH_Final( HASHdigest, &HASHcontext );
1832 ber_dupbv( &keys[nkeys++], &digest );
1838 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1839 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1841 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1842 value = &sa->sa_final;
1844 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1845 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1847 HASH_Init( &HASHcontext );
1848 if( prefix != NULL && prefix->bv_len > 0 ) {
1849 HASH_Update( &HASHcontext,
1850 prefix->bv_val, prefix->bv_len );
1852 HASH_Update( &HASHcontext,
1853 &pre, sizeof( pre ) );
1854 HASH_Update( &HASHcontext,
1855 syntax->ssyn_oid, slen );
1856 HASH_Update( &HASHcontext,
1857 mr->smr_oid, mlen );
1858 HASH_Update( &HASHcontext,
1859 &value->bv_val[value->bv_len-klen], klen );
1860 HASH_Final( HASHdigest, &HASHcontext );
1862 ber_dupbv( &keys[nkeys++], &digest );
1866 keys[nkeys].bv_val = NULL;
1872 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1873 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1874 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1877 return LDAP_SUCCESS;
1886 struct berval *value,
1887 void *assertedValue )
1889 *matchp = UTF8bvnormcmp( value,
1890 (struct berval *) assertedValue,
1891 LDAP_UTF8_CASEFOLD );
1892 return LDAP_SUCCESS;
1895 /* Remove all spaces and '-' characters */
1897 xtelephoneNumberNormalize(
1900 struct berval *normalized )
1904 /* validator should have refused an empty string */
1905 assert( val->bv_len );
1907 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1909 for( p = val->bv_val; *p; p++ ) {
1910 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1916 normalized->bv_len = q - normalized->bv_val;
1918 if( normalized->bv_len == 0 ) {
1919 free( normalized->bv_val );
1920 return LDAP_INVALID_SYNTAX;
1923 return LDAP_SUCCESS;
1930 struct berval *val )
1934 if( val->bv_len == 0 ) {
1935 /* disallow empty strings */
1936 return LDAP_INVALID_SYNTAX;
1939 if( OID_LEADCHAR(val->bv_val[0]) ) {
1941 for(i=1; i < val->bv_len; i++) {
1942 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1943 if( dot++ ) return 1;
1944 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1947 return LDAP_INVALID_SYNTAX;
1951 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1953 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1954 for(i=1; i < val->bv_len; i++) {
1955 if( !DESC_CHAR(val->bv_val[i] ) ) {
1956 return LDAP_INVALID_SYNTAX;
1960 return LDAP_SUCCESS;
1963 return LDAP_INVALID_SYNTAX;
1966 #ifndef SLAP_NVALUES
1974 struct berval *value,
1975 void *assertedValue )
1978 int vsign = 1, avsign = 1; /* default sign = '+' */
1979 struct berval *asserted;
1980 ber_len_t vlen, avlen;
1983 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1985 vlen = value->bv_len;
1986 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1987 char *tmp = memchr( v, '$', vlen );
1990 while( vlen && ASCII_SPACE( v[vlen-1] ))
1993 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) /* ANSI 2.2.1 */
1999 /* Do the same with the *assertedValue number */
2000 asserted = (struct berval *) assertedValue;
2001 av = asserted->bv_val;
2002 avlen = asserted->bv_len;
2003 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
2009 match = vsign - avsign;
2011 match = (vlen != avlen
2012 ? ( vlen < avlen ? -1 : 1 )
2013 : memcmp( v, av, vlen ));
2019 return LDAP_SUCCESS;
2026 struct berval *val )
2030 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
2032 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
2033 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
2034 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
2035 return LDAP_INVALID_SYNTAX;
2038 for( i=1; i < val->bv_len; i++ ) {
2039 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
2042 return LDAP_SUCCESS;
2045 #ifndef SLAP_NVALUES
2050 struct berval *normalized )
2060 /* Ignore leading spaces */
2061 while ( len && ( *p == ' ' )) {
2068 negative = ( *p == '-' );
2069 if(( *p == '-' ) || ( *p == '+' )) {
2075 /* Ignore leading zeros */
2076 while ( len && ( *p == '0' )) {
2081 /* If there are no non-zero digits left, the number is zero, otherwise
2082 allocate space for the number and copy it into the buffer */
2084 normalized->bv_val = ch_strdup("0");
2085 normalized->bv_len = 1;
2088 normalized->bv_len = len+negative;
2089 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
2091 normalized->bv_val[0] = '-';
2093 AC_MEMCPY( normalized->bv_val + negative, p, len );
2094 normalized->bv_val[len+negative] = '\0';
2097 return LDAP_SUCCESS;
2100 /* Index generation function */
2101 static int integerIndexer(
2106 struct berval *prefix,
2113 HASH_CONTEXT HASHcontext;
2114 unsigned char HASHdigest[HASH_BYTES];
2115 struct berval digest;
2116 digest.bv_val = HASHdigest;
2117 digest.bv_len = sizeof(HASHdigest);
2119 for( i=0; values[i].bv_val != NULL; i++ ) {
2120 /* empty - just count them */
2123 /* we should have at least one value at this point */
2126 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2128 slen = syntax->ssyn_oidlen;
2129 mlen = mr->smr_oidlen;
2131 for( i=0; values[i].bv_val != NULL; i++ ) {
2133 xintegerNormalize( syntax, &values[i], &norm );
2135 HASH_Init( &HASHcontext );
2136 if( prefix != NULL && prefix->bv_len > 0 ) {
2137 HASH_Update( &HASHcontext,
2138 prefix->bv_val, prefix->bv_len );
2140 HASH_Update( &HASHcontext,
2141 syntax->ssyn_oid, slen );
2142 HASH_Update( &HASHcontext,
2143 mr->smr_oid, mlen );
2144 HASH_Update( &HASHcontext,
2145 norm.bv_val, norm.bv_len );
2146 HASH_Final( HASHdigest, &HASHcontext );
2148 ber_dupbv( &keys[i], &digest );
2149 ch_free( norm.bv_val );
2152 keys[i].bv_val = NULL;
2154 return LDAP_SUCCESS;
2157 /* Index generation function */
2158 static int integerFilter(
2163 struct berval *prefix,
2164 void * assertedValue,
2169 HASH_CONTEXT HASHcontext;
2170 unsigned char HASHdigest[HASH_BYTES];
2172 struct berval digest;
2173 digest.bv_val = HASHdigest;
2174 digest.bv_len = sizeof(HASHdigest);
2176 slen = syntax->ssyn_oidlen;
2177 mlen = mr->smr_oidlen;
2179 xintegerNormalize( syntax, assertedValue, &norm );
2181 keys = ch_malloc( sizeof( struct berval ) * 2 );
2183 HASH_Init( &HASHcontext );
2184 if( prefix != NULL && prefix->bv_len > 0 ) {
2185 HASH_Update( &HASHcontext,
2186 prefix->bv_val, prefix->bv_len );
2188 HASH_Update( &HASHcontext,
2189 syntax->ssyn_oid, slen );
2190 HASH_Update( &HASHcontext,
2191 mr->smr_oid, mlen );
2192 HASH_Update( &HASHcontext,
2193 norm.bv_val, norm.bv_len );
2194 HASH_Final( HASHdigest, &HASHcontext );
2196 ber_dupbv( &keys[0], &digest );
2197 keys[1].bv_val = NULL;
2198 ch_free( norm.bv_val );
2201 return LDAP_SUCCESS;
2207 countryStringValidate(
2209 struct berval *val )
2211 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2213 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2214 return LDAP_INVALID_SYNTAX;
2216 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2217 return LDAP_INVALID_SYNTAX;
2220 return LDAP_SUCCESS;
2224 printableStringValidate(
2226 struct berval *val )
2230 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2232 for(i=0; i < val->bv_len; i++) {
2233 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2234 return LDAP_INVALID_SYNTAX;
2238 return LDAP_SUCCESS;
2242 printablesStringValidate(
2244 struct berval *val )
2248 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2250 for(i=0,len=0; i < val->bv_len; i++) {
2251 int c = val->bv_val[i];
2255 return LDAP_INVALID_SYNTAX;
2259 } else if ( SLAP_PRINTABLE(c) ) {
2262 return LDAP_INVALID_SYNTAX;
2267 return LDAP_INVALID_SYNTAX;
2270 return LDAP_SUCCESS;
2276 struct berval *val )
2280 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2282 for(i=0; i < val->bv_len; i++) {
2283 if( !LDAP_ASCII(val->bv_val[i]) ) {
2284 return LDAP_INVALID_SYNTAX;
2288 return LDAP_SUCCESS;
2291 #ifndef SLAP_NVALUES
2294 xIA5StringNormalize(
2297 struct berval *normalized )
2301 assert( val->bv_len );
2305 /* Ignore initial whitespace */
2306 while ( ASCII_SPACE( *p ) ) {
2310 normalized->bv_val = ch_strdup( p );
2311 p = q = normalized->bv_val;
2314 if ( ASCII_SPACE( *p ) ) {
2317 /* Ignore the extra whitespace */
2318 while ( ASCII_SPACE( *p ) ) {
2326 assert( normalized->bv_val <= p );
2330 * If the string ended in space, backup the pointer one
2331 * position. One is enough because the above loop collapsed
2332 * all whitespace to a single space.
2335 if ( ASCII_SPACE( q[-1] ) ) {
2339 /* null terminate */
2342 normalized->bv_len = q - normalized->bv_val;
2344 if( normalized->bv_len == 0 ) {
2345 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
2346 normalized->bv_val[0] = ' ';
2347 normalized->bv_val[1] = '\0';
2348 normalized->bv_len = 1;
2351 return LDAP_SUCCESS;
2360 struct berval *value,
2361 void *assertedValue )
2363 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2366 match = strncmp( value->bv_val,
2367 ((struct berval *) assertedValue)->bv_val,
2372 return LDAP_SUCCESS;
2376 caseExactIA5SubstringsMatch(
2381 struct berval *value,
2382 void *assertedValue )
2385 SubstringsAssertion *sub = assertedValue;
2386 struct berval left = *value;
2390 /* Add up asserted input length */
2391 if( sub->sa_initial.bv_val ) {
2392 inlen += sub->sa_initial.bv_len;
2395 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2396 inlen += sub->sa_any[i].bv_len;
2399 if( sub->sa_final.bv_val ) {
2400 inlen += sub->sa_final.bv_len;
2403 if( sub->sa_initial.bv_val ) {
2404 if( inlen > left.bv_len ) {
2409 match = strncmp( sub->sa_initial.bv_val, left.bv_val,
2410 sub->sa_initial.bv_len );
2416 left.bv_val += sub->sa_initial.bv_len;
2417 left.bv_len -= sub->sa_initial.bv_len;
2418 inlen -= sub->sa_initial.bv_len;
2421 if( sub->sa_final.bv_val ) {
2422 if( inlen > left.bv_len ) {
2427 match = strncmp( sub->sa_final.bv_val,
2428 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2429 sub->sa_final.bv_len );
2435 left.bv_len -= sub->sa_final.bv_len;
2436 inlen -= sub->sa_final.bv_len;
2440 for(i=0; sub->sa_any[i].bv_val; i++) {
2445 if( inlen > left.bv_len ) {
2446 /* not enough length */
2451 if( sub->sa_any[i].bv_len == 0 ) {
2455 p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
2462 idx = p - left.bv_val;
2464 if( idx >= left.bv_len ) {
2465 /* this shouldn't happen */
2472 if( sub->sa_any[i].bv_len > left.bv_len ) {
2473 /* not enough left */
2478 match = strncmp( left.bv_val,
2479 sub->sa_any[i].bv_val,
2480 sub->sa_any[i].bv_len );
2488 left.bv_val += sub->sa_any[i].bv_len;
2489 left.bv_len -= sub->sa_any[i].bv_len;
2490 inlen -= sub->sa_any[i].bv_len;
2496 return LDAP_SUCCESS;
2499 /* Index generation function */
2500 static int caseExactIA5Indexer(
2505 struct berval *prefix,
2512 HASH_CONTEXT HASHcontext;
2513 unsigned char HASHdigest[HASH_BYTES];
2514 struct berval digest;
2515 digest.bv_val = HASHdigest;
2516 digest.bv_len = sizeof(HASHdigest);
2518 for( i=0; values[i].bv_val != NULL; i++ ) {
2519 /* empty - just count them */
2522 /* we should have at least one value at this point */
2525 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2527 slen = syntax->ssyn_oidlen;
2528 mlen = mr->smr_oidlen;
2530 for( i=0; values[i].bv_val != NULL; i++ ) {
2531 struct berval *value = &values[i];
2533 HASH_Init( &HASHcontext );
2534 if( prefix != NULL && prefix->bv_len > 0 ) {
2535 HASH_Update( &HASHcontext,
2536 prefix->bv_val, prefix->bv_len );
2538 HASH_Update( &HASHcontext,
2539 syntax->ssyn_oid, slen );
2540 HASH_Update( &HASHcontext,
2541 mr->smr_oid, mlen );
2542 HASH_Update( &HASHcontext,
2543 value->bv_val, value->bv_len );
2544 HASH_Final( HASHdigest, &HASHcontext );
2546 ber_dupbv( &keys[i], &digest );
2549 keys[i].bv_val = NULL;
2551 return LDAP_SUCCESS;
2554 /* Index generation function */
2555 static int caseExactIA5Filter(
2560 struct berval *prefix,
2561 void * assertedValue,
2566 HASH_CONTEXT HASHcontext;
2567 unsigned char HASHdigest[HASH_BYTES];
2568 struct berval *value;
2569 struct berval digest;
2570 digest.bv_val = HASHdigest;
2571 digest.bv_len = sizeof(HASHdigest);
2573 slen = syntax->ssyn_oidlen;
2574 mlen = mr->smr_oidlen;
2576 value = (struct berval *) assertedValue;
2578 keys = ch_malloc( sizeof( struct berval ) * 2 );
2580 HASH_Init( &HASHcontext );
2581 if( prefix != NULL && prefix->bv_len > 0 ) {
2582 HASH_Update( &HASHcontext,
2583 prefix->bv_val, prefix->bv_len );
2585 HASH_Update( &HASHcontext,
2586 syntax->ssyn_oid, slen );
2587 HASH_Update( &HASHcontext,
2588 mr->smr_oid, mlen );
2589 HASH_Update( &HASHcontext,
2590 value->bv_val, value->bv_len );
2591 HASH_Final( HASHdigest, &HASHcontext );
2593 ber_dupbv( &keys[0], &digest );
2594 keys[1].bv_val = NULL;
2597 return LDAP_SUCCESS;
2600 /* Substrings Index generation function */
2601 static int caseExactIA5SubstringsIndexer(
2606 struct berval *prefix,
2613 HASH_CONTEXT HASHcontext;
2614 unsigned char HASHdigest[HASH_BYTES];
2615 struct berval digest;
2616 digest.bv_val = HASHdigest;
2617 digest.bv_len = sizeof(HASHdigest);
2619 /* we should have at least one value at this point */
2620 assert( values != NULL && values[0].bv_val != NULL );
2623 for( i=0; values[i].bv_val != NULL; i++ ) {
2624 /* count number of indices to generate */
2625 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2629 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2630 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2631 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2632 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2634 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2638 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2639 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2640 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2644 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2645 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2646 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2647 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2649 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2655 /* no keys to generate */
2657 return LDAP_SUCCESS;
2660 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2662 slen = syntax->ssyn_oidlen;
2663 mlen = mr->smr_oidlen;
2666 for( i=0; values[i].bv_val != NULL; i++ ) {
2668 struct berval *value;
2671 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2673 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2674 ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2676 char pre = SLAP_INDEX_SUBSTR_PREFIX;
2677 max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2679 for( j=0; j<max; j++ ) {
2680 HASH_Init( &HASHcontext );
2681 if( prefix != NULL && prefix->bv_len > 0 ) {
2682 HASH_Update( &HASHcontext,
2683 prefix->bv_val, prefix->bv_len );
2686 HASH_Update( &HASHcontext,
2687 &pre, sizeof( pre ) );
2688 HASH_Update( &HASHcontext,
2689 syntax->ssyn_oid, slen );
2690 HASH_Update( &HASHcontext,
2691 mr->smr_oid, mlen );
2692 HASH_Update( &HASHcontext,
2694 SLAP_INDEX_SUBSTR_MAXLEN );
2695 HASH_Final( HASHdigest, &HASHcontext );
2697 ber_dupbv( &keys[nkeys++], &digest );
2701 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2702 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2704 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2707 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2708 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2709 HASH_Init( &HASHcontext );
2710 if( prefix != NULL && prefix->bv_len > 0 ) {
2711 HASH_Update( &HASHcontext,
2712 prefix->bv_val, prefix->bv_len );
2714 HASH_Update( &HASHcontext,
2715 &pre, sizeof( pre ) );
2716 HASH_Update( &HASHcontext,
2717 syntax->ssyn_oid, slen );
2718 HASH_Update( &HASHcontext,
2719 mr->smr_oid, mlen );
2720 HASH_Update( &HASHcontext,
2722 HASH_Final( HASHdigest, &HASHcontext );
2724 ber_dupbv( &keys[nkeys++], &digest );
2727 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2728 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2729 HASH_Init( &HASHcontext );
2730 if( prefix != NULL && prefix->bv_len > 0 ) {
2731 HASH_Update( &HASHcontext,
2732 prefix->bv_val, prefix->bv_len );
2734 HASH_Update( &HASHcontext,
2735 &pre, sizeof( pre ) );
2736 HASH_Update( &HASHcontext,
2737 syntax->ssyn_oid, slen );
2738 HASH_Update( &HASHcontext,
2739 mr->smr_oid, mlen );
2740 HASH_Update( &HASHcontext,
2741 &value->bv_val[value->bv_len-j], j );
2742 HASH_Final( HASHdigest, &HASHcontext );
2744 ber_dupbv( &keys[nkeys++], &digest );
2751 keys[nkeys].bv_val = NULL;
2758 return LDAP_SUCCESS;
2761 static int caseExactIA5SubstringsFilter(
2766 struct berval *prefix,
2767 void * assertedValue,
2770 SubstringsAssertion *sa = assertedValue;
2772 ber_len_t nkeys = 0;
2773 size_t slen, mlen, klen;
2775 HASH_CONTEXT HASHcontext;
2776 unsigned char HASHdigest[HASH_BYTES];
2777 struct berval *value;
2778 struct berval digest;
2780 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2781 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2786 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2788 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2789 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2790 /* don't bother accounting for stepping */
2791 nkeys += sa->sa_any[i].bv_len -
2792 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2797 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2798 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2805 return LDAP_SUCCESS;
2808 digest.bv_val = HASHdigest;
2809 digest.bv_len = sizeof(HASHdigest);
2811 slen = syntax->ssyn_oidlen;
2812 mlen = mr->smr_oidlen;
2814 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2817 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2818 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2820 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2821 value = &sa->sa_initial;
2823 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2824 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2826 HASH_Init( &HASHcontext );
2827 if( prefix != NULL && prefix->bv_len > 0 ) {
2828 HASH_Update( &HASHcontext,
2829 prefix->bv_val, prefix->bv_len );
2831 HASH_Update( &HASHcontext,
2832 &pre, sizeof( pre ) );
2833 HASH_Update( &HASHcontext,
2834 syntax->ssyn_oid, slen );
2835 HASH_Update( &HASHcontext,
2836 mr->smr_oid, mlen );
2837 HASH_Update( &HASHcontext,
2838 value->bv_val, klen );
2839 HASH_Final( HASHdigest, &HASHcontext );
2841 ber_dupbv( &keys[nkeys++], &digest );
2844 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2846 pre = SLAP_INDEX_SUBSTR_PREFIX;
2847 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2849 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2850 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2854 value = &sa->sa_any[i];
2857 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2858 j += SLAP_INDEX_SUBSTR_STEP )
2860 HASH_Init( &HASHcontext );
2861 if( prefix != NULL && prefix->bv_len > 0 ) {
2862 HASH_Update( &HASHcontext,
2863 prefix->bv_val, prefix->bv_len );
2865 HASH_Update( &HASHcontext,
2866 &pre, sizeof( pre ) );
2867 HASH_Update( &HASHcontext,
2868 syntax->ssyn_oid, slen );
2869 HASH_Update( &HASHcontext,
2870 mr->smr_oid, mlen );
2871 HASH_Update( &HASHcontext,
2872 &value->bv_val[j], klen );
2873 HASH_Final( HASHdigest, &HASHcontext );
2875 ber_dupbv( &keys[nkeys++], &digest );
2880 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2881 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2883 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2884 value = &sa->sa_final;
2886 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2887 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2889 HASH_Init( &HASHcontext );
2890 if( prefix != NULL && prefix->bv_len > 0 ) {
2891 HASH_Update( &HASHcontext,
2892 prefix->bv_val, prefix->bv_len );
2894 HASH_Update( &HASHcontext,
2895 &pre, sizeof( pre ) );
2896 HASH_Update( &HASHcontext,
2897 syntax->ssyn_oid, slen );
2898 HASH_Update( &HASHcontext,
2899 mr->smr_oid, mlen );
2900 HASH_Update( &HASHcontext,
2901 &value->bv_val[value->bv_len-klen], klen );
2902 HASH_Final( HASHdigest, &HASHcontext );
2904 ber_dupbv( &keys[nkeys++], &digest );
2908 keys[nkeys].bv_val = NULL;
2915 return LDAP_SUCCESS;
2924 struct berval *value,
2925 void *assertedValue )
2927 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2929 if( match == 0 && value->bv_len ) {
2930 match = strncasecmp( value->bv_val,
2931 ((struct berval *) assertedValue)->bv_val,
2936 return LDAP_SUCCESS;
2940 caseIgnoreIA5SubstringsMatch(
2945 struct berval *value,
2946 void *assertedValue )
2949 SubstringsAssertion *sub = assertedValue;
2950 struct berval left = *value;
2954 /* Add up asserted input length */
2955 if( sub->sa_initial.bv_val ) {
2956 inlen += sub->sa_initial.bv_len;
2959 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2960 inlen += sub->sa_any[i].bv_len;
2963 if( sub->sa_final.bv_val ) {
2964 inlen += sub->sa_final.bv_len;
2967 if( sub->sa_initial.bv_val ) {
2968 if( inlen > left.bv_len ) {
2973 match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
2974 sub->sa_initial.bv_len );
2980 left.bv_val += sub->sa_initial.bv_len;
2981 left.bv_len -= sub->sa_initial.bv_len;
2982 inlen -= sub->sa_initial.bv_len;
2985 if( sub->sa_final.bv_val ) {
2986 if( inlen > left.bv_len ) {
2991 match = strncasecmp( sub->sa_final.bv_val,
2992 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2993 sub->sa_final.bv_len );
2999 left.bv_len -= sub->sa_final.bv_len;
3000 inlen -= sub->sa_final.bv_len;
3004 for(i=0; sub->sa_any[i].bv_val; i++) {
3009 if( inlen > left.bv_len ) {
3010 /* not enough length */
3015 if( sub->sa_any[i].bv_len == 0 ) {
3019 p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
3026 assert( idx < left.bv_len );
3027 if( idx >= left.bv_len ) {
3028 /* this shouldn't happen */
3035 if( sub->sa_any[i].bv_len > left.bv_len ) {
3036 /* not enough left */
3041 match = strncasecmp( left.bv_val,
3042 sub->sa_any[i].bv_val,
3043 sub->sa_any[i].bv_len );
3052 left.bv_val += sub->sa_any[i].bv_len;
3053 left.bv_len -= sub->sa_any[i].bv_len;
3054 inlen -= sub->sa_any[i].bv_len;
3060 return LDAP_SUCCESS;
3063 /* Index generation function */
3064 static int caseIgnoreIA5Indexer(
3069 struct berval *prefix,
3074 int rc = LDAP_SUCCESS;
3077 HASH_CONTEXT HASHcontext;
3078 unsigned char HASHdigest[HASH_BYTES];
3079 struct berval digest;
3080 digest.bv_val = HASHdigest;
3081 digest.bv_len = sizeof(HASHdigest);
3083 /* we should have at least one value at this point */
3084 assert( values != NULL && values[0].bv_val != NULL );
3086 for( i=0; values[i].bv_val != NULL; i++ ) {
3087 /* just count them */
3090 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3092 slen = syntax->ssyn_oidlen;
3093 mlen = mr->smr_oidlen;
3095 for( i=0; values[i].bv_val != NULL; i++ ) {
3096 struct berval value;
3098 if( mr->smr_normalize ) {
3099 rc = (mr->smr_normalize)( use, syntax, mr, &values[i], &value );
3100 if( rc != LDAP_SUCCESS ) {
3103 #ifndef SLAP_NVALUES
3104 } else if ( mr->smr_syntax->ssyn_normalize ) {
3105 rc = (mr->smr_syntax->ssyn_normalize)( syntax, &values[i], &value );
3106 if( rc != LDAP_SUCCESS ) {
3111 ber_dupbv( &value, &values[i] );
3114 ldap_pvt_str2lower( value.bv_val );
3116 HASH_Init( &HASHcontext );
3117 if( prefix != NULL && prefix->bv_len > 0 ) {
3118 HASH_Update( &HASHcontext,
3119 prefix->bv_val, prefix->bv_len );
3121 HASH_Update( &HASHcontext,
3122 syntax->ssyn_oid, slen );
3123 HASH_Update( &HASHcontext,
3124 mr->smr_oid, mlen );
3125 HASH_Update( &HASHcontext,
3126 value.bv_val, value.bv_len );
3127 HASH_Final( HASHdigest, &HASHcontext );
3129 free( value.bv_val );
3131 ber_dupbv( &keys[i], &digest );
3134 keys[i].bv_val = NULL;
3135 if( rc != LDAP_SUCCESS ) {
3136 ber_bvarray_free( keys );
3143 /* Index generation function */
3144 static int caseIgnoreIA5Filter(
3149 struct berval *prefix,
3150 void * assertedValue,
3155 HASH_CONTEXT HASHcontext;
3156 unsigned char HASHdigest[HASH_BYTES];
3157 struct berval value;
3158 struct berval digest;
3159 digest.bv_val = HASHdigest;
3160 digest.bv_len = sizeof(HASHdigest);
3162 slen = syntax->ssyn_oidlen;
3163 mlen = mr->smr_oidlen;
3165 ber_dupbv( &value, (struct berval *) assertedValue );
3166 ldap_pvt_str2lower( value.bv_val );
3168 keys = ch_malloc( sizeof( struct berval ) * 2 );
3170 HASH_Init( &HASHcontext );
3171 if( prefix != NULL && prefix->bv_len > 0 ) {
3172 HASH_Update( &HASHcontext,
3173 prefix->bv_val, prefix->bv_len );
3175 HASH_Update( &HASHcontext,
3176 syntax->ssyn_oid, slen );
3177 HASH_Update( &HASHcontext,
3178 mr->smr_oid, mlen );
3179 HASH_Update( &HASHcontext,
3180 value.bv_val, value.bv_len );
3181 HASH_Final( HASHdigest, &HASHcontext );
3183 ber_dupbv( &keys[0], &digest );
3184 keys[1].bv_val = NULL;
3186 free( value.bv_val );
3190 return LDAP_SUCCESS;
3193 /* Substrings Index generation function */
3194 static int caseIgnoreIA5SubstringsIndexer(
3199 struct berval *prefix,
3206 HASH_CONTEXT HASHcontext;
3207 unsigned char HASHdigest[HASH_BYTES];
3208 struct berval digest;
3209 digest.bv_val = HASHdigest;
3210 digest.bv_len = sizeof(HASHdigest);
3212 /* we should have at least one value at this point */
3213 assert( values != NULL && values[0].bv_val != NULL );
3216 for( i=0; values[i].bv_val != NULL; i++ ) {
3217 /* count number of indices to generate */
3218 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3222 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3223 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3224 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3225 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3227 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3231 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3232 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3233 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3237 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3238 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3239 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3240 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3242 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3248 /* no keys to generate */
3250 return LDAP_SUCCESS;
3253 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3255 slen = syntax->ssyn_oidlen;
3256 mlen = mr->smr_oidlen;
3259 for( i=0; values[i].bv_val != NULL; i++ ) {
3261 struct berval value;
3263 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3265 ber_dupbv( &value, &values[i] );
3266 ldap_pvt_str2lower( value.bv_val );
3268 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3269 ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3271 char pre = SLAP_INDEX_SUBSTR_PREFIX;
3272 max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3274 for( j=0; j<max; j++ ) {
3275 HASH_Init( &HASHcontext );
3276 if( prefix != NULL && prefix->bv_len > 0 ) {
3277 HASH_Update( &HASHcontext,
3278 prefix->bv_val, prefix->bv_len );
3281 HASH_Update( &HASHcontext,
3282 &pre, sizeof( pre ) );
3283 HASH_Update( &HASHcontext,
3284 syntax->ssyn_oid, slen );
3285 HASH_Update( &HASHcontext,
3286 mr->smr_oid, mlen );
3287 HASH_Update( &HASHcontext,
3289 SLAP_INDEX_SUBSTR_MAXLEN );
3290 HASH_Final( HASHdigest, &HASHcontext );
3292 ber_dupbv( &keys[nkeys++], &digest );
3296 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3297 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3299 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3302 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3303 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3304 HASH_Init( &HASHcontext );
3305 if( prefix != NULL && prefix->bv_len > 0 ) {
3306 HASH_Update( &HASHcontext,
3307 prefix->bv_val, prefix->bv_len );
3309 HASH_Update( &HASHcontext,
3310 &pre, sizeof( pre ) );
3311 HASH_Update( &HASHcontext,
3312 syntax->ssyn_oid, slen );
3313 HASH_Update( &HASHcontext,
3314 mr->smr_oid, mlen );
3315 HASH_Update( &HASHcontext,
3317 HASH_Final( HASHdigest, &HASHcontext );
3319 ber_dupbv( &keys[nkeys++], &digest );
3322 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3323 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3324 HASH_Init( &HASHcontext );
3325 if( prefix != NULL && prefix->bv_len > 0 ) {
3326 HASH_Update( &HASHcontext,
3327 prefix->bv_val, prefix->bv_len );
3329 HASH_Update( &HASHcontext,
3330 &pre, sizeof( pre ) );
3331 HASH_Update( &HASHcontext,
3332 syntax->ssyn_oid, slen );
3333 HASH_Update( &HASHcontext,
3334 mr->smr_oid, mlen );
3335 HASH_Update( &HASHcontext,
3336 &value.bv_val[value.bv_len-j], j );
3337 HASH_Final( HASHdigest, &HASHcontext );
3339 ber_dupbv( &keys[nkeys++], &digest );
3344 free( value.bv_val );
3348 keys[nkeys].bv_val = NULL;
3355 return LDAP_SUCCESS;
3358 static int caseIgnoreIA5SubstringsFilter(
3363 struct berval *prefix,
3364 void * assertedValue,
3367 SubstringsAssertion *sa = assertedValue;
3369 ber_len_t nkeys = 0;
3370 size_t slen, mlen, klen;
3372 HASH_CONTEXT HASHcontext;
3373 unsigned char HASHdigest[HASH_BYTES];
3374 struct berval value;
3375 struct berval digest;
3377 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3378 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3383 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3385 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3386 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3387 /* don't bother accounting for stepping */
3388 nkeys += sa->sa_any[i].bv_len -
3389 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3394 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3395 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3402 return LDAP_SUCCESS;
3405 digest.bv_val = HASHdigest;
3406 digest.bv_len = sizeof(HASHdigest);
3408 slen = syntax->ssyn_oidlen;
3409 mlen = mr->smr_oidlen;
3411 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3414 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3415 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3417 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3418 ber_dupbv( &value, &sa->sa_initial );
3419 ldap_pvt_str2lower( value.bv_val );
3421 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3422 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3424 HASH_Init( &HASHcontext );
3425 if( prefix != NULL && prefix->bv_len > 0 ) {
3426 HASH_Update( &HASHcontext,
3427 prefix->bv_val, prefix->bv_len );
3429 HASH_Update( &HASHcontext,
3430 &pre, sizeof( pre ) );
3431 HASH_Update( &HASHcontext,
3432 syntax->ssyn_oid, slen );
3433 HASH_Update( &HASHcontext,
3434 mr->smr_oid, mlen );
3435 HASH_Update( &HASHcontext,
3436 value.bv_val, klen );
3437 HASH_Final( HASHdigest, &HASHcontext );
3439 free( value.bv_val );
3440 ber_dupbv( &keys[nkeys++], &digest );
3443 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3445 pre = SLAP_INDEX_SUBSTR_PREFIX;
3446 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3448 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3449 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3453 ber_dupbv( &value, &sa->sa_any[i] );
3454 ldap_pvt_str2lower( value.bv_val );
3457 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3458 j += SLAP_INDEX_SUBSTR_STEP )
3460 HASH_Init( &HASHcontext );
3461 if( prefix != NULL && prefix->bv_len > 0 ) {
3462 HASH_Update( &HASHcontext,
3463 prefix->bv_val, prefix->bv_len );
3465 HASH_Update( &HASHcontext,
3466 &pre, sizeof( pre ) );
3467 HASH_Update( &HASHcontext,
3468 syntax->ssyn_oid, slen );
3469 HASH_Update( &HASHcontext,
3470 mr->smr_oid, mlen );
3471 HASH_Update( &HASHcontext,
3472 &value.bv_val[j], klen );
3473 HASH_Final( HASHdigest, &HASHcontext );
3475 ber_dupbv( &keys[nkeys++], &digest );
3478 free( value.bv_val );
3482 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3483 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3485 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3486 ber_dupbv( &value, &sa->sa_final );
3487 ldap_pvt_str2lower( value.bv_val );
3489 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3490 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3492 HASH_Init( &HASHcontext );
3493 if( prefix != NULL && prefix->bv_len > 0 ) {
3494 HASH_Update( &HASHcontext,
3495 prefix->bv_val, prefix->bv_len );
3497 HASH_Update( &HASHcontext,
3498 &pre, sizeof( pre ) );
3499 HASH_Update( &HASHcontext,
3500 syntax->ssyn_oid, slen );
3501 HASH_Update( &HASHcontext,
3502 mr->smr_oid, mlen );
3503 HASH_Update( &HASHcontext,
3504 &value.bv_val[value.bv_len-klen], klen );
3505 HASH_Final( HASHdigest, &HASHcontext );
3507 free( value.bv_val );
3508 ber_dupbv( &keys[nkeys++], &digest );
3512 keys[nkeys].bv_val = NULL;
3519 return LDAP_SUCCESS;
3525 numericStringValidate(
3531 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
3533 for(i=0; i < in->bv_len; i++) {
3534 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3535 return LDAP_INVALID_SYNTAX;
3539 return LDAP_SUCCESS;
3542 #ifndef SLAP_NVALUES
3545 xnumericStringNormalize(
3548 struct berval *normalized )
3550 /* removal all spaces */
3553 assert( val->bv_len );
3555 normalized->bv_val = ch_malloc( val->bv_len + 1 );
3558 q = normalized->bv_val;
3561 if ( ASCII_SPACE( *p ) ) {
3562 /* Ignore whitespace */
3569 /* we should have copied no more then is in val */
3570 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3572 /* null terminate */
3575 normalized->bv_len = q - normalized->bv_val;
3577 if( normalized->bv_len == 0 ) {
3578 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
3579 normalized->bv_val[0] = ' ';
3580 normalized->bv_val[1] = '\0';
3581 normalized->bv_len = 1;
3584 return LDAP_SUCCESS;
3588 objectIdentifierFirstComponentMatch(
3593 struct berval *value,
3594 void *assertedValue )
3596 int rc = LDAP_SUCCESS;
3598 struct berval *asserted = (struct berval *) assertedValue;
3602 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3603 return LDAP_INVALID_SYNTAX;
3606 /* trim leading white space */
3607 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3611 /* grab next word */
3612 oid.bv_val = &value->bv_val[i];
3613 j = value->bv_len - i;
3614 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
3619 /* insert attributeTypes, objectclass check here */
3620 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3621 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3624 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3625 MatchingRule *asserted_mr = mr_bvfind( asserted );
3626 MatchingRule *stored_mr = mr_bvfind( &oid );
3628 if( asserted_mr == NULL ) {
3629 rc = SLAPD_COMPARE_UNDEFINED;
3631 match = asserted_mr != stored_mr;
3634 } else if ( !strcmp( syntax->ssyn_oid,
3635 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3637 AttributeType *asserted_at = at_bvfind( asserted );
3638 AttributeType *stored_at = at_bvfind( &oid );
3640 if( asserted_at == NULL ) {
3641 rc = SLAPD_COMPARE_UNDEFINED;
3643 match = asserted_at != stored_at;
3646 } else if ( !strcmp( syntax->ssyn_oid,
3647 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3649 ObjectClass *asserted_oc = oc_bvfind( asserted );
3650 ObjectClass *stored_oc = oc_bvfind( &oid );
3652 if( asserted_oc == NULL ) {
3653 rc = SLAPD_COMPARE_UNDEFINED;
3655 match = asserted_oc != stored_oc;
3661 LDAP_LOG( CONFIG, ENTRY,
3662 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
3663 match, value->bv_val, asserted->bv_val );
3665 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3666 "%d\n\t\"%s\"\n\t\"%s\"\n",
3667 match, value->bv_val, asserted->bv_val );
3670 if( rc == LDAP_SUCCESS ) *matchp = match;
3682 struct berval *value,
3683 void *assertedValue )
3685 long lValue, lAssertedValue;
3687 /* safe to assume integers are NUL terminated? */
3688 lValue = strtol(value->bv_val, NULL, 10);
3689 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
3690 return LDAP_CONSTRAINT_VIOLATION;
3693 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3694 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
3695 && errno == ERANGE )
3697 return LDAP_CONSTRAINT_VIOLATION;
3700 *matchp = (lValue & lAssertedValue) ? 0 : 1;
3701 return LDAP_SUCCESS;
3710 struct berval *value,
3711 void *assertedValue )
3713 long lValue, lAssertedValue;
3715 /* safe to assume integers are NUL terminated? */
3716 lValue = strtol(value->bv_val, NULL, 10);
3717 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
3718 return LDAP_CONSTRAINT_VIOLATION;
3721 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3722 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
3723 && errno == ERANGE )
3725 return LDAP_CONSTRAINT_VIOLATION;
3728 *matchp = (lValue | lAssertedValue) ? 0 : -1;
3729 return LDAP_SUCCESS;
3732 #ifndef SLAP_NVALUES
3735 #include <openssl/x509.h>
3736 #include <openssl/err.h>
3739 * Next function returns a string representation of a ASN1_INTEGER.
3740 * It works for unlimited lengths.
3743 static struct berval *
3744 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3748 static char digit[] = "0123456789";
3750 /* We work backwards, make it fill from the end of buf */
3751 p = buf + sizeof(buf) - 1;
3754 if ( a == NULL || a->length == 0 ) {
3762 /* We want to preserve the original */
3763 copy = ch_malloc(n*sizeof(unsigned int));
3764 for (i = 0; i<n; i++) {
3765 copy[i] = a->data[i];
3769 * base indicates the index of the most significant
3770 * byte that might be nonzero. When it goes off the
3771 * end, we now there is nothing left to do.
3777 for (i = base; i<n; i++ ) {
3778 copy[i] += carry*256;
3779 carry = copy[i] % 10;
3784 * Way too large, we need to leave
3785 * room for sign if negative
3790 *--p = digit[carry];
3792 if (copy[base] == 0) base++;
3797 if ( a->type == V_ASN1_NEG_INTEGER ) {
3801 return ber_str2bv( p, 0, 1, bv );
3805 * Given a certificate in DER format, extract the corresponding
3806 * assertion value for certificateExactMatch
3809 certificateExactConvert(
3811 struct berval * out )
3814 unsigned char *p = in->bv_val;
3815 struct berval serial;
3816 struct berval issuer_dn;
3818 xcert = d2i_X509(NULL, &p, in->bv_len);
3821 LDAP_LOG( CONFIG, ENTRY,
3822 "certificateExactConvert: error parsing cert: %s\n",
3823 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3825 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3826 "error parsing cert: %s\n",
3827 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3829 return LDAP_INVALID_SYNTAX;
3832 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3834 return LDAP_INVALID_SYNTAX;
3836 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
3840 ber_memfree(serial.bv_val);
3841 return LDAP_INVALID_SYNTAX;
3846 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3847 out->bv_val = ch_malloc(out->bv_len);
3849 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3851 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3853 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3854 p += issuer_dn.bv_len;
3858 LDAP_LOG( CONFIG, ARGS,
3859 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
3861 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3863 out->bv_val, NULL, NULL );
3866 ber_memfree(serial.bv_val);
3867 ber_memfree(issuer_dn.bv_val);
3869 return LDAP_SUCCESS;
3873 serial_and_issuer_parse(
3874 struct berval *assertion,
3875 struct berval *serial,
3876 struct berval *issuer_dn
3884 begin = assertion->bv_val;
3885 end = assertion->bv_val+assertion->bv_len-1;
3886 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
3887 if ( p > end ) return LDAP_INVALID_SYNTAX;
3889 /* p now points at the $ sign, now use
3890 * begin and end to delimit the serial number
3892 while (ASCII_SPACE(*begin)) begin++;
3894 while (ASCII_SPACE(*end)) end--;
3896 if( end <= begin ) return LDAP_INVALID_SYNTAX;
3898 bv.bv_len = end-begin+1;
3900 ber_dupbv(serial, &bv);
3902 /* now extract the issuer, remember p was at the dollar sign */
3904 end = assertion->bv_val+assertion->bv_len-1;
3905 while (ASCII_SPACE(*begin)) begin++;
3906 /* should we trim spaces at the end too? is it safe always? no, no */
3908 if( end <= begin ) return LDAP_INVALID_SYNTAX;
3911 bv.bv_len = end-begin+1;
3914 dnNormalize2( NULL, &bv, issuer_dn );
3917 return LDAP_SUCCESS;
3921 certificateExactMatch(
3926 struct berval *value,
3927 void *assertedValue )
3930 unsigned char *p = value->bv_val;
3931 struct berval serial;
3932 struct berval issuer_dn;
3933 struct berval asserted_serial;
3934 struct berval asserted_issuer_dn;
3937 xcert = d2i_X509(NULL, &p, value->bv_len);
3940 LDAP_LOG( CONFIG, ENTRY,
3941 "certificateExactMatch: error parsing cert: %s\n",
3942 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3944 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3945 "error parsing cert: %s\n",
3946 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3948 return LDAP_INVALID_SYNTAX;
3951 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3952 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
3956 serial_and_issuer_parse(assertedValue,
3957 &asserted_serial, &asserted_issuer_dn);
3962 slap_schema.si_syn_integer,
3963 slap_schema.si_mr_integerMatch,
3966 if ( ret == LDAP_SUCCESS ) {
3967 if ( *matchp == 0 ) {
3968 /* We need to normalize everything for dnMatch */
3972 slap_schema.si_syn_distinguishedName,
3973 slap_schema.si_mr_distinguishedNameMatch,
3975 &asserted_issuer_dn);
3980 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
3981 "%d\n\t\"%s $ %s\"\n",
3982 *matchp, serial.bv_val, issuer_dn.bv_val );
3983 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
3984 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3987 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3988 "%d\n\t\"%s $ %s\"\n",
3989 *matchp, serial.bv_val, issuer_dn.bv_val );
3990 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3991 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3995 ber_memfree(serial.bv_val);
3996 ber_memfree(issuer_dn.bv_val);
3997 ber_memfree(asserted_serial.bv_val);
3998 ber_memfree(asserted_issuer_dn.bv_val);
4004 * Index generation function
4005 * We just index the serials, in most scenarios the issuer DN is one of
4006 * a very small set of values.
4008 static int certificateExactIndexer(
4013 struct berval *prefix,
4021 struct berval serial;
4023 /* we should have at least one value at this point */
4024 assert( values != NULL && values[0].bv_val != NULL );
4026 for( i=0; values[i].bv_val != NULL; i++ ) {
4027 /* empty -- just count them */
4030 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
4032 for( i=0; values[i].bv_val != NULL; i++ ) {
4033 p = values[i].bv_val;
4034 xcert = d2i_X509(NULL, &p, values[i].bv_len);
4037 LDAP_LOG( CONFIG, ENTRY,
4038 "certificateExactIndexer: error parsing cert: %s\n",
4039 ERR_error_string(ERR_get_error(),NULL), 0, 0);
4041 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
4042 "error parsing cert: %s\n",
4043 ERR_error_string(ERR_get_error(),NULL),
4046 /* Do we leak keys on error? */
4047 return LDAP_INVALID_SYNTAX;
4050 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
4052 xintegerNormalize( slap_schema.si_syn_integer,
4053 &serial, &keys[i] );
4054 ber_memfree(serial.bv_val);
4056 LDAP_LOG( CONFIG, ENTRY,
4057 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
4059 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
4066 keys[i].bv_val = NULL;
4068 return LDAP_SUCCESS;
4071 /* Index generation function */
4072 /* We think this is always called with a value in matching rule syntax */
4073 static int certificateExactFilter(
4078 struct berval *prefix,
4079 void * assertedValue,
4083 struct berval asserted_serial;
4086 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
4087 if( ret != LDAP_SUCCESS ) return ret;
4089 keys = ch_malloc( sizeof( struct berval ) * 2 );
4090 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
4091 keys[1].bv_val = NULL;
4094 ber_memfree(asserted_serial.bv_val);
4095 return LDAP_SUCCESS;
4101 check_time_syntax (struct berval *val,
4105 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
4106 static int mdays[2][12] = {
4107 /* non-leap years */
4108 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
4110 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
4113 int part, c, tzoffset, leapyear = 0 ;
4115 if( val->bv_len == 0 ) {
4116 return LDAP_INVALID_SYNTAX;
4119 p = (char *)val->bv_val;
4120 e = p + val->bv_len;
4122 /* Ignore initial whitespace */
4123 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4127 if (e - p < 13 - (2 * start)) {
4128 return LDAP_INVALID_SYNTAX;
4131 for (part = 0; part < 9; part++) {
4135 for (part = start; part < 7; part++) {
4137 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
4144 return LDAP_INVALID_SYNTAX;
4146 if (c < 0 || c > 9) {
4147 return LDAP_INVALID_SYNTAX;
4153 return LDAP_INVALID_SYNTAX;
4155 if (c < 0 || c > 9) {
4156 return LDAP_INVALID_SYNTAX;
4161 if (part == 2 || part == 3) {
4164 if (parts[part] < 0) {
4165 return LDAP_INVALID_SYNTAX;
4167 if (parts[part] > ceiling[part]) {
4168 return LDAP_INVALID_SYNTAX;
4172 /* leapyear check for the Gregorian calendar (year>1581) */
4173 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
4174 ((parts[0] % 4 == 0) && (parts[1] == 0)))
4179 if (parts[3] > mdays[leapyear][parts[2]]) {
4180 return LDAP_INVALID_SYNTAX;
4185 tzoffset = 0; /* UTC */
4186 } else if (c != '+' && c != '-') {
4187 return LDAP_INVALID_SYNTAX;
4191 } else /* c == '+' */ {
4196 return LDAP_INVALID_SYNTAX;
4199 for (part = 7; part < 9; part++) {
4201 if (c < 0 || c > 9) {
4202 return LDAP_INVALID_SYNTAX;
4207 if (c < 0 || c > 9) {
4208 return LDAP_INVALID_SYNTAX;
4212 if (parts[part] < 0 || parts[part] > ceiling[part]) {
4213 return LDAP_INVALID_SYNTAX;
4218 /* Ignore trailing whitespace */
4219 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4223 return LDAP_INVALID_SYNTAX;
4226 switch ( tzoffset ) {
4227 case -1: /* negativ offset to UTC, ie west of Greenwich */
4228 parts[4] += parts[7];
4229 parts[5] += parts[8];
4230 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4234 c = mdays[leapyear][parts[2]];
4236 if (parts[part] > c) {
4237 parts[part] -= c + 1;
4242 case 1: /* positive offset to UTC, ie east of Greenwich */
4243 parts[4] -= parts[7];
4244 parts[5] -= parts[8];
4245 for (part = 6; --part > 0; ) {
4249 /* first arg to % needs to be non negativ */
4250 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4252 if (parts[part] < 0) {
4253 parts[part] += c + 1;
4258 case 0: /* already UTC */
4262 return LDAP_SUCCESS;
4265 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4270 struct berval *normalized )
4274 rc = check_time_syntax(val, 1, parts);
4275 if (rc != LDAP_SUCCESS) {
4279 normalized->bv_val = ch_malloc( 14 );
4280 if ( normalized->bv_val == NULL ) {
4281 return LBER_ERROR_MEMORY;
4284 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4285 parts[1], parts[2] + 1, parts[3] + 1,
4286 parts[4], parts[5], parts[6] );
4287 normalized->bv_len = 13;
4289 return LDAP_SUCCESS;
4293 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4301 return check_time_syntax(in, 1, parts);
4306 generalizedTimeValidate(
4312 return check_time_syntax(in, 0, parts);
4315 #ifndef SLAP_NVALUES
4318 xgeneralizedTimeNormalize(
4321 struct berval *normalized )
4325 rc = check_time_syntax(val, 0, parts);
4326 if (rc != LDAP_SUCCESS) {
4330 normalized->bv_val = ch_malloc( 16 );
4331 if ( normalized->bv_val == NULL ) {
4332 return LBER_ERROR_MEMORY;
4335 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4336 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4337 parts[4], parts[5], parts[6] );
4338 normalized->bv_len = 15;
4340 return LDAP_SUCCESS;
4345 nisNetgroupTripleValidate(
4347 struct berval *val )
4352 if ( val->bv_len == 0 ) {
4353 return LDAP_INVALID_SYNTAX;
4356 p = (char *)val->bv_val;
4357 e = p + val->bv_len;
4359 if ( *p != '(' /*')'*/ ) {
4360 return LDAP_INVALID_SYNTAX;
4363 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4367 return LDAP_INVALID_SYNTAX;
4370 } else if ( !AD_CHAR( *p ) ) {
4371 return LDAP_INVALID_SYNTAX;
4375 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4376 return LDAP_INVALID_SYNTAX;
4382 return LDAP_INVALID_SYNTAX;
4385 return LDAP_SUCCESS;
4389 bootParameterValidate(
4391 struct berval *val )
4395 if ( val->bv_len == 0 ) {
4396 return LDAP_INVALID_SYNTAX;
4399 p = (char *)val->bv_val;
4400 e = p + val->bv_len;
4403 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4404 if ( !AD_CHAR( *p ) ) {
4405 return LDAP_INVALID_SYNTAX;
4410 return LDAP_INVALID_SYNTAX;
4414 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4415 if ( !AD_CHAR( *p ) ) {
4416 return LDAP_INVALID_SYNTAX;
4421 return LDAP_INVALID_SYNTAX;
4425 for ( p++; p < e; p++ ) {
4426 if ( !SLAP_PRINTABLE( *p ) ) {
4427 return LDAP_INVALID_SYNTAX;
4431 return LDAP_SUCCESS;
4434 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4435 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4437 static slap_syntax_defs_rec syntax_defs[] = {
4438 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4439 X_BINARY X_NOT_H_R ")",
4440 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4441 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4442 0, NULL, NULL, NULL},
4443 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4444 0, NULL, NULL, NULL},
4445 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4447 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4448 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4450 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4451 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4452 0, bitStringValidate, NULL, NULL },
4453 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4454 0, booleanValidate, NULL, NULL},
4455 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4456 X_BINARY X_NOT_H_R ")",
4457 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4458 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4459 X_BINARY X_NOT_H_R ")",
4460 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4461 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4462 X_BINARY X_NOT_H_R ")",
4463 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4464 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4465 0, countryStringValidate, xIA5StringNormalize, NULL},
4466 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4467 0, dnValidate, dnNormalize2, dnPretty2},
4468 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4469 0, NULL, NULL, NULL},
4470 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4471 0, NULL, NULL, NULL},
4472 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4473 0, UTF8StringValidate, xUTF8StringNormalize, NULL},
4474 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4475 0, NULL, NULL, NULL},
4476 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4477 0, NULL, NULL, NULL},
4478 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4479 0, NULL, NULL, NULL},
4480 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4481 0, NULL, NULL, NULL},
4482 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4483 0, NULL, NULL, NULL},
4484 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4485 0, printablesStringValidate, xtelephoneNumberNormalize, NULL},
4486 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4487 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4488 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4489 0, generalizedTimeValidate, xgeneralizedTimeNormalize, NULL},
4490 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4491 0, NULL, NULL, NULL},
4492 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4493 0, IA5StringValidate, xIA5StringNormalize, NULL},
4494 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4495 0, integerValidate, xintegerNormalize, NULL},
4496 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4497 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4498 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4499 0, NULL, NULL, NULL},
4500 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4501 0, NULL, NULL, NULL},
4502 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4503 0, NULL, NULL, NULL},
4504 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4505 0, NULL, NULL, NULL},
4506 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4507 0, NULL, NULL, NULL},
4508 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4509 0, nameUIDValidate, xnameUIDNormalize, NULL},
4510 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4511 0, NULL, NULL, NULL},
4512 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4513 0, numericStringValidate, xnumericStringNormalize, NULL},
4514 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4515 0, NULL, NULL, NULL},
4516 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4517 0, oidValidate, NULL, NULL},
4518 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4519 0, IA5StringValidate, xIA5StringNormalize, NULL},
4520 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4521 0, blobValidate, NULL, NULL},
4522 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4523 0, UTF8StringValidate, xUTF8StringNormalize, NULL},
4524 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4525 0, NULL, NULL, NULL},
4526 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4527 0, NULL, NULL, NULL},
4528 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4529 0, printableStringValidate, xIA5StringNormalize, NULL},
4530 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4531 X_BINARY X_NOT_H_R ")",
4532 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4533 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4534 X_BINARY X_NOT_H_R ")",
4535 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4536 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4537 0, printableStringValidate, xtelephoneNumberNormalize, NULL},
4538 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4539 0, NULL, NULL, NULL},
4540 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4541 0, printablesStringValidate, xIA5StringNormalize, NULL},
4542 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4543 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4544 0, utcTimeValidate, xutcTimeNormalize, NULL},
4546 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4547 0, NULL, NULL, NULL},
4548 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4549 0, NULL, NULL, NULL},
4550 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4551 0, NULL, NULL, NULL},
4552 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4553 0, NULL, NULL, NULL},
4554 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4555 0, NULL, NULL, NULL},
4557 /* RFC 2307 NIS Syntaxes */
4558 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4559 0, nisNetgroupTripleValidate, NULL, NULL},
4560 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4561 0, bootParameterValidate, NULL, NULL},
4565 /* These OIDs are not published yet, but will be in the next
4566 * I-D for PKIX LDAPv3 schema as have been advanced by David
4567 * Chadwick in private mail.
4569 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4570 0, UTF8StringValidate, NULL, NULL},
4573 /* OpenLDAP Experimental Syntaxes */
4574 #ifdef SLAPD_ACI_ENABLED
4575 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4577 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4581 #ifdef SLAPD_AUTHPASSWD
4582 /* needs updating */
4583 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4584 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4587 /* OpenLDAP Void Syntax */
4588 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4589 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4590 {NULL, 0, NULL, NULL, NULL}
4594 char *certificateExactMatchSyntaxes[] = {
4595 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4599 char *directoryStringSyntaxes[] = {
4600 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4603 char *integerFirstComponentMatchSyntaxes[] = {
4604 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4605 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
4608 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4609 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4610 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4611 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
4612 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4613 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4614 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4615 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4616 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4621 * Other matching rules in X.520 that we do not use (yet):
4623 * 2.5.13.9 numericStringOrderingMatch
4624 * 2.5.13.19 octetStringSubstringsMatch
4625 * 2.5.13.25 uTCTimeMatch
4626 * 2.5.13.26 uTCTimeOrderingMatch
4627 * 2.5.13.31 directoryStringFirstComponentMatch
4628 * 2.5.13.32 wordMatch
4629 * 2.5.13.33 keywordMatch
4630 * 2.5.13.35 certificateMatch
4631 * 2.5.13.36 certificatePairExactMatch
4632 * 2.5.13.37 certificatePairMatch
4633 * 2.5.13.38 certificateListExactMatch
4634 * 2.5.13.39 certificateListMatch
4635 * 2.5.13.40 algorithmIdentifierMatch
4636 * 2.5.13.41 storedPrefixMatch
4637 * 2.5.13.42 attributeCertificateMatch
4638 * 2.5.13.43 readerAndKeyIDMatch
4639 * 2.5.13.44 attributeIntegrityMatch
4641 static slap_mrule_defs_rec mrule_defs[] = {
4643 * EQUALITY matching rules must be listed after associated APPROX
4644 * matching rules. So, we list all APPROX matching rules first.
4646 #ifndef SLAP_NVALUES
4647 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4649 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4650 NULL, NULL, directoryStringApproxMatch,
4651 directoryStringApproxIndexer, directoryStringApproxFilter,
4654 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4656 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4657 NULL, NULL, IA5StringApproxMatch,
4658 IA5StringApproxIndexer, IA5StringApproxFilter,
4663 * Other matching rules
4666 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4667 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4668 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4670 objectIdentifierNormalize, objectIdentifierMatch,
4671 objectIdentifierIndexer, objectIdentifierFilter,
4674 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4675 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4676 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4678 distinguishedNameNormalize, distinguishedNameMatch,
4679 distinguishedNameIndexer, distinguishedNameFilter,
4682 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4683 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4684 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4685 directoryStringSyntaxes,
4687 caseIgnoreNormalize, caseIgnoreMatch,
4688 caseIgnoreIndexer, caseIgnoreFilter,
4689 directoryStringApproxMatchOID },
4691 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4692 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4693 SLAP_MR_ORDERING, directoryStringSyntaxes,
4694 NULL, caseIgnoreNormalize, caseIgnoreOrderingMatch,
4697 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4698 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4699 SLAP_MR_SUBSTR, NULL,
4701 caseIgnoreSubstringsMatch,
4702 caseIgnoreSubstringsIndexer, caseIgnoreSubstringsFilter,
4705 {"( 2.5.13.5 NAME 'caseExactMatch' "
4706 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4707 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4709 caseExactNormalize, caseExactMatch,
4710 caseExactIndexer, caseExactFilter,
4711 directoryStringApproxMatchOID },
4713 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4714 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4715 SLAP_MR_ORDERING, directoryStringSyntaxes,
4716 NULL, caseExactNormalize, caseExactOrderingMatch,
4719 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4720 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4721 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4723 NULL, caseExactSubstringsMatch,
4724 caseExactSubstringsIndexer, caseExactSubstringsFilter,
4727 {"( 2.5.13.8 NAME 'numericStringMatch' "
4728 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4729 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4731 numericStringNormalize, numericStringMatch,
4732 numericStringIndexer, numericStringFilter,
4735 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4736 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4737 SLAP_MR_SUBSTR, NULL,
4739 NULL, numericStringSubstringsMatch,
4740 numericStringSubstringsIndexer, numericStringSubstringsFilter,
4743 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4745 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4746 NULL, NULL, NULL, NULL, NULL, NULL},
4748 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4749 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4750 SLAP_MR_SUBSTR, NULL,
4751 NULL, NULL, NULL, NULL, NULL, NULL},
4753 {"( 2.5.13.13 NAME 'booleanMatch' "
4754 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4755 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4756 NULL, NULL, booleanMatch, NULL, NULL, NULL},
4758 {"( 2.5.13.14 NAME 'integerMatch' "
4759 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4760 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4762 integerNormalize, integerMatch,
4763 integerIndexer, integerFilter,
4766 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4767 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4768 SLAP_MR_ORDERING, NULL, NULL,
4769 integerNormalize, integerOrderingMatch,
4770 integerIndexer, integerFilter,
4773 {"( 2.5.13.16 NAME 'bitStringMatch' "
4774 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4775 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4777 bitStringNormalize, bitStringMatch,
4778 bitStringIndexer, bitStringFilter,
4781 {"( 2.5.13.17 NAME 'octetStringMatch' "
4782 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4783 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4785 octetStringMatch, octetStringIndexer, octetStringFilter,
4788 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4789 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4790 SLAP_MR_ORDERING, NULL,
4792 octetStringOrderingMatch, NULL, NULL,
4795 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4796 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4797 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4799 telephoneNumberNormalize, telephoneNumberMatch,
4800 telephoneNumberIndexer, telephoneNumberFilter,
4803 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4804 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4805 SLAP_MR_SUBSTR, NULL,
4806 NULL, NULL, telephoneNumberSubstringsMatch,
4807 telephoneNumberSubstringsIndexer, telephoneNumberSubstringsFilter,
4810 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4811 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4812 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4817 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4818 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4819 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4821 uniqueMemberNormalize, uniqueMemberMatch,
4825 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4826 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4827 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4828 NULL, NULL, NULL, NULL, NULL, NULL},
4830 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4831 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4832 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4834 generalizedTimeNormalize, generalizedTimeMatch,
4838 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4839 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4840 SLAP_MR_ORDERING, NULL,
4842 generalizedTimeOrderingMatch, generalizedTimeOrderingMatch,
4846 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4847 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4848 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
4850 integerFirstComponentNormalize, integerMatch,
4854 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4855 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4856 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4857 objectIdentifierFirstComponentMatchSyntaxes,
4859 objectIdentifierFirstComponentNormalize, objectIdentifierMatch,
4863 #ifndef SLAP_NVALUES
4865 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4866 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4867 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4868 certificateExactConvert, NULL,
4869 certificateExactMatch,
4870 certificateExactIndexer, certificateExactFilter,
4875 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4876 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4877 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4879 caseExactIA5Normalize, caseExactIA5Match,
4880 caseExactIA5Indexer, caseExactIA5Filter,
4881 IA5StringApproxMatchOID },
4883 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4884 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4885 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4887 NULL, caseIgnoreIA5Match,
4888 caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4889 IA5StringApproxMatchOID },
4891 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4892 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4893 SLAP_MR_SUBSTR, NULL,
4895 NULL, caseIgnoreIA5SubstringsMatch,
4896 caseIgnoreIA5SubstringsIndexer, caseIgnoreIA5SubstringsFilter,
4899 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4900 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4901 SLAP_MR_SUBSTR, NULL,
4903 NULL, caseExactIA5SubstringsMatch,
4904 caseExactIA5SubstringsIndexer, caseExactIA5SubstringsFilter,
4907 #ifdef SLAPD_AUTHPASSWD
4908 /* needs updating */
4909 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4910 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4911 SLAP_MR_EQUALITY, NULL,
4913 authPasswordMatch, NULL, NULL,
4917 #ifdef SLAPD_ACI_ENABLED
4918 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4919 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4920 SLAP_MR_EQUALITY, NULL,
4922 OpenLDAPaciMatch, NULL, NULL,
4926 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4927 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4930 NULL, integerBitAndMatch, NULL, NULL,
4933 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4934 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4937 NULL, integerBitOrMatch, NULL, NULL,
4940 {NULL, SLAP_MR_NONE, NULL,
4941 NULL, NULL, NULL, NULL, NULL,
4946 slap_schema_init( void )
4951 /* we should only be called once (from main) */
4952 assert( schema_init_done == 0 );
4954 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4955 res = register_syntax( &syntax_defs[i] );
4958 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4959 syntax_defs[i].sd_desc );
4964 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4965 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4966 mrule_defs[i].mrd_compat_syntaxes == NULL )
4969 "slap_schema_init: Ignoring unusable matching rule %s\n",
4970 mrule_defs[i].mrd_desc );
4974 res = register_matching_rule( &mrule_defs[i] );
4978 "slap_schema_init: Error registering matching rule %s\n",
4979 mrule_defs[i].mrd_desc );
4984 res = slap_schema_load();
4985 schema_init_done = 1;
4990 schema_destroy( void )