1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
9 LDAP/X.500 string syntax / matching rules have a few oddities. This
10 comment attempts to detail how slapd(8) treats them.
13 StringSyntax X.500 LDAP Matching
14 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
15 PrintableString subset subset i/e + ignore insignificant spaces
16 NumericString subset subset ignore all spaces
17 IA5String ASCII ASCII i/e + ignore insignificant spaces
18 TeletexString T.61 T.61 i/e + ignore insignificant spaces
20 TelephoneNumber subset subset i + ignore all spaces and "-"
22 See draft-ietf-ldapbis-strpro for details (once published).
26 In X.500(93), a directory string can be either a PrintableString,
27 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
28 In later versions, more CHOICEs were added. In all cases the string
31 In LDPAv3, a directory string is a UTF-8 encoded UCS string.
33 For matching, there are both case ignore and exact rules. Both
34 also require that "insignificant" spaces be ignored.
35 spaces before the first non-space are ignored;
36 spaces after the last non-space are ignored;
37 spaces after a space are ignored.
38 Note: by these rules (and as clarified in X.520), a string of only
39 spaces is to be treated as if held one space, not empty (which would
43 In ASN.1, numeric string is just a string of digits and spaces and
44 could be empty. However, in X.500, all attribute values of numeric
45 string carry a non-empty constraint. For example:
47 internationalISDNNumber ATTRIBUTE ::= {
48 WITH SYNTAX InternationalISDNNumber
49 EQUALITY MATCHING RULE numericStringMatch
50 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
51 ID id-at-internationalISDNNumber }
52 InternationalISDNNumber ::= NumericString (SIZE(1..ub-international-isdn-number))
54 Unfornately, some assertion values are don't carry the same constraint
55 (but its unclear how such an assertion could ever be true). In LDAP,
56 there is one syntax (numericString) not two (numericString with constraint,
57 numericString without constraint). This should be treated as numericString
58 with non-empty constraint. Note that while someone may have no
59 ISDN number, there are no ISDN numbers which are zero length.
61 In matching, spaces are ignored.
64 In ASN.1, Printable string is just a string of printable characters and
65 can be empty. In X.500, semantics much like NumericString (see serialNumber
66 for a like example) excepting uses insignificant space handling instead of
70 Basically same as PrintableString. There are no examples in X.500, but
71 same logic applies. So we require them to be non-empty as well.
83 #include <ac/string.h>
84 #include <ac/socket.h>
90 #include "ldap_utf8.h"
92 #include "lutil_hash.h"
93 #define HASH_BYTES LUTIL_HASH_BYTES
94 #define HASH_CONTEXT lutil_HASH_CTX
95 #define HASH_Init(c) lutil_HASHInit(c)
96 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
97 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
99 /* recycled validatation routines */
100 #define berValidate blobValidate
102 /* unimplemented pretters */
103 #define integerPretty NULL
105 /* recycled matching routines */
106 #define bitStringMatch octetStringMatch
107 #define numericStringMatch caseIgnoreIA5Match
108 #define objectIdentifierMatch caseIgnoreIA5Match
109 #define telephoneNumberMatch caseIgnoreIA5Match
110 #define telephoneNumberSubstringsMatch caseIgnoreIA5SubstringsMatch
111 #define generalizedTimeMatch caseIgnoreIA5Match
112 #define generalizedTimeOrderingMatch caseIgnoreIA5Match
113 #define uniqueMemberMatch dnMatch
114 #define integerFirstComponentMatch integerMatch
116 /* approx matching rules */
117 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
118 #define directoryStringApproxMatch approxMatch
119 #define directoryStringApproxIndexer approxIndexer
120 #define directoryStringApproxFilter approxFilter
121 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
122 #define IA5StringApproxMatch approxMatch
123 #define IA5StringApproxIndexer approxIndexer
124 #define IA5StringApproxFilter approxFilter
126 /* ordering matching rules */
127 #define caseIgnoreOrderingMatch caseIgnoreMatch
128 #define caseExactOrderingMatch caseExactMatch
129 #define integerOrderingMatch integerMatch
131 /* unimplemented matching routines */
132 #define caseIgnoreListMatch NULL
133 #define caseIgnoreListSubstringsMatch NULL
134 #define protocolInformationMatch NULL
136 #ifdef SLAPD_ACI_ENABLED
137 #define OpenLDAPaciMatch NULL
139 #ifdef SLAPD_AUTHPASSWD
140 #define authPasswordMatch NULL
143 /* recycled indexing/filtering routines */
144 #define dnIndexer caseExactIgnoreIndexer
145 #define dnFilter caseExactIgnoreFilter
146 #define bitStringFilter octetStringFilter
147 #define bitStringIndexer octetStringIndexer
149 #define telephoneNumberIndexer caseIgnoreIA5Indexer
150 #define telephoneNumberFilter caseIgnoreIA5Filter
151 #define telephoneNumberSubstringsIndexer caseIgnoreIA5SubstringsIndexer
152 #define telephoneNumberSubstringsFilter caseIgnoreIA5SubstringsFilter
154 static MatchingRule *caseExactMatchingRule;
155 static MatchingRule *caseExactSubstringsMatchingRule;
156 static MatchingRule *integerFirstComponentMatchingRule;
158 static const struct MatchingRulePtr {
162 /* must match OIDs below */
163 { "2.5.13.5", &caseExactMatchingRule },
164 { "2.5.13.7", &caseExactSubstringsMatchingRule },
165 { "2.5.13.29", &integerFirstComponentMatchingRule }
169 static char *bvcasechr( struct berval *bv, unsigned char c, ber_len_t *len )
172 char lower = TOLOWER( c );
173 char upper = TOUPPER( c );
175 if( c == 0 ) return NULL;
177 for( i=0; i < bv->bv_len; i++ ) {
178 if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
180 return &bv->bv_val[i];
193 struct berval *value,
194 void *assertedValue )
196 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
199 match = memcmp( value->bv_val,
200 ((struct berval *) assertedValue)->bv_val,
208 /* Index generation function */
209 static int octetStringIndexer(
214 struct berval *prefix,
221 HASH_CONTEXT HASHcontext;
222 unsigned char HASHdigest[HASH_BYTES];
223 struct berval digest;
224 digest.bv_val = HASHdigest;
225 digest.bv_len = sizeof(HASHdigest);
227 for( i=0; values[i].bv_val != NULL; i++ ) {
228 /* just count them */
231 /* we should have at least one value at this point */
234 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
236 slen = syntax->ssyn_oidlen;
237 mlen = mr->smr_oidlen;
239 for( i=0; values[i].bv_val != NULL; i++ ) {
240 HASH_Init( &HASHcontext );
241 if( prefix != NULL && prefix->bv_len > 0 ) {
242 HASH_Update( &HASHcontext,
243 prefix->bv_val, prefix->bv_len );
245 HASH_Update( &HASHcontext,
246 syntax->ssyn_oid, slen );
247 HASH_Update( &HASHcontext,
249 HASH_Update( &HASHcontext,
250 values[i].bv_val, values[i].bv_len );
251 HASH_Final( HASHdigest, &HASHcontext );
253 ber_dupbv( &keys[i], &digest );
256 keys[i].bv_val = NULL;
263 /* Index generation function */
264 static int octetStringFilter(
269 struct berval *prefix,
275 HASH_CONTEXT HASHcontext;
276 unsigned char HASHdigest[HASH_BYTES];
277 struct berval *value = (struct berval *) assertValue;
278 struct berval digest;
279 digest.bv_val = HASHdigest;
280 digest.bv_len = sizeof(HASHdigest);
282 slen = syntax->ssyn_oidlen;
283 mlen = mr->smr_oidlen;
285 keys = ch_malloc( sizeof( struct berval ) * 2 );
287 HASH_Init( &HASHcontext );
288 if( prefix != NULL && prefix->bv_len > 0 ) {
289 HASH_Update( &HASHcontext,
290 prefix->bv_val, prefix->bv_len );
292 HASH_Update( &HASHcontext,
293 syntax->ssyn_oid, slen );
294 HASH_Update( &HASHcontext,
296 HASH_Update( &HASHcontext,
297 value->bv_val, value->bv_len );
298 HASH_Final( HASHdigest, &HASHcontext );
300 ber_dupbv( keys, &digest );
301 keys[1].bv_val = NULL;
313 /* any value allowed */
322 /* any value allowed */
333 /* very unforgiving validation, requires no normalization
334 * before simplistic matching
336 if( in->bv_len < 3 ) {
337 return LDAP_INVALID_SYNTAX;
341 * rfc 2252 section 6.3 Bit String
342 * bitstring = "'" *binary-digit "'"
343 * binary-digit = "0" / "1"
344 * example: '0101111101'B
347 if( in->bv_val[0] != '\'' ||
348 in->bv_val[in->bv_len-2] != '\'' ||
349 in->bv_val[in->bv_len-1] != 'B' )
351 return LDAP_INVALID_SYNTAX;
354 for( i=in->bv_len-3; i>0; i-- ) {
355 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
356 return LDAP_INVALID_SYNTAX;
367 struct berval *normalized )
370 * A normalized bitString is has no extaneous (leading) zero bits.
371 * That is, '00010'B is normalized to '10'B
372 * However, as a special case, '0'B requires no normalization.
376 /* start at the first bit */
379 /* Find the first non-zero bit */
380 while ( *p == '0' ) p++;
383 /* no non-zero bits */
384 ber_str2bv( "\'0\'B", sizeof("\'0\'B") - 1, 1, normalized );
388 normalized->bv_val = ch_malloc( val->bv_len + 1 );
390 normalized->bv_val[0] = '\'';
391 normalized->bv_len = 1;
393 for( ; *p != '\0'; p++ ) {
394 normalized->bv_val[normalized->bv_len++] = *p;
397 normalized->bv_val[normalized->bv_len] = '\0';
411 if( in->bv_len == 0 ) return LDAP_SUCCESS;
413 ber_dupbv( &dn, in );
414 if( !dn.bv_val ) return LDAP_OTHER;
416 if( dn.bv_val[dn.bv_len-1] == 'B'
417 && dn.bv_val[dn.bv_len-2] == '\'' )
419 /* assume presence of optional UID */
422 for(i=dn.bv_len-3; i>1; i--) {
423 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
427 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
428 ber_memfree( dn.bv_val );
429 return LDAP_INVALID_SYNTAX;
432 /* trim the UID to allow use of dnValidate */
433 dn.bv_val[i-1] = '\0';
437 rc = dnValidate( NULL, &dn );
439 ber_memfree( dn.bv_val );
447 struct berval *normalized )
452 ber_dupbv( &out, val );
453 if( out.bv_len != 0 ) {
454 struct berval uidin = { 0, NULL };
455 struct berval uidout = { 0, NULL };
457 if( out.bv_val[out.bv_len-1] == 'B'
458 && out.bv_val[out.bv_len-2] == '\'' )
460 /* assume presence of optional UID */
461 uidin.bv_val = strrchr( out.bv_val, '#' );
463 if( uidin.bv_val == NULL ) {
465 return LDAP_INVALID_SYNTAX;
468 uidin.bv_len = out.bv_len - (uidin.bv_val - out.bv_val);
469 out.bv_len -= uidin.bv_len--;
471 /* temporarily trim the UID */
472 *(uidin.bv_val++) = '\0';
474 rc = bitStringNormalize( syntax, &uidin, &uidout );
476 if( rc != LDAP_SUCCESS ) {
478 return LDAP_INVALID_SYNTAX;
482 #ifdef USE_DN_NORMALIZE
483 rc = dnNormalize2( NULL, &out, normalized );
485 rc = dnPretty2( NULL, &out, normalized );
488 if( rc != LDAP_SUCCESS ) {
490 free( uidout.bv_val );
491 return LDAP_INVALID_SYNTAX;
494 if( uidout.bv_len ) {
495 normalized->bv_val = ch_realloc( normalized->bv_val,
496 normalized->bv_len + uidout.bv_len + sizeof("#") );
498 /* insert the separator */
499 normalized->bv_val[normalized->bv_len++] = '#';
502 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
503 uidout.bv_val, uidout.bv_len );
504 normalized->bv_len += uidout.bv_len;
507 normalized->bv_val[normalized->bv_len] = '\0';
517 * Handling boolean syntax and matching is quite rigid.
518 * A more flexible approach would be to allow a variety
519 * of strings to be normalized and prettied into TRUE
527 /* very unforgiving validation, requires no normalization
528 * before simplistic matching
531 if( in->bv_len == 4 ) {
532 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
535 } else if( in->bv_len == 5 ) {
536 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
541 return LDAP_INVALID_SYNTAX;
550 struct berval *value,
551 void *assertedValue )
553 /* simplistic matching allowed by rigid validation */
554 struct berval *asserted = (struct berval *) assertedValue;
555 *matchp = value->bv_len != asserted->bv_len;
566 unsigned char *u = in->bv_val;
568 if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
570 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
571 /* get the length indicated by the first byte */
572 len = LDAP_UTF8_CHARLEN2( u, len );
574 /* very basic checks */
577 if( (u[5] & 0xC0) != 0x80 ) {
578 return LDAP_INVALID_SYNTAX;
581 if( (u[4] & 0xC0) != 0x80 ) {
582 return LDAP_INVALID_SYNTAX;
585 if( (u[3] & 0xC0) != 0x80 ) {
586 return LDAP_INVALID_SYNTAX;
589 if( (u[2] & 0xC0 )!= 0x80 ) {
590 return LDAP_INVALID_SYNTAX;
593 if( (u[1] & 0xC0) != 0x80 ) {
594 return LDAP_INVALID_SYNTAX;
597 /* CHARLEN already validated it */
600 return LDAP_INVALID_SYNTAX;
603 /* make sure len corresponds with the offset
604 to the next character */
605 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
608 if( count != 0 ) return LDAP_INVALID_SYNTAX;
617 struct berval *normalized )
622 /* validator should have refused an empty string */
623 assert( val->bv_len );
627 /* Ignore initial whitespace */
628 /* All space is ASCII. All ASCII is 1 byte */
629 for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
631 normalized->bv_len = val->bv_len - (p - val->bv_val);
633 if( !normalized->bv_len ) {
634 ber_mem2bv( " ", 1, 1, normalized );
638 ber_mem2bv( p, normalized->bv_len, 1, normalized );
639 e = normalized->bv_val + normalized->bv_len;
641 assert( normalized->bv_val );
643 p = q = normalized->bv_val;
648 if ( ASCII_SPACE( *p ) ) {
653 /* Ignore the extra whitespace */
654 while ( ASCII_SPACE( *p ) ) {
658 len = LDAP_UTF8_COPY(q,p);
664 assert( normalized->bv_val <= p );
665 assert( q+len <= p );
667 /* cannot start with a space */
668 assert( !ASCII_SPACE(normalized->bv_val[0]) );
671 * If the string ended in space, backup the pointer one
672 * position. One is enough because the above loop collapsed
673 * all whitespace to a single space.
681 /* cannot end with a space */
682 assert( !ASCII_SPACE( *q ) );
689 normalized->bv_len = q - normalized->bv_val;
694 /* Returns Unicode canonically normalized copy of a substring assertion
695 * Skipping attribute description */
696 static SubstringsAssertion *
697 UTF8SubstringsassertionNormalize(
698 SubstringsAssertion *sa,
701 SubstringsAssertion *nsa;
704 nsa = (SubstringsAssertion *)ch_calloc( 1, sizeof(SubstringsAssertion) );
709 if( sa->sa_initial.bv_val != NULL ) {
710 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
711 if( nsa->sa_initial.bv_val == NULL ) {
716 if( sa->sa_any != NULL ) {
717 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
720 nsa->sa_any = (struct berval *)ch_malloc( (i + 1) * sizeof(struct berval) );
721 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
722 UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
724 if( nsa->sa_any[i].bv_val == NULL ) {
728 nsa->sa_any[i].bv_val = NULL;
731 if( sa->sa_final.bv_val != NULL ) {
732 UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
733 if( nsa->sa_final.bv_val == NULL ) {
741 if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
742 if ( nsa->sa_any )ber_bvarray_free( nsa->sa_any );
743 if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
748 #ifndef SLAPD_APPROX_OLDSINGLESTRING
750 #if defined(SLAPD_APPROX_INITIALS)
751 #define SLAPD_APPROX_DELIMITER "._ "
752 #define SLAPD_APPROX_WORDLEN 2
754 #define SLAPD_APPROX_DELIMITER " "
755 #define SLAPD_APPROX_WORDLEN 1
764 struct berval *value,
765 void *assertedValue )
767 struct berval *nval, *assertv;
768 char *val, **values, **words, *c;
769 int i, count, len, nextchunk=0, nextavail=0;
771 /* Yes, this is necessary */
772 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
778 /* Yes, this is necessary */
779 assertv = UTF8bvnormalize( ((struct berval *)assertedValue), NULL, LDAP_UTF8_APPROX );
780 if( assertv == NULL ) {
786 /* Isolate how many words there are */
787 for ( c = nval->bv_val, count = 1; *c; c++ ) {
788 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
789 if ( c == NULL ) break;
794 /* Get a phonetic copy of each word */
795 words = (char **)ch_malloc( count * sizeof(char *) );
796 values = (char **)ch_malloc( count * sizeof(char *) );
797 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
799 values[i] = phonetic(c);
802 /* Work through the asserted value's words, to see if at least some
803 of the words are there, in the same order. */
805 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
806 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
811 #if defined(SLAPD_APPROX_INITIALS)
812 else if( len == 1 ) {
813 /* Single letter words need to at least match one word's initial */
814 for( i=nextavail; i<count; i++ )
815 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
822 /* Isolate the next word in the asserted value and phonetic it */
823 assertv->bv_val[nextchunk+len] = '\0';
824 val = phonetic( assertv->bv_val + nextchunk );
826 /* See if this phonetic chunk is in the remaining words of *value */
827 for( i=nextavail; i<count; i++ ){
828 if( !strcmp( val, values[i] ) ){
836 /* This chunk in the asserted value was NOT within the *value. */
842 /* Go on to the next word in the asserted value */
846 /* If some of the words were seen, call it a match */
847 if( nextavail > 0 ) {
855 ber_bvfree( assertv );
856 for( i=0; i<count; i++ ) {
857 ch_free( values[i] );
872 struct berval *prefix,
877 int i,j, len, wordcount, keycount=0;
878 struct berval *newkeys;
881 for( j=0; values[j].bv_val != NULL; j++ ) {
882 struct berval val = { 0, NULL };
883 /* Yes, this is necessary */
884 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
885 assert( val.bv_val != NULL );
887 /* Isolate how many words there are. There will be a key for each */
888 for( wordcount = 0, c = val.bv_val; *c; c++) {
889 len = strcspn(c, SLAPD_APPROX_DELIMITER);
890 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
892 if (*c == '\0') break;
896 /* Allocate/increase storage to account for new keys */
897 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
898 * sizeof(struct berval) );
899 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
900 if( keys ) ch_free( keys );
903 /* Get a phonetic copy of each word */
904 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
906 if( len < SLAPD_APPROX_WORDLEN ) continue;
907 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
912 ber_memfree( val.bv_val );
914 keys[keycount].bv_val = NULL;
926 struct berval *prefix,
935 /* Yes, this is necessary */
936 val = UTF8bvnormalize( ((struct berval *)assertValue), NULL, LDAP_UTF8_APPROX );
937 if( val == NULL || val->bv_val == NULL ) {
938 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
939 keys[0].bv_val = NULL;
945 /* Isolate how many words there are. There will be a key for each */
946 for( count = 0,c = val->bv_val; *c; c++) {
947 len = strcspn(c, SLAPD_APPROX_DELIMITER);
948 if( len >= SLAPD_APPROX_WORDLEN ) count++;
950 if (*c == '\0') break;
954 /* Allocate storage for new keys */
955 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
957 /* Get a phonetic copy of each word */
958 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
960 if( len < SLAPD_APPROX_WORDLEN ) continue;
961 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
967 keys[count].bv_val = NULL;
975 /* No other form of Approximate Matching is defined */
983 struct berval *value,
984 void *assertedValue )
986 char *vapprox, *avapprox;
989 /* Yes, this is necessary */
990 s = UTF8normalize( value, UTF8_NOCASEFOLD );
996 /* Yes, this is necessary */
997 t = UTF8normalize( ((struct berval *)assertedValue),
1002 return LDAP_SUCCESS;
1005 vapprox = phonetic( strip8bitChars( s ) );
1006 avapprox = phonetic( strip8bitChars( t ) );
1011 *matchp = strcmp( vapprox, avapprox );
1014 ch_free( avapprox );
1016 return LDAP_SUCCESS;
1025 struct berval *prefix,
1033 for( i=0; values[i].bv_val != NULL; i++ ) {
1034 /* empty - just count them */
1037 /* we should have at least one value at this point */
1040 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1042 /* Copy each value and run it through phonetic() */
1043 for( i=0; values[i].bv_val != NULL; i++ ) {
1044 /* Yes, this is necessary */
1045 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1047 /* strip 8-bit chars and run through phonetic() */
1048 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1051 keys[i].bv_val = NULL;
1054 return LDAP_SUCCESS;
1064 struct berval *prefix,
1071 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1073 /* Yes, this is necessary */
1074 s = UTF8normalize( ((struct berval *)assertValue),
1079 /* strip 8-bit chars and run through phonetic() */
1080 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1086 return LDAP_SUCCESS;
1097 struct berval *value,
1098 void *assertedValue )
1100 *matchp = UTF8bvnormcmp( value,
1101 (struct berval *) assertedValue,
1102 LDAP_UTF8_NOCASEFOLD );
1103 return LDAP_SUCCESS;
1107 caseExactIgnoreSubstringsMatch(
1112 struct berval *value,
1113 void *assertedValue )
1116 SubstringsAssertion *sub = NULL;
1117 struct berval left = { 0, NULL };
1123 casefold = ( mr != caseExactSubstringsMatchingRule )
1124 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1126 if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1132 sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1138 /* Add up asserted input length */
1139 if( sub->sa_initial.bv_val ) {
1140 inlen += sub->sa_initial.bv_len;
1143 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1144 inlen += sub->sa_any[i].bv_len;
1147 if( sub->sa_final.bv_val ) {
1148 inlen += sub->sa_final.bv_len;
1151 if( sub->sa_initial.bv_val ) {
1152 if( inlen > left.bv_len ) {
1157 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1158 sub->sa_initial.bv_len );
1164 left.bv_val += sub->sa_initial.bv_len;
1165 left.bv_len -= sub->sa_initial.bv_len;
1166 inlen -= sub->sa_initial.bv_len;
1169 if( sub->sa_final.bv_val ) {
1170 if( inlen > left.bv_len ) {
1175 match = memcmp( sub->sa_final.bv_val,
1176 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1177 sub->sa_final.bv_len );
1183 left.bv_len -= sub->sa_final.bv_len;
1184 inlen -= sub->sa_final.bv_len;
1188 for(i=0; sub->sa_any[i].bv_val; i++) {
1193 if( inlen > left.bv_len ) {
1194 /* not enough length */
1199 if( sub->sa_any[i].bv_len == 0 ) {
1203 p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1209 idx = p - left.bv_val;
1211 if( idx >= left.bv_len ) {
1212 /* this shouldn't happen */
1214 if ( sub->sa_final.bv_val )
1215 ch_free( sub->sa_final.bv_val );
1217 ber_bvarray_free( sub->sa_any );
1218 if ( sub->sa_initial.bv_val )
1219 ch_free( sub->sa_initial.bv_val );
1227 if( sub->sa_any[i].bv_len > left.bv_len ) {
1228 /* not enough left */
1233 match = memcmp( left.bv_val,
1234 sub->sa_any[i].bv_val,
1235 sub->sa_any[i].bv_len );
1243 left.bv_val += sub->sa_any[i].bv_len;
1244 left.bv_len -= sub->sa_any[i].bv_len;
1245 inlen -= sub->sa_any[i].bv_len;
1252 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1253 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1254 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1258 return LDAP_SUCCESS;
1261 /* Index generation function */
1262 static int caseExactIgnoreIndexer(
1267 struct berval *prefix,
1275 HASH_CONTEXT HASHcontext;
1276 unsigned char HASHdigest[HASH_BYTES];
1277 struct berval digest;
1278 digest.bv_val = HASHdigest;
1279 digest.bv_len = sizeof(HASHdigest);
1281 for( i=0; values[i].bv_val != NULL; i++ ) {
1282 /* empty - just count them */
1285 /* we should have at least one value at this point */
1288 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1290 slen = syntax->ssyn_oidlen;
1291 mlen = mr->smr_oidlen;
1293 casefold = ( mr != caseExactMatchingRule )
1294 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1296 for( i=0; values[i].bv_val != NULL; i++ ) {
1297 struct berval value;
1298 UTF8bvnormalize( &values[i], &value, casefold );
1300 HASH_Init( &HASHcontext );
1301 if( prefix != NULL && prefix->bv_len > 0 ) {
1302 HASH_Update( &HASHcontext,
1303 prefix->bv_val, prefix->bv_len );
1305 HASH_Update( &HASHcontext,
1306 syntax->ssyn_oid, slen );
1307 HASH_Update( &HASHcontext,
1308 mr->smr_oid, mlen );
1309 HASH_Update( &HASHcontext,
1310 value.bv_val, value.bv_len );
1311 HASH_Final( HASHdigest, &HASHcontext );
1313 free( value.bv_val );
1315 ber_dupbv( &keys[i], &digest );
1318 keys[i].bv_val = NULL;
1320 return LDAP_SUCCESS;
1323 /* Index generation function */
1324 static int caseExactIgnoreFilter(
1329 struct berval *prefix,
1336 HASH_CONTEXT HASHcontext;
1337 unsigned char HASHdigest[HASH_BYTES];
1338 struct berval value = { 0, NULL };
1339 struct berval digest;
1341 digest.bv_val = HASHdigest;
1342 digest.bv_len = sizeof(HASHdigest);
1344 slen = syntax->ssyn_oidlen;
1345 mlen = mr->smr_oidlen;
1347 casefold = ( mr != caseExactMatchingRule )
1348 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1350 UTF8bvnormalize( (struct berval *) assertValue, &value, casefold );
1351 /* This usually happens if filter contains bad UTF8 */
1352 if( value.bv_val == NULL ) {
1353 keys = ch_malloc( sizeof( struct berval ) );
1354 keys[0].bv_val = NULL;
1355 return LDAP_SUCCESS;
1358 keys = ch_malloc( sizeof( struct berval ) * 2 );
1360 HASH_Init( &HASHcontext );
1361 if( prefix != NULL && prefix->bv_len > 0 ) {
1362 HASH_Update( &HASHcontext,
1363 prefix->bv_val, prefix->bv_len );
1365 HASH_Update( &HASHcontext,
1366 syntax->ssyn_oid, slen );
1367 HASH_Update( &HASHcontext,
1368 mr->smr_oid, mlen );
1369 HASH_Update( &HASHcontext,
1370 value.bv_val, value.bv_len );
1371 HASH_Final( HASHdigest, &HASHcontext );
1373 ber_dupbv( keys, &digest );
1374 keys[1].bv_val = NULL;
1376 free( value.bv_val );
1379 return LDAP_SUCCESS;
1382 /* Substrings Index generation function */
1383 static int caseExactIgnoreSubstringsIndexer(
1388 struct berval *prefix,
1398 HASH_CONTEXT HASHcontext;
1399 unsigned char HASHdigest[HASH_BYTES];
1400 struct berval digest;
1401 digest.bv_val = HASHdigest;
1402 digest.bv_len = sizeof(HASHdigest);
1406 for( i=0; values[i].bv_val != NULL; i++ ) {
1407 /* empty - just count them */
1410 /* we should have at least one value at this point */
1413 casefold = ( mr != caseExactSubstringsMatchingRule )
1414 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1416 nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1417 for( i=0; values[i].bv_val != NULL; i++ ) {
1418 UTF8bvnormalize( &values[i], &nvalues[i], casefold );
1420 nvalues[i].bv_val = NULL;
1423 for( i=0; values[i].bv_val != NULL; i++ ) {
1424 /* count number of indices to generate */
1425 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1429 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1430 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1431 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1432 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1434 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1438 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1439 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1440 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1444 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1445 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1446 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1447 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1449 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1455 /* no keys to generate */
1457 ber_bvarray_free( nvalues );
1458 return LDAP_SUCCESS;
1461 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1463 slen = syntax->ssyn_oidlen;
1464 mlen = mr->smr_oidlen;
1467 for( i=0; values[i].bv_val != NULL; i++ ) {
1470 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1472 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1473 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1475 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1476 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1478 for( j=0; j<max; j++ ) {
1479 HASH_Init( &HASHcontext );
1480 if( prefix != NULL && prefix->bv_len > 0 ) {
1481 HASH_Update( &HASHcontext,
1482 prefix->bv_val, prefix->bv_len );
1485 HASH_Update( &HASHcontext,
1486 &pre, sizeof( pre ) );
1487 HASH_Update( &HASHcontext,
1488 syntax->ssyn_oid, slen );
1489 HASH_Update( &HASHcontext,
1490 mr->smr_oid, mlen );
1491 HASH_Update( &HASHcontext,
1492 &values[i].bv_val[j],
1493 SLAP_INDEX_SUBSTR_MAXLEN );
1494 HASH_Final( HASHdigest, &HASHcontext );
1496 ber_dupbv( &keys[nkeys++], &digest );
1500 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1501 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1503 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1506 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1507 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1508 HASH_Init( &HASHcontext );
1509 if( prefix != NULL && prefix->bv_len > 0 ) {
1510 HASH_Update( &HASHcontext,
1511 prefix->bv_val, prefix->bv_len );
1513 HASH_Update( &HASHcontext,
1514 &pre, sizeof( pre ) );
1515 HASH_Update( &HASHcontext,
1516 syntax->ssyn_oid, slen );
1517 HASH_Update( &HASHcontext,
1518 mr->smr_oid, mlen );
1519 HASH_Update( &HASHcontext,
1520 values[i].bv_val, j );
1521 HASH_Final( HASHdigest, &HASHcontext );
1523 ber_dupbv( &keys[nkeys++], &digest );
1526 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1527 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1528 HASH_Init( &HASHcontext );
1529 if( prefix != NULL && prefix->bv_len > 0 ) {
1530 HASH_Update( &HASHcontext,
1531 prefix->bv_val, prefix->bv_len );
1533 HASH_Update( &HASHcontext,
1534 &pre, sizeof( pre ) );
1535 HASH_Update( &HASHcontext,
1536 syntax->ssyn_oid, slen );
1537 HASH_Update( &HASHcontext,
1538 mr->smr_oid, mlen );
1539 HASH_Update( &HASHcontext,
1540 &values[i].bv_val[values[i].bv_len-j], j );
1541 HASH_Final( HASHdigest, &HASHcontext );
1543 ber_dupbv( &keys[nkeys++], &digest );
1551 keys[nkeys].bv_val = NULL;
1558 ber_bvarray_free( nvalues );
1560 return LDAP_SUCCESS;
1563 static int caseExactIgnoreSubstringsFilter(
1568 struct berval *prefix,
1572 SubstringsAssertion *sa;
1575 ber_len_t nkeys = 0;
1576 size_t slen, mlen, klen;
1578 HASH_CONTEXT HASHcontext;
1579 unsigned char HASHdigest[HASH_BYTES];
1580 struct berval *value;
1581 struct berval digest;
1583 casefold = ( mr != caseExactSubstringsMatchingRule )
1584 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1586 sa = UTF8SubstringsassertionNormalize( assertValue, casefold );
1589 return LDAP_SUCCESS;
1592 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1593 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1598 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1600 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1601 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1602 /* don't bother accounting for stepping */
1603 nkeys += sa->sa_any[i].bv_len -
1604 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1609 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1610 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1616 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1617 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1618 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1621 return LDAP_SUCCESS;
1624 digest.bv_val = HASHdigest;
1625 digest.bv_len = sizeof(HASHdigest);
1627 slen = syntax->ssyn_oidlen;
1628 mlen = mr->smr_oidlen;
1630 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1633 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1634 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1636 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1637 value = &sa->sa_initial;
1639 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1640 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1642 HASH_Init( &HASHcontext );
1643 if( prefix != NULL && prefix->bv_len > 0 ) {
1644 HASH_Update( &HASHcontext,
1645 prefix->bv_val, prefix->bv_len );
1647 HASH_Update( &HASHcontext,
1648 &pre, sizeof( pre ) );
1649 HASH_Update( &HASHcontext,
1650 syntax->ssyn_oid, slen );
1651 HASH_Update( &HASHcontext,
1652 mr->smr_oid, mlen );
1653 HASH_Update( &HASHcontext,
1654 value->bv_val, klen );
1655 HASH_Final( HASHdigest, &HASHcontext );
1657 ber_dupbv( &keys[nkeys++], &digest );
1660 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1662 pre = SLAP_INDEX_SUBSTR_PREFIX;
1663 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1665 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1666 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1670 value = &sa->sa_any[i];
1673 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1674 j += SLAP_INDEX_SUBSTR_STEP )
1676 HASH_Init( &HASHcontext );
1677 if( prefix != NULL && prefix->bv_len > 0 ) {
1678 HASH_Update( &HASHcontext,
1679 prefix->bv_val, prefix->bv_len );
1681 HASH_Update( &HASHcontext,
1682 &pre, sizeof( pre ) );
1683 HASH_Update( &HASHcontext,
1684 syntax->ssyn_oid, slen );
1685 HASH_Update( &HASHcontext,
1686 mr->smr_oid, mlen );
1687 HASH_Update( &HASHcontext,
1688 &value->bv_val[j], klen );
1689 HASH_Final( HASHdigest, &HASHcontext );
1691 ber_dupbv( &keys[nkeys++], &digest );
1697 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1698 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1700 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1701 value = &sa->sa_final;
1703 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1704 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1706 HASH_Init( &HASHcontext );
1707 if( prefix != NULL && prefix->bv_len > 0 ) {
1708 HASH_Update( &HASHcontext,
1709 prefix->bv_val, prefix->bv_len );
1711 HASH_Update( &HASHcontext,
1712 &pre, sizeof( pre ) );
1713 HASH_Update( &HASHcontext,
1714 syntax->ssyn_oid, slen );
1715 HASH_Update( &HASHcontext,
1716 mr->smr_oid, mlen );
1717 HASH_Update( &HASHcontext,
1718 &value->bv_val[value->bv_len-klen], klen );
1719 HASH_Final( HASHdigest, &HASHcontext );
1721 ber_dupbv( &keys[nkeys++], &digest );
1725 keys[nkeys].bv_val = NULL;
1731 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1732 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1733 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1736 return LDAP_SUCCESS;
1745 struct berval *value,
1746 void *assertedValue )
1748 *matchp = UTF8bvnormcmp( value,
1749 (struct berval *) assertedValue,
1750 LDAP_UTF8_CASEFOLD );
1751 return LDAP_SUCCESS;
1754 /* Remove all spaces and '-' characters */
1756 telephoneNumberNormalize(
1759 struct berval *normalized )
1763 /* validator should have refused an empty string */
1764 assert( val->bv_len );
1766 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1768 for( p = val->bv_val; *p; p++ ) {
1769 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1775 normalized->bv_len = q - normalized->bv_val;
1777 if( normalized->bv_len == 0 ) {
1778 free( normalized->bv_val );
1779 return LDAP_INVALID_SYNTAX;
1782 return LDAP_SUCCESS;
1788 struct berval *val )
1792 if( val->bv_len == 0 ) {
1793 /* disallow empty strings */
1794 return LDAP_INVALID_SYNTAX;
1797 if( OID_LEADCHAR(val->bv_val[0]) ) {
1799 for(i=1; i < val->bv_len; i++) {
1800 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1801 if( dot++ ) return 1;
1802 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1805 return LDAP_INVALID_SYNTAX;
1809 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1811 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1812 for(i=1; i < val->bv_len; i++) {
1813 if( !DESC_CHAR(val->bv_val[i] ) ) {
1814 return LDAP_INVALID_SYNTAX;
1818 return LDAP_SUCCESS;
1821 return LDAP_INVALID_SYNTAX;
1830 struct berval *value,
1831 void *assertedValue )
1834 int vsign = 1, avsign = 1; /* default sign = '+' */
1835 struct berval *asserted;
1836 ber_len_t vlen, avlen;
1839 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1841 vlen = value->bv_len;
1842 if( mr == integerFirstComponentMatchingRule ) {
1843 char *tmp = memchr( v, '$', vlen );
1846 while( vlen && ASCII_SPACE( v[vlen-1] ))
1849 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) /* ANSI 2.2.1 */
1855 /* Do the same with the *assertedValue number */
1856 asserted = (struct berval *) assertedValue;
1857 av = asserted->bv_val;
1858 avlen = asserted->bv_len;
1859 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1865 match = vsign - avsign;
1867 match = (vlen != avlen
1868 ? ( vlen < avlen ? -1 : 1 )
1869 : memcmp( v, av, vlen ));
1875 return LDAP_SUCCESS;
1881 struct berval *val )
1885 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1887 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1888 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1889 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1890 return LDAP_INVALID_SYNTAX;
1893 for( i=1; i < val->bv_len; i++ ) {
1894 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1897 return LDAP_SUCCESS;
1904 struct berval *normalized )
1914 /* Ignore leading spaces */
1915 while ( len && ( *p == ' ' )) {
1922 negative = ( *p == '-' );
1923 if(( *p == '-' ) || ( *p == '+' )) {
1929 /* Ignore leading zeros */
1930 while ( len && ( *p == '0' )) {
1935 /* If there are no non-zero digits left, the number is zero, otherwise
1936 allocate space for the number and copy it into the buffer */
1938 normalized->bv_val = ch_strdup("0");
1939 normalized->bv_len = 1;
1942 normalized->bv_len = len+negative;
1943 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1945 normalized->bv_val[0] = '-';
1947 AC_MEMCPY( normalized->bv_val + negative, p, len );
1948 normalized->bv_val[len+negative] = '\0';
1951 return LDAP_SUCCESS;
1954 /* Index generation function */
1955 static int integerIndexer(
1960 struct berval *prefix,
1967 HASH_CONTEXT HASHcontext;
1968 unsigned char HASHdigest[HASH_BYTES];
1969 struct berval digest;
1970 digest.bv_val = HASHdigest;
1971 digest.bv_len = sizeof(HASHdigest);
1973 for( i=0; values[i].bv_val != NULL; i++ ) {
1974 /* empty - just count them */
1977 /* we should have at least one value at this point */
1980 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1982 slen = syntax->ssyn_oidlen;
1983 mlen = mr->smr_oidlen;
1985 for( i=0; values[i].bv_val != NULL; i++ ) {
1987 integerNormalize( syntax, &values[i], &norm );
1989 HASH_Init( &HASHcontext );
1990 if( prefix != NULL && prefix->bv_len > 0 ) {
1991 HASH_Update( &HASHcontext,
1992 prefix->bv_val, prefix->bv_len );
1994 HASH_Update( &HASHcontext,
1995 syntax->ssyn_oid, slen );
1996 HASH_Update( &HASHcontext,
1997 mr->smr_oid, mlen );
1998 HASH_Update( &HASHcontext,
1999 norm.bv_val, norm.bv_len );
2000 HASH_Final( HASHdigest, &HASHcontext );
2002 ber_dupbv( &keys[i], &digest );
2003 ch_free( norm.bv_val );
2006 keys[i].bv_val = NULL;
2008 return LDAP_SUCCESS;
2011 /* Index generation function */
2012 static int integerFilter(
2017 struct berval *prefix,
2023 HASH_CONTEXT HASHcontext;
2024 unsigned char HASHdigest[HASH_BYTES];
2026 struct berval digest;
2027 digest.bv_val = HASHdigest;
2028 digest.bv_len = sizeof(HASHdigest);
2030 slen = syntax->ssyn_oidlen;
2031 mlen = mr->smr_oidlen;
2033 integerNormalize( syntax, assertValue, &norm );
2035 keys = ch_malloc( sizeof( struct berval ) * 2 );
2037 HASH_Init( &HASHcontext );
2038 if( prefix != NULL && prefix->bv_len > 0 ) {
2039 HASH_Update( &HASHcontext,
2040 prefix->bv_val, prefix->bv_len );
2042 HASH_Update( &HASHcontext,
2043 syntax->ssyn_oid, slen );
2044 HASH_Update( &HASHcontext,
2045 mr->smr_oid, mlen );
2046 HASH_Update( &HASHcontext,
2047 norm.bv_val, norm.bv_len );
2048 HASH_Final( HASHdigest, &HASHcontext );
2050 ber_dupbv( &keys[0], &digest );
2051 keys[1].bv_val = NULL;
2052 ch_free( norm.bv_val );
2055 return LDAP_SUCCESS;
2060 countryStringValidate(
2062 struct berval *val )
2064 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2066 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2067 return LDAP_INVALID_SYNTAX;
2069 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2070 return LDAP_INVALID_SYNTAX;
2073 return LDAP_SUCCESS;
2077 printableStringValidate(
2079 struct berval *val )
2083 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2085 for(i=0; i < val->bv_len; i++) {
2086 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2087 return LDAP_INVALID_SYNTAX;
2091 return LDAP_SUCCESS;
2095 printablesStringValidate(
2097 struct berval *val )
2101 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2103 for(i=0,len=0; i < val->bv_len; i++) {
2104 int c = val->bv_val[i];
2108 return LDAP_INVALID_SYNTAX;
2112 } else if ( SLAP_PRINTABLE(c) ) {
2115 return LDAP_INVALID_SYNTAX;
2119 if( len == 0 ) LDAP_INVALID_SYNTAX;
2121 return LDAP_SUCCESS;
2127 struct berval *val )
2131 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2133 for(i=0; i < val->bv_len; i++) {
2134 if( !LDAP_ASCII(val->bv_val[i]) ) {
2135 return LDAP_INVALID_SYNTAX;
2139 return LDAP_SUCCESS;
2146 struct berval *normalized )
2150 assert( val->bv_len );
2154 /* Ignore initial whitespace */
2155 while ( ASCII_SPACE( *p ) ) {
2159 normalized->bv_val = ch_strdup( p );
2160 p = q = normalized->bv_val;
2163 if ( ASCII_SPACE( *p ) ) {
2166 /* Ignore the extra whitespace */
2167 while ( ASCII_SPACE( *p ) ) {
2175 assert( normalized->bv_val <= p );
2179 * If the string ended in space, backup the pointer one
2180 * position. One is enough because the above loop collapsed
2181 * all whitespace to a single space.
2184 if ( ASCII_SPACE( q[-1] ) ) {
2188 /* null terminate */
2191 normalized->bv_len = q - normalized->bv_val;
2193 if( normalized->bv_len == 0 ) {
2194 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
2195 normalized->bv_val[0] = ' ';
2196 normalized->bv_val[1] = '\0';
2197 normalized->bv_len = 1;
2200 return LDAP_SUCCESS;
2209 struct berval *value,
2210 void *assertedValue )
2212 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2215 match = strncmp( value->bv_val,
2216 ((struct berval *) assertedValue)->bv_val,
2221 return LDAP_SUCCESS;
2225 caseExactIA5SubstringsMatch(
2230 struct berval *value,
2231 void *assertedValue )
2234 SubstringsAssertion *sub = assertedValue;
2235 struct berval left = *value;
2239 /* Add up asserted input length */
2240 if( sub->sa_initial.bv_val ) {
2241 inlen += sub->sa_initial.bv_len;
2244 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2245 inlen += sub->sa_any[i].bv_len;
2248 if( sub->sa_final.bv_val ) {
2249 inlen += sub->sa_final.bv_len;
2252 if( sub->sa_initial.bv_val ) {
2253 if( inlen > left.bv_len ) {
2258 match = strncmp( sub->sa_initial.bv_val, left.bv_val,
2259 sub->sa_initial.bv_len );
2265 left.bv_val += sub->sa_initial.bv_len;
2266 left.bv_len -= sub->sa_initial.bv_len;
2267 inlen -= sub->sa_initial.bv_len;
2270 if( sub->sa_final.bv_val ) {
2271 if( inlen > left.bv_len ) {
2276 match = strncmp( sub->sa_final.bv_val,
2277 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2278 sub->sa_final.bv_len );
2284 left.bv_len -= sub->sa_final.bv_len;
2285 inlen -= sub->sa_final.bv_len;
2289 for(i=0; sub->sa_any[i].bv_val; i++) {
2294 if( inlen > left.bv_len ) {
2295 /* not enough length */
2300 if( sub->sa_any[i].bv_len == 0 ) {
2304 p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
2311 idx = p - left.bv_val;
2313 if( idx >= left.bv_len ) {
2314 /* this shouldn't happen */
2321 if( sub->sa_any[i].bv_len > left.bv_len ) {
2322 /* not enough left */
2327 match = strncmp( left.bv_val,
2328 sub->sa_any[i].bv_val,
2329 sub->sa_any[i].bv_len );
2337 left.bv_val += sub->sa_any[i].bv_len;
2338 left.bv_len -= sub->sa_any[i].bv_len;
2339 inlen -= sub->sa_any[i].bv_len;
2345 return LDAP_SUCCESS;
2348 /* Index generation function */
2349 static int caseExactIA5Indexer(
2354 struct berval *prefix,
2361 HASH_CONTEXT HASHcontext;
2362 unsigned char HASHdigest[HASH_BYTES];
2363 struct berval digest;
2364 digest.bv_val = HASHdigest;
2365 digest.bv_len = sizeof(HASHdigest);
2367 for( i=0; values[i].bv_val != NULL; i++ ) {
2368 /* empty - just count them */
2371 /* we should have at least one value at this point */
2374 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2376 slen = syntax->ssyn_oidlen;
2377 mlen = mr->smr_oidlen;
2379 for( i=0; values[i].bv_val != NULL; i++ ) {
2380 struct berval *value = &values[i];
2382 HASH_Init( &HASHcontext );
2383 if( prefix != NULL && prefix->bv_len > 0 ) {
2384 HASH_Update( &HASHcontext,
2385 prefix->bv_val, prefix->bv_len );
2387 HASH_Update( &HASHcontext,
2388 syntax->ssyn_oid, slen );
2389 HASH_Update( &HASHcontext,
2390 mr->smr_oid, mlen );
2391 HASH_Update( &HASHcontext,
2392 value->bv_val, value->bv_len );
2393 HASH_Final( HASHdigest, &HASHcontext );
2395 ber_dupbv( &keys[i], &digest );
2398 keys[i].bv_val = NULL;
2400 return LDAP_SUCCESS;
2403 /* Index generation function */
2404 static int caseExactIA5Filter(
2409 struct berval *prefix,
2415 HASH_CONTEXT HASHcontext;
2416 unsigned char HASHdigest[HASH_BYTES];
2417 struct berval *value;
2418 struct berval digest;
2419 digest.bv_val = HASHdigest;
2420 digest.bv_len = sizeof(HASHdigest);
2422 slen = syntax->ssyn_oidlen;
2423 mlen = mr->smr_oidlen;
2425 value = (struct berval *) assertValue;
2427 keys = ch_malloc( sizeof( struct berval ) * 2 );
2429 HASH_Init( &HASHcontext );
2430 if( prefix != NULL && prefix->bv_len > 0 ) {
2431 HASH_Update( &HASHcontext,
2432 prefix->bv_val, prefix->bv_len );
2434 HASH_Update( &HASHcontext,
2435 syntax->ssyn_oid, slen );
2436 HASH_Update( &HASHcontext,
2437 mr->smr_oid, mlen );
2438 HASH_Update( &HASHcontext,
2439 value->bv_val, value->bv_len );
2440 HASH_Final( HASHdigest, &HASHcontext );
2442 ber_dupbv( &keys[0], &digest );
2443 keys[1].bv_val = NULL;
2446 return LDAP_SUCCESS;
2449 /* Substrings Index generation function */
2450 static int caseExactIA5SubstringsIndexer(
2455 struct berval *prefix,
2462 HASH_CONTEXT HASHcontext;
2463 unsigned char HASHdigest[HASH_BYTES];
2464 struct berval digest;
2465 digest.bv_val = HASHdigest;
2466 digest.bv_len = sizeof(HASHdigest);
2468 /* we should have at least one value at this point */
2469 assert( values != NULL && values[0].bv_val != NULL );
2472 for( i=0; values[i].bv_val != NULL; i++ ) {
2473 /* count number of indices to generate */
2474 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2478 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2479 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2480 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2481 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2483 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2487 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2488 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2489 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2493 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2494 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2495 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2496 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2498 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2504 /* no keys to generate */
2506 return LDAP_SUCCESS;
2509 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2511 slen = syntax->ssyn_oidlen;
2512 mlen = mr->smr_oidlen;
2515 for( i=0; values[i].bv_val != NULL; i++ ) {
2517 struct berval *value;
2520 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2522 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2523 ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2525 char pre = SLAP_INDEX_SUBSTR_PREFIX;
2526 max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2528 for( j=0; j<max; j++ ) {
2529 HASH_Init( &HASHcontext );
2530 if( prefix != NULL && prefix->bv_len > 0 ) {
2531 HASH_Update( &HASHcontext,
2532 prefix->bv_val, prefix->bv_len );
2535 HASH_Update( &HASHcontext,
2536 &pre, sizeof( pre ) );
2537 HASH_Update( &HASHcontext,
2538 syntax->ssyn_oid, slen );
2539 HASH_Update( &HASHcontext,
2540 mr->smr_oid, mlen );
2541 HASH_Update( &HASHcontext,
2543 SLAP_INDEX_SUBSTR_MAXLEN );
2544 HASH_Final( HASHdigest, &HASHcontext );
2546 ber_dupbv( &keys[nkeys++], &digest );
2550 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2551 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2553 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2556 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2557 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2558 HASH_Init( &HASHcontext );
2559 if( prefix != NULL && prefix->bv_len > 0 ) {
2560 HASH_Update( &HASHcontext,
2561 prefix->bv_val, prefix->bv_len );
2563 HASH_Update( &HASHcontext,
2564 &pre, sizeof( pre ) );
2565 HASH_Update( &HASHcontext,
2566 syntax->ssyn_oid, slen );
2567 HASH_Update( &HASHcontext,
2568 mr->smr_oid, mlen );
2569 HASH_Update( &HASHcontext,
2571 HASH_Final( HASHdigest, &HASHcontext );
2573 ber_dupbv( &keys[nkeys++], &digest );
2576 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2577 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2578 HASH_Init( &HASHcontext );
2579 if( prefix != NULL && prefix->bv_len > 0 ) {
2580 HASH_Update( &HASHcontext,
2581 prefix->bv_val, prefix->bv_len );
2583 HASH_Update( &HASHcontext,
2584 &pre, sizeof( pre ) );
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-j], j );
2591 HASH_Final( HASHdigest, &HASHcontext );
2593 ber_dupbv( &keys[nkeys++], &digest );
2600 keys[nkeys].bv_val = NULL;
2607 return LDAP_SUCCESS;
2610 static int caseExactIA5SubstringsFilter(
2615 struct berval *prefix,
2619 SubstringsAssertion *sa = assertValue;
2621 ber_len_t nkeys = 0;
2622 size_t slen, mlen, klen;
2624 HASH_CONTEXT HASHcontext;
2625 unsigned char HASHdigest[HASH_BYTES];
2626 struct berval *value;
2627 struct berval digest;
2629 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2630 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2635 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2637 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2638 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2639 /* don't bother accounting for stepping */
2640 nkeys += sa->sa_any[i].bv_len -
2641 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2646 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2647 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2654 return LDAP_SUCCESS;
2657 digest.bv_val = HASHdigest;
2658 digest.bv_len = sizeof(HASHdigest);
2660 slen = syntax->ssyn_oidlen;
2661 mlen = mr->smr_oidlen;
2663 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2666 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2667 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2669 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2670 value = &sa->sa_initial;
2672 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2673 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2675 HASH_Init( &HASHcontext );
2676 if( prefix != NULL && prefix->bv_len > 0 ) {
2677 HASH_Update( &HASHcontext,
2678 prefix->bv_val, prefix->bv_len );
2680 HASH_Update( &HASHcontext,
2681 &pre, sizeof( pre ) );
2682 HASH_Update( &HASHcontext,
2683 syntax->ssyn_oid, slen );
2684 HASH_Update( &HASHcontext,
2685 mr->smr_oid, mlen );
2686 HASH_Update( &HASHcontext,
2687 value->bv_val, klen );
2688 HASH_Final( HASHdigest, &HASHcontext );
2690 ber_dupbv( &keys[nkeys++], &digest );
2693 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2695 pre = SLAP_INDEX_SUBSTR_PREFIX;
2696 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2698 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2699 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2703 value = &sa->sa_any[i];
2706 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2707 j += SLAP_INDEX_SUBSTR_STEP )
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,
2721 &value->bv_val[j], klen );
2722 HASH_Final( HASHdigest, &HASHcontext );
2724 ber_dupbv( &keys[nkeys++], &digest );
2729 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2730 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2732 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2733 value = &sa->sa_final;
2735 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2736 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2738 HASH_Init( &HASHcontext );
2739 if( prefix != NULL && prefix->bv_len > 0 ) {
2740 HASH_Update( &HASHcontext,
2741 prefix->bv_val, prefix->bv_len );
2743 HASH_Update( &HASHcontext,
2744 &pre, sizeof( pre ) );
2745 HASH_Update( &HASHcontext,
2746 syntax->ssyn_oid, slen );
2747 HASH_Update( &HASHcontext,
2748 mr->smr_oid, mlen );
2749 HASH_Update( &HASHcontext,
2750 &value->bv_val[value->bv_len-klen], klen );
2751 HASH_Final( HASHdigest, &HASHcontext );
2753 ber_dupbv( &keys[nkeys++], &digest );
2757 keys[nkeys].bv_val = NULL;
2764 return LDAP_SUCCESS;
2773 struct berval *value,
2774 void *assertedValue )
2776 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2778 if( match == 0 && value->bv_len ) {
2779 match = strncasecmp( value->bv_val,
2780 ((struct berval *) assertedValue)->bv_val,
2785 return LDAP_SUCCESS;
2789 caseIgnoreIA5SubstringsMatch(
2794 struct berval *value,
2795 void *assertedValue )
2798 SubstringsAssertion *sub = assertedValue;
2799 struct berval left = *value;
2803 /* Add up asserted input length */
2804 if( sub->sa_initial.bv_val ) {
2805 inlen += sub->sa_initial.bv_len;
2808 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2809 inlen += sub->sa_any[i].bv_len;
2812 if( sub->sa_final.bv_val ) {
2813 inlen += sub->sa_final.bv_len;
2816 if( sub->sa_initial.bv_val ) {
2817 if( inlen > left.bv_len ) {
2822 match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
2823 sub->sa_initial.bv_len );
2829 left.bv_val += sub->sa_initial.bv_len;
2830 left.bv_len -= sub->sa_initial.bv_len;
2831 inlen -= sub->sa_initial.bv_len;
2834 if( sub->sa_final.bv_val ) {
2835 if( inlen > left.bv_len ) {
2840 match = strncasecmp( sub->sa_final.bv_val,
2841 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2842 sub->sa_final.bv_len );
2848 left.bv_len -= sub->sa_final.bv_len;
2849 inlen -= sub->sa_final.bv_len;
2853 for(i=0; sub->sa_any[i].bv_val; i++) {
2858 if( inlen > left.bv_len ) {
2859 /* not enough length */
2864 if( sub->sa_any[i].bv_len == 0 ) {
2868 p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
2875 assert( idx < left.bv_len );
2876 if( idx >= left.bv_len ) {
2877 /* this shouldn't happen */
2884 if( sub->sa_any[i].bv_len > left.bv_len ) {
2885 /* not enough left */
2890 match = strncasecmp( left.bv_val,
2891 sub->sa_any[i].bv_val,
2892 sub->sa_any[i].bv_len );
2901 left.bv_val += sub->sa_any[i].bv_len;
2902 left.bv_len -= sub->sa_any[i].bv_len;
2903 inlen -= sub->sa_any[i].bv_len;
2909 return LDAP_SUCCESS;
2912 /* Index generation function */
2913 static int caseIgnoreIA5Indexer(
2918 struct berval *prefix,
2923 int rc = LDAP_SUCCESS;
2926 HASH_CONTEXT HASHcontext;
2927 unsigned char HASHdigest[HASH_BYTES];
2928 struct berval digest;
2929 digest.bv_val = HASHdigest;
2930 digest.bv_len = sizeof(HASHdigest);
2932 /* we should have at least one value at this point */
2933 assert( values != NULL && values[0].bv_val != NULL );
2935 for( i=0; values[i].bv_val != NULL; i++ ) {
2936 /* just count them */
2939 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2941 slen = syntax->ssyn_oidlen;
2942 mlen = mr->smr_oidlen;
2944 for( i=0; values[i].bv_val != NULL; i++ ) {
2945 struct berval value;
2947 if( mr->smr_normalize ) {
2948 rc = (mr->smr_normalize)( use, syntax, mr, &values[i], &value );
2949 if( rc != LDAP_SUCCESS ) {
2952 } else if ( mr->smr_syntax->ssyn_normalize ) {
2953 rc = (mr->smr_syntax->ssyn_normalize)( syntax, &values[i], &value );
2954 if( rc != LDAP_SUCCESS ) {
2958 ber_dupbv( &value, &values[i] );
2961 ldap_pvt_str2lower( value.bv_val );
2963 HASH_Init( &HASHcontext );
2964 if( prefix != NULL && prefix->bv_len > 0 ) {
2965 HASH_Update( &HASHcontext,
2966 prefix->bv_val, prefix->bv_len );
2968 HASH_Update( &HASHcontext,
2969 syntax->ssyn_oid, slen );
2970 HASH_Update( &HASHcontext,
2971 mr->smr_oid, mlen );
2972 HASH_Update( &HASHcontext,
2973 value.bv_val, value.bv_len );
2974 HASH_Final( HASHdigest, &HASHcontext );
2976 free( value.bv_val );
2978 ber_dupbv( &keys[i], &digest );
2981 keys[i].bv_val = NULL;
2982 if( rc != LDAP_SUCCESS ) {
2983 ber_bvarray_free( keys );
2990 /* Index generation function */
2991 static int caseIgnoreIA5Filter(
2996 struct berval *prefix,
3002 HASH_CONTEXT HASHcontext;
3003 unsigned char HASHdigest[HASH_BYTES];
3004 struct berval value;
3005 struct berval digest;
3006 digest.bv_val = HASHdigest;
3007 digest.bv_len = sizeof(HASHdigest);
3009 slen = syntax->ssyn_oidlen;
3010 mlen = mr->smr_oidlen;
3012 ber_dupbv( &value, (struct berval *) assertValue );
3013 ldap_pvt_str2lower( value.bv_val );
3015 keys = ch_malloc( sizeof( struct berval ) * 2 );
3017 HASH_Init( &HASHcontext );
3018 if( prefix != NULL && prefix->bv_len > 0 ) {
3019 HASH_Update( &HASHcontext,
3020 prefix->bv_val, prefix->bv_len );
3022 HASH_Update( &HASHcontext,
3023 syntax->ssyn_oid, slen );
3024 HASH_Update( &HASHcontext,
3025 mr->smr_oid, mlen );
3026 HASH_Update( &HASHcontext,
3027 value.bv_val, value.bv_len );
3028 HASH_Final( HASHdigest, &HASHcontext );
3030 ber_dupbv( &keys[0], &digest );
3031 keys[1].bv_val = NULL;
3033 free( value.bv_val );
3037 return LDAP_SUCCESS;
3040 /* Substrings Index generation function */
3041 static int caseIgnoreIA5SubstringsIndexer(
3046 struct berval *prefix,
3053 HASH_CONTEXT HASHcontext;
3054 unsigned char HASHdigest[HASH_BYTES];
3055 struct berval digest;
3056 digest.bv_val = HASHdigest;
3057 digest.bv_len = sizeof(HASHdigest);
3059 /* we should have at least one value at this point */
3060 assert( values != NULL && values[0].bv_val != NULL );
3063 for( i=0; values[i].bv_val != NULL; i++ ) {
3064 /* count number of indices to generate */
3065 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3069 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3070 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3071 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3072 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3074 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3078 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3079 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3080 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3084 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3085 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3086 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3087 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3089 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3095 /* no keys to generate */
3097 return LDAP_SUCCESS;
3100 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3102 slen = syntax->ssyn_oidlen;
3103 mlen = mr->smr_oidlen;
3106 for( i=0; values[i].bv_val != NULL; i++ ) {
3108 struct berval value;
3110 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3112 ber_dupbv( &value, &values[i] );
3113 ldap_pvt_str2lower( value.bv_val );
3115 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3116 ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3118 char pre = SLAP_INDEX_SUBSTR_PREFIX;
3119 max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3121 for( j=0; j<max; j++ ) {
3122 HASH_Init( &HASHcontext );
3123 if( prefix != NULL && prefix->bv_len > 0 ) {
3124 HASH_Update( &HASHcontext,
3125 prefix->bv_val, prefix->bv_len );
3128 HASH_Update( &HASHcontext,
3129 &pre, sizeof( pre ) );
3130 HASH_Update( &HASHcontext,
3131 syntax->ssyn_oid, slen );
3132 HASH_Update( &HASHcontext,
3133 mr->smr_oid, mlen );
3134 HASH_Update( &HASHcontext,
3136 SLAP_INDEX_SUBSTR_MAXLEN );
3137 HASH_Final( HASHdigest, &HASHcontext );
3139 ber_dupbv( &keys[nkeys++], &digest );
3143 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3144 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3146 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3149 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3150 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3151 HASH_Init( &HASHcontext );
3152 if( prefix != NULL && prefix->bv_len > 0 ) {
3153 HASH_Update( &HASHcontext,
3154 prefix->bv_val, prefix->bv_len );
3156 HASH_Update( &HASHcontext,
3157 &pre, sizeof( pre ) );
3158 HASH_Update( &HASHcontext,
3159 syntax->ssyn_oid, slen );
3160 HASH_Update( &HASHcontext,
3161 mr->smr_oid, mlen );
3162 HASH_Update( &HASHcontext,
3164 HASH_Final( HASHdigest, &HASHcontext );
3166 ber_dupbv( &keys[nkeys++], &digest );
3169 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3170 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3171 HASH_Init( &HASHcontext );
3172 if( prefix != NULL && prefix->bv_len > 0 ) {
3173 HASH_Update( &HASHcontext,
3174 prefix->bv_val, prefix->bv_len );
3176 HASH_Update( &HASHcontext,
3177 &pre, sizeof( pre ) );
3178 HASH_Update( &HASHcontext,
3179 syntax->ssyn_oid, slen );
3180 HASH_Update( &HASHcontext,
3181 mr->smr_oid, mlen );
3182 HASH_Update( &HASHcontext,
3183 &value.bv_val[value.bv_len-j], j );
3184 HASH_Final( HASHdigest, &HASHcontext );
3186 ber_dupbv( &keys[nkeys++], &digest );
3191 free( value.bv_val );
3195 keys[nkeys].bv_val = NULL;
3202 return LDAP_SUCCESS;
3205 static int caseIgnoreIA5SubstringsFilter(
3210 struct berval *prefix,
3214 SubstringsAssertion *sa = assertValue;
3216 ber_len_t nkeys = 0;
3217 size_t slen, mlen, klen;
3219 HASH_CONTEXT HASHcontext;
3220 unsigned char HASHdigest[HASH_BYTES];
3221 struct berval value;
3222 struct berval digest;
3224 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3225 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3230 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3232 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3233 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3234 /* don't bother accounting for stepping */
3235 nkeys += sa->sa_any[i].bv_len -
3236 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3241 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3242 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3249 return LDAP_SUCCESS;
3252 digest.bv_val = HASHdigest;
3253 digest.bv_len = sizeof(HASHdigest);
3255 slen = syntax->ssyn_oidlen;
3256 mlen = mr->smr_oidlen;
3258 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3261 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3262 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3264 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3265 ber_dupbv( &value, &sa->sa_initial );
3266 ldap_pvt_str2lower( value.bv_val );
3268 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3269 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3271 HASH_Init( &HASHcontext );
3272 if( prefix != NULL && prefix->bv_len > 0 ) {
3273 HASH_Update( &HASHcontext,
3274 prefix->bv_val, prefix->bv_len );
3276 HASH_Update( &HASHcontext,
3277 &pre, sizeof( pre ) );
3278 HASH_Update( &HASHcontext,
3279 syntax->ssyn_oid, slen );
3280 HASH_Update( &HASHcontext,
3281 mr->smr_oid, mlen );
3282 HASH_Update( &HASHcontext,
3283 value.bv_val, klen );
3284 HASH_Final( HASHdigest, &HASHcontext );
3286 free( value.bv_val );
3287 ber_dupbv( &keys[nkeys++], &digest );
3290 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3292 pre = SLAP_INDEX_SUBSTR_PREFIX;
3293 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3295 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3296 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3300 ber_dupbv( &value, &sa->sa_any[i] );
3301 ldap_pvt_str2lower( value.bv_val );
3304 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3305 j += SLAP_INDEX_SUBSTR_STEP )
3307 HASH_Init( &HASHcontext );
3308 if( prefix != NULL && prefix->bv_len > 0 ) {
3309 HASH_Update( &HASHcontext,
3310 prefix->bv_val, prefix->bv_len );
3312 HASH_Update( &HASHcontext,
3313 &pre, sizeof( pre ) );
3314 HASH_Update( &HASHcontext,
3315 syntax->ssyn_oid, slen );
3316 HASH_Update( &HASHcontext,
3317 mr->smr_oid, mlen );
3318 HASH_Update( &HASHcontext,
3319 &value.bv_val[j], klen );
3320 HASH_Final( HASHdigest, &HASHcontext );
3322 ber_dupbv( &keys[nkeys++], &digest );
3325 free( value.bv_val );
3329 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3330 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3332 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3333 ber_dupbv( &value, &sa->sa_final );
3334 ldap_pvt_str2lower( value.bv_val );
3336 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3337 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3339 HASH_Init( &HASHcontext );
3340 if( prefix != NULL && prefix->bv_len > 0 ) {
3341 HASH_Update( &HASHcontext,
3342 prefix->bv_val, prefix->bv_len );
3344 HASH_Update( &HASHcontext,
3345 &pre, sizeof( pre ) );
3346 HASH_Update( &HASHcontext,
3347 syntax->ssyn_oid, slen );
3348 HASH_Update( &HASHcontext,
3349 mr->smr_oid, mlen );
3350 HASH_Update( &HASHcontext,
3351 &value.bv_val[value.bv_len-klen], klen );
3352 HASH_Final( HASHdigest, &HASHcontext );
3354 free( value.bv_val );
3355 ber_dupbv( &keys[nkeys++], &digest );
3359 keys[nkeys].bv_val = NULL;
3366 return LDAP_SUCCESS;
3370 numericStringValidate(
3376 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
3378 for(i=0; i < in->bv_len; i++) {
3379 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3380 return LDAP_INVALID_SYNTAX;
3384 return LDAP_SUCCESS;
3388 numericStringNormalize(
3391 struct berval *normalized )
3393 /* removal all spaces */
3396 assert( val->bv_len );
3398 normalized->bv_val = ch_malloc( val->bv_len + 1 );
3401 q = normalized->bv_val;
3404 if ( ASCII_SPACE( *p ) ) {
3405 /* Ignore whitespace */
3412 /* we should have copied no more then is in val */
3413 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3415 /* null terminate */
3418 normalized->bv_len = q - normalized->bv_val;
3420 if( normalized->bv_len == 0 ) {
3421 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
3422 normalized->bv_val[0] = ' ';
3423 normalized->bv_val[1] = '\0';
3424 normalized->bv_len = 1;
3427 return LDAP_SUCCESS;
3431 objectIdentifierFirstComponentMatch(
3436 struct berval *value,
3437 void *assertedValue )
3439 int rc = LDAP_SUCCESS;
3441 struct berval *asserted = (struct berval *) assertedValue;
3445 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3446 return LDAP_INVALID_SYNTAX;
3449 /* trim leading white space */
3450 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3454 /* grab next word */
3455 oid.bv_val = &value->bv_val[i];
3456 oid.bv_len = value->bv_len - i;
3457 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3462 /* insert attributeTypes, objectclass check here */
3463 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3464 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3467 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3468 MatchingRule *asserted_mr = mr_bvfind( asserted );
3469 MatchingRule *stored_mr = mr_bvfind( &oid );
3471 if( asserted_mr == NULL ) {
3472 rc = SLAPD_COMPARE_UNDEFINED;
3474 match = asserted_mr != stored_mr;
3477 } else if ( !strcmp( syntax->ssyn_oid,
3478 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3480 AttributeType *asserted_at = at_bvfind( asserted );
3481 AttributeType *stored_at = at_bvfind( &oid );
3483 if( asserted_at == NULL ) {
3484 rc = SLAPD_COMPARE_UNDEFINED;
3486 match = asserted_at != stored_at;
3489 } else if ( !strcmp( syntax->ssyn_oid,
3490 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3492 ObjectClass *asserted_oc = oc_bvfind( asserted );
3493 ObjectClass *stored_oc = oc_bvfind( &oid );
3495 if( asserted_oc == NULL ) {
3496 rc = SLAPD_COMPARE_UNDEFINED;
3498 match = asserted_oc != stored_oc;
3504 LDAP_LOG( CONFIG, ENTRY,
3505 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
3506 match, value->bv_val, asserted->bv_val );
3508 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3509 "%d\n\t\"%s\"\n\t\"%s\"\n",
3510 match, value->bv_val, asserted->bv_val );
3514 if( rc == LDAP_SUCCESS ) *matchp = match;
3524 struct berval *value,
3525 void *assertedValue )
3527 long lValue, lAssertedValue;
3529 /* safe to assume integers are NUL terminated? */
3530 lValue = strtoul(value->bv_val, NULL, 10);
3531 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3532 return LDAP_CONSTRAINT_VIOLATION;
3534 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3535 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3536 return LDAP_CONSTRAINT_VIOLATION;
3538 *matchp = (lValue & lAssertedValue);
3539 return LDAP_SUCCESS;
3548 struct berval *value,
3549 void *assertedValue )
3551 long lValue, lAssertedValue;
3553 /* safe to assume integers are NUL terminated? */
3554 lValue = strtoul(value->bv_val, NULL, 10);
3555 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3556 return LDAP_CONSTRAINT_VIOLATION;
3558 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3559 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3560 return LDAP_CONSTRAINT_VIOLATION;
3562 *matchp = (lValue | lAssertedValue);
3563 return LDAP_SUCCESS;
3567 #include <openssl/x509.h>
3568 #include <openssl/err.h>
3569 char digit[] = "0123456789";
3572 * Next function returns a string representation of a ASN1_INTEGER.
3573 * It works for unlimited lengths.
3576 static struct berval *
3577 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3582 /* We work backwards, make it fill from the end of buf */
3583 p = buf + sizeof(buf) - 1;
3586 if ( a == NULL || a->length == 0 ) {
3594 /* We want to preserve the original */
3595 copy = ch_malloc(n*sizeof(unsigned int));
3596 for (i = 0; i<n; i++) {
3597 copy[i] = a->data[i];
3601 * base indicates the index of the most significant
3602 * byte that might be nonzero. When it goes off the
3603 * end, we now there is nothing left to do.
3609 for (i = base; i<n; i++ ) {
3610 copy[i] += carry*256;
3611 carry = copy[i] % 10;
3616 * Way too large, we need to leave
3617 * room for sign if negative
3622 *--p = digit[carry];
3623 if (copy[base] == 0)
3629 if ( a->type == V_ASN1_NEG_INTEGER ) {
3633 return ber_str2bv( p, 0, 1, bv );
3637 * Given a certificate in DER format, extract the corresponding
3638 * assertion value for certificateExactMatch
3641 certificateExactConvert(
3643 struct berval * out )
3646 unsigned char *p = in->bv_val;
3647 struct berval serial;
3648 struct berval issuer_dn;
3650 xcert = d2i_X509(NULL, &p, in->bv_len);
3653 LDAP_LOG( CONFIG, ENTRY,
3654 "certificateExactConvert: error parsing cert: %s\n",
3655 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3657 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3658 "error parsing cert: %s\n",
3659 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3661 return LDAP_INVALID_SYNTAX;
3664 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3666 return LDAP_INVALID_SYNTAX;
3668 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn ) != LDAP_SUCCESS ) {
3670 ber_memfree(serial.bv_val);
3671 return LDAP_INVALID_SYNTAX;
3676 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3677 out->bv_val = ch_malloc(out->bv_len);
3679 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3681 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3683 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3684 p += issuer_dn.bv_len;
3688 LDAP_LOG( CONFIG, ARGS,
3689 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
3691 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3693 out->bv_val, NULL, NULL );
3696 ber_memfree(serial.bv_val);
3697 ber_memfree(issuer_dn.bv_val);
3699 return LDAP_SUCCESS;
3703 serial_and_issuer_parse(
3704 struct berval *assertion,
3705 struct berval *serial,
3706 struct berval *issuer_dn
3714 begin = assertion->bv_val;
3715 end = assertion->bv_val+assertion->bv_len-1;
3716 for (p=begin; p<=end && *p != '$'; p++)
3719 return LDAP_INVALID_SYNTAX;
3721 /* p now points at the $ sign, now use begin and end to delimit the
3723 while (ASCII_SPACE(*begin))
3726 while (ASCII_SPACE(*end))
3729 bv.bv_len = end-begin+1;
3731 ber_dupbv(serial, &bv);
3733 /* now extract the issuer, remember p was at the dollar sign */
3736 end = assertion->bv_val+assertion->bv_len-1;
3737 while (ASCII_SPACE(*begin))
3739 /* should we trim spaces at the end too? is it safe always? */
3741 bv.bv_len = end-begin+1;
3743 dnNormalize2( NULL, &bv, issuer_dn );
3746 return LDAP_SUCCESS;
3750 certificateExactMatch(
3755 struct berval *value,
3756 void *assertedValue )
3759 unsigned char *p = value->bv_val;
3760 struct berval serial;
3761 struct berval issuer_dn;
3762 struct berval asserted_serial;
3763 struct berval asserted_issuer_dn;
3766 xcert = d2i_X509(NULL, &p, value->bv_len);
3769 LDAP_LOG( CONFIG, ENTRY,
3770 "certificateExactMatch: error parsing cert: %s\n",
3771 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3773 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3774 "error parsing cert: %s\n",
3775 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3777 return LDAP_INVALID_SYNTAX;
3780 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3781 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
3785 serial_and_issuer_parse(assertedValue,
3787 &asserted_issuer_dn);
3792 slap_schema.si_syn_integer,
3793 slap_schema.si_mr_integerMatch,
3796 if ( ret == LDAP_SUCCESS ) {
3797 if ( *matchp == 0 ) {
3798 /* We need to normalize everything for dnMatch */
3802 slap_schema.si_syn_distinguishedName,
3803 slap_schema.si_mr_distinguishedNameMatch,
3805 &asserted_issuer_dn);
3810 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
3811 "%d\n\t\"%s $ %s\"\n",
3812 *matchp, serial.bv_val, issuer_dn.bv_val );
3813 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
3814 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3817 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3818 "%d\n\t\"%s $ %s\"\n",
3819 *matchp, serial.bv_val, issuer_dn.bv_val );
3820 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3821 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3825 ber_memfree(serial.bv_val);
3826 ber_memfree(issuer_dn.bv_val);
3827 ber_memfree(asserted_serial.bv_val);
3828 ber_memfree(asserted_issuer_dn.bv_val);
3834 * Index generation function
3835 * We just index the serials, in most scenarios the issuer DN is one of
3836 * a very small set of values.
3838 static int certificateExactIndexer(
3843 struct berval *prefix,
3851 struct berval serial;
3853 /* we should have at least one value at this point */
3854 assert( values != NULL && values[0].bv_val != NULL );
3856 for( i=0; values[i].bv_val != NULL; i++ ) {
3857 /* empty -- just count them */
3860 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3862 for( i=0; values[i].bv_val != NULL; i++ ) {
3863 p = values[i].bv_val;
3864 xcert = d2i_X509(NULL, &p, values[i].bv_len);
3867 LDAP_LOG( CONFIG, ENTRY,
3868 "certificateExactIndexer: error parsing cert: %s\n",
3869 ERR_error_string(ERR_get_error(),NULL), 0, 0);
3871 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3872 "error parsing cert: %s\n",
3873 ERR_error_string(ERR_get_error(),NULL),
3876 /* Do we leak keys on error? */
3877 return LDAP_INVALID_SYNTAX;
3880 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3882 integerNormalize( slap_schema.si_syn_integer,
3885 ber_memfree(serial.bv_val);
3887 LDAP_LOG( CONFIG, ENTRY,
3888 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
3890 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3897 keys[i].bv_val = NULL;
3899 return LDAP_SUCCESS;
3902 /* Index generation function */
3903 /* We think this is always called with a value in matching rule syntax */
3904 static int certificateExactFilter(
3909 struct berval *prefix,
3914 struct berval asserted_serial;
3916 serial_and_issuer_parse(assertValue,
3920 keys = ch_malloc( sizeof( struct berval ) * 2 );
3921 integerNormalize( syntax, &asserted_serial, &keys[0] );
3922 keys[1].bv_val = NULL;
3925 ber_memfree(asserted_serial.bv_val);
3926 return LDAP_SUCCESS;
3931 check_time_syntax (struct berval *val,
3935 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3936 static int mdays[2][12] = {
3937 /* non-leap years */
3938 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3940 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3943 int part, c, tzoffset, leapyear = 0 ;
3945 if( val->bv_len == 0 ) {
3946 return LDAP_INVALID_SYNTAX;
3949 p = (char *)val->bv_val;
3950 e = p + val->bv_len;
3952 /* Ignore initial whitespace */
3953 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3957 if (e - p < 13 - (2 * start)) {
3958 return LDAP_INVALID_SYNTAX;
3961 for (part = 0; part < 9; part++) {
3965 for (part = start; part < 7; part++) {
3967 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3974 return LDAP_INVALID_SYNTAX;
3976 if (c < 0 || c > 9) {
3977 return LDAP_INVALID_SYNTAX;
3983 return LDAP_INVALID_SYNTAX;
3985 if (c < 0 || c > 9) {
3986 return LDAP_INVALID_SYNTAX;
3991 if (part == 2 || part == 3) {
3994 if (parts[part] < 0) {
3995 return LDAP_INVALID_SYNTAX;
3997 if (parts[part] > ceiling[part]) {
3998 return LDAP_INVALID_SYNTAX;
4002 /* leapyear check for the Gregorian calendar (year>1581) */
4003 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
4004 ((parts[0] % 4 == 0) && (parts[1] == 0)))
4009 if (parts[3] > mdays[leapyear][parts[2]]) {
4010 return LDAP_INVALID_SYNTAX;
4015 tzoffset = 0; /* UTC */
4016 } else if (c != '+' && c != '-') {
4017 return LDAP_INVALID_SYNTAX;
4021 } else /* c == '+' */ {
4026 return LDAP_INVALID_SYNTAX;
4029 for (part = 7; part < 9; part++) {
4031 if (c < 0 || c > 9) {
4032 return LDAP_INVALID_SYNTAX;
4037 if (c < 0 || c > 9) {
4038 return LDAP_INVALID_SYNTAX;
4042 if (parts[part] < 0 || parts[part] > ceiling[part]) {
4043 return LDAP_INVALID_SYNTAX;
4048 /* Ignore trailing whitespace */
4049 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4053 return LDAP_INVALID_SYNTAX;
4056 switch ( tzoffset ) {
4057 case -1: /* negativ offset to UTC, ie west of Greenwich */
4058 parts[4] += parts[7];
4059 parts[5] += parts[8];
4060 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4064 c = mdays[leapyear][parts[2]];
4066 if (parts[part] > c) {
4067 parts[part] -= c + 1;
4072 case 1: /* positive offset to UTC, ie east of Greenwich */
4073 parts[4] -= parts[7];
4074 parts[5] -= parts[8];
4075 for (part = 6; --part > 0; ) {
4079 /* first arg to % needs to be non negativ */
4080 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4082 if (parts[part] < 0) {
4083 parts[part] += c + 1;
4088 case 0: /* already UTC */
4092 return LDAP_SUCCESS;
4095 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4100 struct berval *normalized )
4104 rc = check_time_syntax(val, 1, parts);
4105 if (rc != LDAP_SUCCESS) {
4109 normalized->bv_val = ch_malloc( 14 );
4110 if ( normalized->bv_val == NULL ) {
4111 return LBER_ERROR_MEMORY;
4114 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4115 parts[1], parts[2] + 1, parts[3] + 1,
4116 parts[4], parts[5], parts[6] );
4117 normalized->bv_len = 13;
4119 return LDAP_SUCCESS;
4123 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4131 return check_time_syntax(in, 1, parts);
4136 generalizedTimeValidate(
4142 return check_time_syntax(in, 0, parts);
4146 generalizedTimeNormalize(
4149 struct berval *normalized )
4153 rc = check_time_syntax(val, 0, parts);
4154 if (rc != LDAP_SUCCESS) {
4158 normalized->bv_val = ch_malloc( 16 );
4159 if ( normalized->bv_val == NULL ) {
4160 return LBER_ERROR_MEMORY;
4163 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4164 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4165 parts[4], parts[5], parts[6] );
4166 normalized->bv_len = 15;
4168 return LDAP_SUCCESS;
4172 nisNetgroupTripleValidate(
4174 struct berval *val )
4179 if ( val->bv_len == 0 ) {
4180 return LDAP_INVALID_SYNTAX;
4183 p = (char *)val->bv_val;
4184 e = p + val->bv_len;
4186 if ( *p != '(' /*')'*/ ) {
4187 return LDAP_INVALID_SYNTAX;
4190 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4194 return LDAP_INVALID_SYNTAX;
4197 } else if ( !AD_CHAR( *p ) ) {
4198 return LDAP_INVALID_SYNTAX;
4202 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4203 return LDAP_INVALID_SYNTAX;
4209 return LDAP_INVALID_SYNTAX;
4212 return LDAP_SUCCESS;
4216 bootParameterValidate(
4218 struct berval *val )
4222 if ( val->bv_len == 0 ) {
4223 return LDAP_INVALID_SYNTAX;
4226 p = (char *)val->bv_val;
4227 e = p + val->bv_len;
4230 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4231 if ( !AD_CHAR( *p ) ) {
4232 return LDAP_INVALID_SYNTAX;
4237 return LDAP_INVALID_SYNTAX;
4241 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4242 if ( !AD_CHAR( *p ) ) {
4243 return LDAP_INVALID_SYNTAX;
4248 return LDAP_INVALID_SYNTAX;
4252 for ( p++; p < e; p++ ) {
4253 if ( !SLAP_PRINTABLE( *p ) ) {
4254 return LDAP_INVALID_SYNTAX;
4258 return LDAP_SUCCESS;
4261 static struct syntax_defs_rec {
4263 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4264 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4266 slap_syntax_validate_func *sd_validate;
4267 slap_syntax_transform_func *sd_normalize;
4268 slap_syntax_transform_func *sd_pretty;
4269 #ifdef SLAPD_BINARY_CONVERSION
4270 slap_syntax_transform_func *sd_ber2str;
4271 slap_syntax_transform_func *sd_str2ber;
4274 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4275 X_BINARY X_NOT_H_R ")",
4276 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4277 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4278 0, NULL, NULL, NULL},
4279 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4280 0, NULL, NULL, NULL},
4281 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4283 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4284 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4286 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4287 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4288 0, bitStringValidate, bitStringNormalize, NULL },
4289 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4290 0, booleanValidate, NULL, NULL},
4291 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4292 X_BINARY X_NOT_H_R ")",
4293 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4294 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4295 X_BINARY X_NOT_H_R ")",
4296 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4297 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4298 X_BINARY X_NOT_H_R ")",
4299 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4300 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4301 0, countryStringValidate, IA5StringNormalize, NULL},
4302 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4303 0, dnValidate, dnNormalize2, dnPretty2},
4304 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4305 0, NULL, NULL, NULL},
4306 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4307 0, NULL, NULL, NULL},
4308 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4309 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4310 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4311 0, NULL, NULL, NULL},
4312 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4313 0, NULL, NULL, NULL},
4314 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4315 0, NULL, NULL, NULL},
4316 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4317 0, NULL, NULL, NULL},
4318 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4319 0, NULL, NULL, NULL},
4320 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4321 0, printablesStringValidate, telephoneNumberNormalize, NULL},
4322 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4323 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4324 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4325 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4326 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4327 0, NULL, NULL, NULL},
4328 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4329 0, IA5StringValidate, IA5StringNormalize, NULL},
4330 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4331 0, integerValidate, integerNormalize, NULL},
4332 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4333 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4334 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4335 0, NULL, NULL, NULL},
4336 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4337 0, NULL, NULL, NULL},
4338 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4339 0, NULL, NULL, NULL},
4340 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4341 0, NULL, NULL, NULL},
4342 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4343 0, NULL, NULL, NULL},
4344 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4345 0, nameUIDValidate, nameUIDNormalize, NULL},
4346 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4347 0, NULL, NULL, NULL},
4348 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4349 0, numericStringValidate, numericStringNormalize, NULL},
4350 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4351 0, NULL, NULL, NULL},
4352 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4353 0, oidValidate, NULL, NULL},
4354 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4355 0, IA5StringValidate, IA5StringNormalize, NULL},
4356 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4357 0, blobValidate, NULL, NULL},
4358 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4359 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4360 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4361 0, NULL, NULL, NULL},
4362 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4363 0, NULL, NULL, NULL},
4364 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4365 0, printableStringValidate, IA5StringNormalize, NULL},
4366 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4367 X_BINARY X_NOT_H_R ")",
4368 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4369 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4370 X_BINARY X_NOT_H_R ")",
4371 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4372 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4373 0, printableStringValidate, telephoneNumberNormalize, NULL},
4374 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4375 0, NULL, NULL, NULL},
4376 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4377 0, printablesStringValidate, IA5StringNormalize, NULL},
4378 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4379 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4380 0, utcTimeValidate, utcTimeNormalize, NULL},
4382 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4383 0, NULL, NULL, NULL},
4384 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4385 0, NULL, NULL, NULL},
4386 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4387 0, NULL, NULL, NULL},
4388 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4389 0, NULL, NULL, NULL},
4390 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4391 0, NULL, NULL, NULL},
4393 /* RFC 2307 NIS Syntaxes */
4394 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4395 0, nisNetgroupTripleValidate, NULL, NULL},
4396 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4397 0, bootParameterValidate, NULL, NULL},
4401 /* These OIDs are not published yet, but will be in the next
4402 * I-D for PKIX LDAPv3 schema as have been advanced by David
4403 * Chadwick in private mail.
4405 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4406 0, NULL, NULL, NULL},
4409 /* OpenLDAP Experimental Syntaxes */
4410 #ifdef SLAPD_ACI_ENABLED
4411 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4413 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4417 #ifdef SLAPD_AUTHPASSWD
4418 /* needs updating */
4419 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4420 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4423 /* OpenLDAP Void Syntax */
4424 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4425 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4426 {NULL, 0, NULL, NULL, NULL}
4430 * Other matching rules in X.520 that we do not use (yet):
4432 * 2.5.13.9 numericStringOrderingMatch
4433 * 2.5.13.18 octetStringOrderingMatch
4434 * 2.5.13.19 octetStringSubstringsMatch
4435 * 2.5.13.25 uTCTimeMatch
4436 * 2.5.13.26 uTCTimeOrderingMatch
4437 * 2.5.13.31 directoryStringFirstComponentMatch
4438 * 2.5.13.32 wordMatch
4439 * 2.5.13.33 keywordMatch
4440 * 2.5.13.35 certificateMatch
4441 * 2.5.13.36 certificatePairExactMatch
4442 * 2.5.13.37 certificatePairMatch
4443 * 2.5.13.38 certificateListExactMatch
4444 * 2.5.13.39 certificateListMatch
4445 * 2.5.13.40 algorithmIdentifierMatch
4446 * 2.5.13.41 storedPrefixMatch
4447 * 2.5.13.42 attributeCertificateMatch
4448 * 2.5.13.43 readerAndKeyIDMatch
4449 * 2.5.13.44 attributeIntegrityMatch
4451 static struct mrule_defs_rec {
4453 slap_mask_t mrd_usage;
4454 slap_mr_convert_func * mrd_convert;
4455 slap_mr_normalize_func * mrd_normalize;
4456 slap_mr_match_func * mrd_match;
4457 slap_mr_indexer_func * mrd_indexer;
4458 slap_mr_filter_func * mrd_filter;
4460 char * mrd_associated;
4463 * EQUALITY matching rules must be listed after associated APPROX
4464 * matching rules. So, we list all APPROX matching rules first.
4466 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4467 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4468 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4470 directoryStringApproxMatch,
4471 directoryStringApproxIndexer,
4472 directoryStringApproxFilter,
4475 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4476 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4477 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4479 IA5StringApproxMatch,
4480 IA5StringApproxIndexer,
4481 IA5StringApproxFilter,
4485 * Other matching rules
4488 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4489 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4490 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4492 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4495 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4496 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4497 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4499 dnMatch, dnIndexer, dnFilter,
4502 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4503 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4504 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4506 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4507 directoryStringApproxMatchOID },
4509 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4510 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4513 caseIgnoreOrderingMatch, NULL, NULL,
4516 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4517 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4518 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4520 caseExactIgnoreSubstringsMatch,
4521 caseExactIgnoreSubstringsIndexer,
4522 caseExactIgnoreSubstringsFilter,
4525 {"( 2.5.13.5 NAME 'caseExactMatch' "
4526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4527 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4529 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4530 directoryStringApproxMatchOID },
4532 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4533 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4536 caseExactOrderingMatch, NULL, NULL,
4539 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4540 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4541 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4543 caseExactIgnoreSubstringsMatch,
4544 caseExactIgnoreSubstringsIndexer,
4545 caseExactIgnoreSubstringsFilter,
4548 {"( 2.5.13.8 NAME 'numericStringMatch' "
4549 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4550 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4553 caseIgnoreIA5Indexer,
4554 caseIgnoreIA5Filter,
4557 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4559 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4561 caseIgnoreIA5SubstringsMatch,
4562 caseIgnoreIA5SubstringsIndexer,
4563 caseIgnoreIA5SubstringsFilter,
4566 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4567 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4568 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4570 caseIgnoreListMatch, NULL, NULL,
4573 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4574 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4575 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4577 caseIgnoreListSubstringsMatch, NULL, NULL,
4580 {"( 2.5.13.13 NAME 'booleanMatch' "
4581 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4582 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4584 booleanMatch, NULL, NULL,
4587 {"( 2.5.13.14 NAME 'integerMatch' "
4588 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4589 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4591 integerMatch, integerIndexer, integerFilter,
4594 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4595 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4598 integerOrderingMatch, NULL, NULL,
4601 {"( 2.5.13.16 NAME 'bitStringMatch' "
4602 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4603 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4605 bitStringMatch, bitStringIndexer, bitStringFilter,
4608 {"( 2.5.13.17 NAME 'octetStringMatch' "
4609 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4610 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4612 octetStringMatch, octetStringIndexer, octetStringFilter,
4615 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4616 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4617 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4619 telephoneNumberMatch,
4620 telephoneNumberIndexer,
4621 telephoneNumberFilter,
4624 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4625 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4626 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4628 telephoneNumberSubstringsMatch,
4629 telephoneNumberSubstringsIndexer,
4630 telephoneNumberSubstringsFilter,
4633 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4634 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4635 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4640 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4641 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4642 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4644 uniqueMemberMatch, NULL, NULL,
4647 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4648 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4649 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4651 protocolInformationMatch, NULL, NULL,
4654 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4655 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4656 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4658 generalizedTimeMatch, NULL, NULL,
4661 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4662 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4665 generalizedTimeOrderingMatch, NULL, NULL,
4668 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4669 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4670 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4672 integerFirstComponentMatch, NULL, NULL,
4675 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4676 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4677 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4679 objectIdentifierFirstComponentMatch, NULL, NULL,
4683 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4684 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4685 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4686 certificateExactConvert, NULL,
4687 certificateExactMatch,
4688 certificateExactIndexer, certificateExactFilter,
4692 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4693 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4694 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4696 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4697 IA5StringApproxMatchOID },
4699 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4700 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4701 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4703 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4704 IA5StringApproxMatchOID },
4706 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4707 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4710 caseIgnoreIA5SubstringsMatch,
4711 caseIgnoreIA5SubstringsIndexer,
4712 caseIgnoreIA5SubstringsFilter,
4715 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4716 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4719 caseExactIA5SubstringsMatch,
4720 caseExactIA5SubstringsIndexer,
4721 caseExactIA5SubstringsFilter,
4724 #ifdef SLAPD_AUTHPASSWD
4725 /* needs updating */
4726 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4730 authPasswordMatch, NULL, NULL,
4734 #ifdef SLAPD_ACI_ENABLED
4735 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4736 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4739 OpenLDAPaciMatch, NULL, NULL,
4743 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4744 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4747 integerBitAndMatch, NULL, NULL,
4750 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4751 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4754 integerBitOrMatch, NULL, NULL,
4757 {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4761 slap_schema_init( void )
4766 /* we should only be called once (from main) */
4767 assert( schema_init_done == 0 );
4769 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4770 res = register_syntax( syntax_defs[i].sd_desc,
4771 syntax_defs[i].sd_flags,
4772 syntax_defs[i].sd_validate,
4773 syntax_defs[i].sd_normalize,
4774 syntax_defs[i].sd_pretty
4775 #ifdef SLAPD_BINARY_CONVERSION
4777 syntax_defs[i].sd_ber2str,
4778 syntax_defs[i].sd_str2ber
4783 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4784 syntax_defs[i].sd_desc );
4789 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4790 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4792 "slap_schema_init: Ingoring unusable matching rule %s\n",
4793 mrule_defs[i].mrd_desc );
4797 res = register_matching_rule(
4798 mrule_defs[i].mrd_desc,
4799 mrule_defs[i].mrd_usage,
4800 mrule_defs[i].mrd_convert,
4801 mrule_defs[i].mrd_normalize,
4802 mrule_defs[i].mrd_match,
4803 mrule_defs[i].mrd_indexer,
4804 mrule_defs[i].mrd_filter,
4805 mrule_defs[i].mrd_associated );
4809 "slap_schema_init: Error registering matching rule %s\n",
4810 mrule_defs[i].mrd_desc );
4815 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4816 *mr_ptr[i].mr = mr_find( mr_ptr[i].oid );
4818 res = slap_schema_load();
4819 schema_init_done = 1;
4824 schema_destroy( void )
4830 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4831 *mr_ptr[i].mr = NULL;