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 /* no value allowed */
314 return LDAP_INVALID_SYNTAX;
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),
780 NULL, LDAP_UTF8_APPROX );
781 if( assertv == NULL ) {
787 /* Isolate how many words there are */
788 for ( c = nval->bv_val, count = 1; *c; c++ ) {
789 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
790 if ( c == NULL ) break;
795 /* Get a phonetic copy of each word */
796 words = (char **)ch_malloc( count * sizeof(char *) );
797 values = (char **)ch_malloc( count * sizeof(char *) );
798 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
800 values[i] = phonetic(c);
803 /* Work through the asserted value's words, to see if at least some
804 of the words are there, in the same order. */
806 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
807 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
812 #if defined(SLAPD_APPROX_INITIALS)
813 else if( len == 1 ) {
814 /* Single letter words need to at least match one word's initial */
815 for( i=nextavail; i<count; i++ )
816 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
823 /* Isolate the next word in the asserted value and phonetic it */
824 assertv->bv_val[nextchunk+len] = '\0';
825 val = phonetic( assertv->bv_val + nextchunk );
827 /* See if this phonetic chunk is in the remaining words of *value */
828 for( i=nextavail; i<count; i++ ){
829 if( !strcmp( val, values[i] ) ){
837 /* This chunk in the asserted value was NOT within the *value. */
843 /* Go on to the next word in the asserted value */
847 /* If some of the words were seen, call it a match */
848 if( nextavail > 0 ) {
856 ber_bvfree( assertv );
857 for( i=0; i<count; i++ ) {
858 ch_free( values[i] );
873 struct berval *prefix,
878 int i,j, len, wordcount, keycount=0;
879 struct berval *newkeys;
882 for( j=0; values[j].bv_val != NULL; j++ ) {
883 struct berval val = { 0, NULL };
884 /* Yes, this is necessary */
885 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
886 assert( val.bv_val != NULL );
888 /* Isolate how many words there are. There will be a key for each */
889 for( wordcount = 0, c = val.bv_val; *c; c++) {
890 len = strcspn(c, SLAPD_APPROX_DELIMITER);
891 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
893 if (*c == '\0') break;
897 /* Allocate/increase storage to account for new keys */
898 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
899 * sizeof(struct berval) );
900 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
901 if( keys ) ch_free( keys );
904 /* Get a phonetic copy of each word */
905 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
907 if( len < SLAPD_APPROX_WORDLEN ) continue;
908 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
913 ber_memfree( val.bv_val );
915 keys[keycount].bv_val = NULL;
927 struct berval *prefix,
936 /* Yes, this is necessary */
937 val = UTF8bvnormalize( ((struct berval *)assertValue),
938 NULL, LDAP_UTF8_APPROX );
939 if( val == NULL || val->bv_val == NULL ) {
940 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
941 keys[0].bv_val = NULL;
947 /* Isolate how many words there are. There will be a key for each */
948 for( count = 0,c = val->bv_val; *c; c++) {
949 len = strcspn(c, SLAPD_APPROX_DELIMITER);
950 if( len >= SLAPD_APPROX_WORDLEN ) count++;
952 if (*c == '\0') break;
956 /* Allocate storage for new keys */
957 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
959 /* Get a phonetic copy of each word */
960 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
962 if( len < SLAPD_APPROX_WORDLEN ) continue;
963 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
969 keys[count].bv_val = NULL;
977 /* No other form of Approximate Matching is defined */
985 struct berval *value,
986 void *assertedValue )
988 char *vapprox, *avapprox;
991 /* Yes, this is necessary */
992 s = UTF8normalize( value, UTF8_NOCASEFOLD );
998 /* Yes, this is necessary */
999 t = UTF8normalize( ((struct berval *)assertedValue),
1004 return LDAP_SUCCESS;
1007 vapprox = phonetic( strip8bitChars( s ) );
1008 avapprox = phonetic( strip8bitChars( t ) );
1013 *matchp = strcmp( vapprox, avapprox );
1016 ch_free( avapprox );
1018 return LDAP_SUCCESS;
1027 struct berval *prefix,
1035 for( i=0; values[i].bv_val != NULL; i++ ) {
1036 /* empty - just count them */
1039 /* we should have at least one value at this point */
1042 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1044 /* Copy each value and run it through phonetic() */
1045 for( i=0; values[i].bv_val != NULL; i++ ) {
1046 /* Yes, this is necessary */
1047 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1049 /* strip 8-bit chars and run through phonetic() */
1050 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1053 keys[i].bv_val = NULL;
1056 return LDAP_SUCCESS;
1066 struct berval *prefix,
1073 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1075 /* Yes, this is necessary */
1076 s = UTF8normalize( ((struct berval *)assertValue),
1081 /* strip 8-bit chars and run through phonetic() */
1082 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1088 return LDAP_SUCCESS;
1099 struct berval *value,
1100 void *assertedValue )
1102 *matchp = UTF8bvnormcmp( value,
1103 (struct berval *) assertedValue,
1104 LDAP_UTF8_NOCASEFOLD );
1105 return LDAP_SUCCESS;
1109 caseExactIgnoreSubstringsMatch(
1114 struct berval *value,
1115 void *assertedValue )
1118 SubstringsAssertion *sub = NULL;
1119 struct berval left = { 0, NULL };
1125 casefold = ( mr != caseExactSubstringsMatchingRule )
1126 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1128 if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1134 sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1140 /* Add up asserted input length */
1141 if( sub->sa_initial.bv_val ) {
1142 inlen += sub->sa_initial.bv_len;
1145 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1146 inlen += sub->sa_any[i].bv_len;
1149 if( sub->sa_final.bv_val ) {
1150 inlen += sub->sa_final.bv_len;
1153 if( sub->sa_initial.bv_val ) {
1154 if( inlen > left.bv_len ) {
1159 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1160 sub->sa_initial.bv_len );
1166 left.bv_val += sub->sa_initial.bv_len;
1167 left.bv_len -= sub->sa_initial.bv_len;
1168 inlen -= sub->sa_initial.bv_len;
1171 if( sub->sa_final.bv_val ) {
1172 if( inlen > left.bv_len ) {
1177 match = memcmp( sub->sa_final.bv_val,
1178 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1179 sub->sa_final.bv_len );
1185 left.bv_len -= sub->sa_final.bv_len;
1186 inlen -= sub->sa_final.bv_len;
1190 for(i=0; sub->sa_any[i].bv_val; i++) {
1195 if( inlen > left.bv_len ) {
1196 /* not enough length */
1201 if( sub->sa_any[i].bv_len == 0 ) {
1205 p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1211 idx = p - left.bv_val;
1213 if( idx >= left.bv_len ) {
1214 /* this shouldn't happen */
1216 if ( sub->sa_final.bv_val )
1217 ch_free( sub->sa_final.bv_val );
1219 ber_bvarray_free( sub->sa_any );
1220 if ( sub->sa_initial.bv_val )
1221 ch_free( sub->sa_initial.bv_val );
1229 if( sub->sa_any[i].bv_len > left.bv_len ) {
1230 /* not enough left */
1235 match = memcmp( left.bv_val,
1236 sub->sa_any[i].bv_val,
1237 sub->sa_any[i].bv_len );
1245 left.bv_val += sub->sa_any[i].bv_len;
1246 left.bv_len -= sub->sa_any[i].bv_len;
1247 inlen -= sub->sa_any[i].bv_len;
1254 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1255 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1256 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1260 return LDAP_SUCCESS;
1263 /* Index generation function */
1264 static int caseExactIgnoreIndexer(
1269 struct berval *prefix,
1277 HASH_CONTEXT HASHcontext;
1278 unsigned char HASHdigest[HASH_BYTES];
1279 struct berval digest;
1280 digest.bv_val = HASHdigest;
1281 digest.bv_len = sizeof(HASHdigest);
1283 for( i=0; values[i].bv_val != NULL; i++ ) {
1284 /* empty - just count them */
1287 /* we should have at least one value at this point */
1290 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1292 slen = syntax->ssyn_oidlen;
1293 mlen = mr->smr_oidlen;
1295 casefold = ( mr != caseExactMatchingRule )
1296 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1298 for( i=0; values[i].bv_val != NULL; i++ ) {
1299 struct berval value;
1300 UTF8bvnormalize( &values[i], &value, casefold );
1302 HASH_Init( &HASHcontext );
1303 if( prefix != NULL && prefix->bv_len > 0 ) {
1304 HASH_Update( &HASHcontext,
1305 prefix->bv_val, prefix->bv_len );
1307 HASH_Update( &HASHcontext,
1308 syntax->ssyn_oid, slen );
1309 HASH_Update( &HASHcontext,
1310 mr->smr_oid, mlen );
1311 HASH_Update( &HASHcontext,
1312 value.bv_val, value.bv_len );
1313 HASH_Final( HASHdigest, &HASHcontext );
1315 free( value.bv_val );
1317 ber_dupbv( &keys[i], &digest );
1320 keys[i].bv_val = NULL;
1322 return LDAP_SUCCESS;
1325 /* Index generation function */
1326 static int caseExactIgnoreFilter(
1331 struct berval *prefix,
1338 HASH_CONTEXT HASHcontext;
1339 unsigned char HASHdigest[HASH_BYTES];
1340 struct berval value = { 0, NULL };
1341 struct berval digest;
1343 digest.bv_val = HASHdigest;
1344 digest.bv_len = sizeof(HASHdigest);
1346 slen = syntax->ssyn_oidlen;
1347 mlen = mr->smr_oidlen;
1349 casefold = ( mr != caseExactMatchingRule )
1350 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1352 UTF8bvnormalize( (struct berval *) assertValue, &value, casefold );
1353 /* This usually happens if filter contains bad UTF8 */
1354 if( value.bv_val == NULL ) {
1355 keys = ch_malloc( sizeof( struct berval ) );
1356 keys[0].bv_val = NULL;
1357 return LDAP_SUCCESS;
1360 keys = ch_malloc( sizeof( struct berval ) * 2 );
1362 HASH_Init( &HASHcontext );
1363 if( prefix != NULL && prefix->bv_len > 0 ) {
1364 HASH_Update( &HASHcontext,
1365 prefix->bv_val, prefix->bv_len );
1367 HASH_Update( &HASHcontext,
1368 syntax->ssyn_oid, slen );
1369 HASH_Update( &HASHcontext,
1370 mr->smr_oid, mlen );
1371 HASH_Update( &HASHcontext,
1372 value.bv_val, value.bv_len );
1373 HASH_Final( HASHdigest, &HASHcontext );
1375 ber_dupbv( keys, &digest );
1376 keys[1].bv_val = NULL;
1378 free( value.bv_val );
1381 return LDAP_SUCCESS;
1384 /* Substrings Index generation function */
1385 static int caseExactIgnoreSubstringsIndexer(
1390 struct berval *prefix,
1400 HASH_CONTEXT HASHcontext;
1401 unsigned char HASHdigest[HASH_BYTES];
1402 struct berval digest;
1403 digest.bv_val = HASHdigest;
1404 digest.bv_len = sizeof(HASHdigest);
1408 for( i=0; values[i].bv_val != NULL; i++ ) {
1409 /* empty - just count them */
1412 /* we should have at least one value at this point */
1415 casefold = ( mr != caseExactSubstringsMatchingRule )
1416 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1418 nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1419 for( i=0; values[i].bv_val != NULL; i++ ) {
1420 UTF8bvnormalize( &values[i], &nvalues[i], casefold );
1422 nvalues[i].bv_val = NULL;
1425 for( i=0; values[i].bv_val != NULL; i++ ) {
1426 /* count number of indices to generate */
1427 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1431 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1432 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1433 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1434 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1436 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1440 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1441 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1442 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1446 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1447 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1448 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1449 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1451 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1457 /* no keys to generate */
1459 ber_bvarray_free( nvalues );
1460 return LDAP_SUCCESS;
1463 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1465 slen = syntax->ssyn_oidlen;
1466 mlen = mr->smr_oidlen;
1469 for( i=0; values[i].bv_val != NULL; i++ ) {
1472 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1474 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1475 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1477 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1478 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1480 for( j=0; j<max; j++ ) {
1481 HASH_Init( &HASHcontext );
1482 if( prefix != NULL && prefix->bv_len > 0 ) {
1483 HASH_Update( &HASHcontext,
1484 prefix->bv_val, prefix->bv_len );
1487 HASH_Update( &HASHcontext,
1488 &pre, sizeof( pre ) );
1489 HASH_Update( &HASHcontext,
1490 syntax->ssyn_oid, slen );
1491 HASH_Update( &HASHcontext,
1492 mr->smr_oid, mlen );
1493 HASH_Update( &HASHcontext,
1494 &values[i].bv_val[j],
1495 SLAP_INDEX_SUBSTR_MAXLEN );
1496 HASH_Final( HASHdigest, &HASHcontext );
1498 ber_dupbv( &keys[nkeys++], &digest );
1502 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1503 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1505 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1508 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1509 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1510 HASH_Init( &HASHcontext );
1511 if( prefix != NULL && prefix->bv_len > 0 ) {
1512 HASH_Update( &HASHcontext,
1513 prefix->bv_val, prefix->bv_len );
1515 HASH_Update( &HASHcontext,
1516 &pre, sizeof( pre ) );
1517 HASH_Update( &HASHcontext,
1518 syntax->ssyn_oid, slen );
1519 HASH_Update( &HASHcontext,
1520 mr->smr_oid, mlen );
1521 HASH_Update( &HASHcontext,
1522 values[i].bv_val, j );
1523 HASH_Final( HASHdigest, &HASHcontext );
1525 ber_dupbv( &keys[nkeys++], &digest );
1528 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1529 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1530 HASH_Init( &HASHcontext );
1531 if( prefix != NULL && prefix->bv_len > 0 ) {
1532 HASH_Update( &HASHcontext,
1533 prefix->bv_val, prefix->bv_len );
1535 HASH_Update( &HASHcontext,
1536 &pre, sizeof( pre ) );
1537 HASH_Update( &HASHcontext,
1538 syntax->ssyn_oid, slen );
1539 HASH_Update( &HASHcontext,
1540 mr->smr_oid, mlen );
1541 HASH_Update( &HASHcontext,
1542 &values[i].bv_val[values[i].bv_len-j], j );
1543 HASH_Final( HASHdigest, &HASHcontext );
1545 ber_dupbv( &keys[nkeys++], &digest );
1553 keys[nkeys].bv_val = NULL;
1560 ber_bvarray_free( nvalues );
1562 return LDAP_SUCCESS;
1565 static int caseExactIgnoreSubstringsFilter(
1570 struct berval *prefix,
1574 SubstringsAssertion *sa;
1577 ber_len_t nkeys = 0;
1578 size_t slen, mlen, klen;
1580 HASH_CONTEXT HASHcontext;
1581 unsigned char HASHdigest[HASH_BYTES];
1582 struct berval *value;
1583 struct berval digest;
1585 casefold = ( mr != caseExactSubstringsMatchingRule )
1586 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1588 sa = UTF8SubstringsassertionNormalize( assertValue, casefold );
1591 return LDAP_SUCCESS;
1594 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1595 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1600 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1602 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1603 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1604 /* don't bother accounting for stepping */
1605 nkeys += sa->sa_any[i].bv_len -
1606 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1611 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1612 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1618 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1619 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1620 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1623 return LDAP_SUCCESS;
1626 digest.bv_val = HASHdigest;
1627 digest.bv_len = sizeof(HASHdigest);
1629 slen = syntax->ssyn_oidlen;
1630 mlen = mr->smr_oidlen;
1632 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1635 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1636 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1638 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1639 value = &sa->sa_initial;
1641 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1642 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1644 HASH_Init( &HASHcontext );
1645 if( prefix != NULL && prefix->bv_len > 0 ) {
1646 HASH_Update( &HASHcontext,
1647 prefix->bv_val, prefix->bv_len );
1649 HASH_Update( &HASHcontext,
1650 &pre, sizeof( pre ) );
1651 HASH_Update( &HASHcontext,
1652 syntax->ssyn_oid, slen );
1653 HASH_Update( &HASHcontext,
1654 mr->smr_oid, mlen );
1655 HASH_Update( &HASHcontext,
1656 value->bv_val, klen );
1657 HASH_Final( HASHdigest, &HASHcontext );
1659 ber_dupbv( &keys[nkeys++], &digest );
1662 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1664 pre = SLAP_INDEX_SUBSTR_PREFIX;
1665 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1667 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1668 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1672 value = &sa->sa_any[i];
1675 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1676 j += SLAP_INDEX_SUBSTR_STEP )
1678 HASH_Init( &HASHcontext );
1679 if( prefix != NULL && prefix->bv_len > 0 ) {
1680 HASH_Update( &HASHcontext,
1681 prefix->bv_val, prefix->bv_len );
1683 HASH_Update( &HASHcontext,
1684 &pre, sizeof( pre ) );
1685 HASH_Update( &HASHcontext,
1686 syntax->ssyn_oid, slen );
1687 HASH_Update( &HASHcontext,
1688 mr->smr_oid, mlen );
1689 HASH_Update( &HASHcontext,
1690 &value->bv_val[j], klen );
1691 HASH_Final( HASHdigest, &HASHcontext );
1693 ber_dupbv( &keys[nkeys++], &digest );
1699 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1700 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1702 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1703 value = &sa->sa_final;
1705 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1706 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1708 HASH_Init( &HASHcontext );
1709 if( prefix != NULL && prefix->bv_len > 0 ) {
1710 HASH_Update( &HASHcontext,
1711 prefix->bv_val, prefix->bv_len );
1713 HASH_Update( &HASHcontext,
1714 &pre, sizeof( pre ) );
1715 HASH_Update( &HASHcontext,
1716 syntax->ssyn_oid, slen );
1717 HASH_Update( &HASHcontext,
1718 mr->smr_oid, mlen );
1719 HASH_Update( &HASHcontext,
1720 &value->bv_val[value->bv_len-klen], klen );
1721 HASH_Final( HASHdigest, &HASHcontext );
1723 ber_dupbv( &keys[nkeys++], &digest );
1727 keys[nkeys].bv_val = NULL;
1733 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1734 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1735 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1738 return LDAP_SUCCESS;
1747 struct berval *value,
1748 void *assertedValue )
1750 *matchp = UTF8bvnormcmp( value,
1751 (struct berval *) assertedValue,
1752 LDAP_UTF8_CASEFOLD );
1753 return LDAP_SUCCESS;
1756 /* Remove all spaces and '-' characters */
1758 telephoneNumberNormalize(
1761 struct berval *normalized )
1765 /* validator should have refused an empty string */
1766 assert( val->bv_len );
1768 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1770 for( p = val->bv_val; *p; p++ ) {
1771 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1777 normalized->bv_len = q - normalized->bv_val;
1779 if( normalized->bv_len == 0 ) {
1780 free( normalized->bv_val );
1781 return LDAP_INVALID_SYNTAX;
1784 return LDAP_SUCCESS;
1790 struct berval *val )
1794 if( val->bv_len == 0 ) {
1795 /* disallow empty strings */
1796 return LDAP_INVALID_SYNTAX;
1799 if( OID_LEADCHAR(val->bv_val[0]) ) {
1801 for(i=1; i < val->bv_len; i++) {
1802 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1803 if( dot++ ) return 1;
1804 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1807 return LDAP_INVALID_SYNTAX;
1811 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1813 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1814 for(i=1; i < val->bv_len; i++) {
1815 if( !DESC_CHAR(val->bv_val[i] ) ) {
1816 return LDAP_INVALID_SYNTAX;
1820 return LDAP_SUCCESS;
1823 return LDAP_INVALID_SYNTAX;
1832 struct berval *value,
1833 void *assertedValue )
1836 int vsign = 1, avsign = 1; /* default sign = '+' */
1837 struct berval *asserted;
1838 ber_len_t vlen, avlen;
1841 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1843 vlen = value->bv_len;
1844 if( mr == integerFirstComponentMatchingRule ) {
1845 char *tmp = memchr( v, '$', vlen );
1848 while( vlen && ASCII_SPACE( v[vlen-1] ))
1851 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) /* ANSI 2.2.1 */
1857 /* Do the same with the *assertedValue number */
1858 asserted = (struct berval *) assertedValue;
1859 av = asserted->bv_val;
1860 avlen = asserted->bv_len;
1861 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1867 match = vsign - avsign;
1869 match = (vlen != avlen
1870 ? ( vlen < avlen ? -1 : 1 )
1871 : memcmp( v, av, vlen ));
1877 return LDAP_SUCCESS;
1883 struct berval *val )
1887 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1889 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1890 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1891 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1892 return LDAP_INVALID_SYNTAX;
1895 for( i=1; i < val->bv_len; i++ ) {
1896 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1899 return LDAP_SUCCESS;
1906 struct berval *normalized )
1916 /* Ignore leading spaces */
1917 while ( len && ( *p == ' ' )) {
1924 negative = ( *p == '-' );
1925 if(( *p == '-' ) || ( *p == '+' )) {
1931 /* Ignore leading zeros */
1932 while ( len && ( *p == '0' )) {
1937 /* If there are no non-zero digits left, the number is zero, otherwise
1938 allocate space for the number and copy it into the buffer */
1940 normalized->bv_val = ch_strdup("0");
1941 normalized->bv_len = 1;
1944 normalized->bv_len = len+negative;
1945 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1947 normalized->bv_val[0] = '-';
1949 AC_MEMCPY( normalized->bv_val + negative, p, len );
1950 normalized->bv_val[len+negative] = '\0';
1953 return LDAP_SUCCESS;
1956 /* Index generation function */
1957 static int integerIndexer(
1962 struct berval *prefix,
1969 HASH_CONTEXT HASHcontext;
1970 unsigned char HASHdigest[HASH_BYTES];
1971 struct berval digest;
1972 digest.bv_val = HASHdigest;
1973 digest.bv_len = sizeof(HASHdigest);
1975 for( i=0; values[i].bv_val != NULL; i++ ) {
1976 /* empty - just count them */
1979 /* we should have at least one value at this point */
1982 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1984 slen = syntax->ssyn_oidlen;
1985 mlen = mr->smr_oidlen;
1987 for( i=0; values[i].bv_val != NULL; i++ ) {
1989 integerNormalize( syntax, &values[i], &norm );
1991 HASH_Init( &HASHcontext );
1992 if( prefix != NULL && prefix->bv_len > 0 ) {
1993 HASH_Update( &HASHcontext,
1994 prefix->bv_val, prefix->bv_len );
1996 HASH_Update( &HASHcontext,
1997 syntax->ssyn_oid, slen );
1998 HASH_Update( &HASHcontext,
1999 mr->smr_oid, mlen );
2000 HASH_Update( &HASHcontext,
2001 norm.bv_val, norm.bv_len );
2002 HASH_Final( HASHdigest, &HASHcontext );
2004 ber_dupbv( &keys[i], &digest );
2005 ch_free( norm.bv_val );
2008 keys[i].bv_val = NULL;
2010 return LDAP_SUCCESS;
2013 /* Index generation function */
2014 static int integerFilter(
2019 struct berval *prefix,
2025 HASH_CONTEXT HASHcontext;
2026 unsigned char HASHdigest[HASH_BYTES];
2028 struct berval digest;
2029 digest.bv_val = HASHdigest;
2030 digest.bv_len = sizeof(HASHdigest);
2032 slen = syntax->ssyn_oidlen;
2033 mlen = mr->smr_oidlen;
2035 integerNormalize( syntax, assertValue, &norm );
2037 keys = ch_malloc( sizeof( struct berval ) * 2 );
2039 HASH_Init( &HASHcontext );
2040 if( prefix != NULL && prefix->bv_len > 0 ) {
2041 HASH_Update( &HASHcontext,
2042 prefix->bv_val, prefix->bv_len );
2044 HASH_Update( &HASHcontext,
2045 syntax->ssyn_oid, slen );
2046 HASH_Update( &HASHcontext,
2047 mr->smr_oid, mlen );
2048 HASH_Update( &HASHcontext,
2049 norm.bv_val, norm.bv_len );
2050 HASH_Final( HASHdigest, &HASHcontext );
2052 ber_dupbv( &keys[0], &digest );
2053 keys[1].bv_val = NULL;
2054 ch_free( norm.bv_val );
2057 return LDAP_SUCCESS;
2062 countryStringValidate(
2064 struct berval *val )
2066 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2068 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2069 return LDAP_INVALID_SYNTAX;
2071 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2072 return LDAP_INVALID_SYNTAX;
2075 return LDAP_SUCCESS;
2079 printableStringValidate(
2081 struct berval *val )
2085 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2087 for(i=0; i < val->bv_len; i++) {
2088 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2089 return LDAP_INVALID_SYNTAX;
2093 return LDAP_SUCCESS;
2097 printablesStringValidate(
2099 struct berval *val )
2103 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2105 for(i=0,len=0; i < val->bv_len; i++) {
2106 int c = val->bv_val[i];
2110 return LDAP_INVALID_SYNTAX;
2114 } else if ( SLAP_PRINTABLE(c) ) {
2117 return LDAP_INVALID_SYNTAX;
2121 if( len == 0 ) LDAP_INVALID_SYNTAX;
2123 return LDAP_SUCCESS;
2129 struct berval *val )
2133 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2135 for(i=0; i < val->bv_len; i++) {
2136 if( !LDAP_ASCII(val->bv_val[i]) ) {
2137 return LDAP_INVALID_SYNTAX;
2141 return LDAP_SUCCESS;
2148 struct berval *normalized )
2152 assert( val->bv_len );
2156 /* Ignore initial whitespace */
2157 while ( ASCII_SPACE( *p ) ) {
2161 normalized->bv_val = ch_strdup( p );
2162 p = q = normalized->bv_val;
2165 if ( ASCII_SPACE( *p ) ) {
2168 /* Ignore the extra whitespace */
2169 while ( ASCII_SPACE( *p ) ) {
2177 assert( normalized->bv_val <= p );
2181 * If the string ended in space, backup the pointer one
2182 * position. One is enough because the above loop collapsed
2183 * all whitespace to a single space.
2186 if ( ASCII_SPACE( q[-1] ) ) {
2190 /* null terminate */
2193 normalized->bv_len = q - normalized->bv_val;
2195 if( normalized->bv_len == 0 ) {
2196 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
2197 normalized->bv_val[0] = ' ';
2198 normalized->bv_val[1] = '\0';
2199 normalized->bv_len = 1;
2202 return LDAP_SUCCESS;
2211 struct berval *value,
2212 void *assertedValue )
2214 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2217 match = strncmp( value->bv_val,
2218 ((struct berval *) assertedValue)->bv_val,
2223 return LDAP_SUCCESS;
2227 caseExactIA5SubstringsMatch(
2232 struct berval *value,
2233 void *assertedValue )
2236 SubstringsAssertion *sub = assertedValue;
2237 struct berval left = *value;
2241 /* Add up asserted input length */
2242 if( sub->sa_initial.bv_val ) {
2243 inlen += sub->sa_initial.bv_len;
2246 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2247 inlen += sub->sa_any[i].bv_len;
2250 if( sub->sa_final.bv_val ) {
2251 inlen += sub->sa_final.bv_len;
2254 if( sub->sa_initial.bv_val ) {
2255 if( inlen > left.bv_len ) {
2260 match = strncmp( sub->sa_initial.bv_val, left.bv_val,
2261 sub->sa_initial.bv_len );
2267 left.bv_val += sub->sa_initial.bv_len;
2268 left.bv_len -= sub->sa_initial.bv_len;
2269 inlen -= sub->sa_initial.bv_len;
2272 if( sub->sa_final.bv_val ) {
2273 if( inlen > left.bv_len ) {
2278 match = strncmp( sub->sa_final.bv_val,
2279 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2280 sub->sa_final.bv_len );
2286 left.bv_len -= sub->sa_final.bv_len;
2287 inlen -= sub->sa_final.bv_len;
2291 for(i=0; sub->sa_any[i].bv_val; i++) {
2296 if( inlen > left.bv_len ) {
2297 /* not enough length */
2302 if( sub->sa_any[i].bv_len == 0 ) {
2306 p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
2313 idx = p - left.bv_val;
2315 if( idx >= left.bv_len ) {
2316 /* this shouldn't happen */
2323 if( sub->sa_any[i].bv_len > left.bv_len ) {
2324 /* not enough left */
2329 match = strncmp( left.bv_val,
2330 sub->sa_any[i].bv_val,
2331 sub->sa_any[i].bv_len );
2339 left.bv_val += sub->sa_any[i].bv_len;
2340 left.bv_len -= sub->sa_any[i].bv_len;
2341 inlen -= sub->sa_any[i].bv_len;
2347 return LDAP_SUCCESS;
2350 /* Index generation function */
2351 static int caseExactIA5Indexer(
2356 struct berval *prefix,
2363 HASH_CONTEXT HASHcontext;
2364 unsigned char HASHdigest[HASH_BYTES];
2365 struct berval digest;
2366 digest.bv_val = HASHdigest;
2367 digest.bv_len = sizeof(HASHdigest);
2369 for( i=0; values[i].bv_val != NULL; i++ ) {
2370 /* empty - just count them */
2373 /* we should have at least one value at this point */
2376 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2378 slen = syntax->ssyn_oidlen;
2379 mlen = mr->smr_oidlen;
2381 for( i=0; values[i].bv_val != NULL; i++ ) {
2382 struct berval *value = &values[i];
2384 HASH_Init( &HASHcontext );
2385 if( prefix != NULL && prefix->bv_len > 0 ) {
2386 HASH_Update( &HASHcontext,
2387 prefix->bv_val, prefix->bv_len );
2389 HASH_Update( &HASHcontext,
2390 syntax->ssyn_oid, slen );
2391 HASH_Update( &HASHcontext,
2392 mr->smr_oid, mlen );
2393 HASH_Update( &HASHcontext,
2394 value->bv_val, value->bv_len );
2395 HASH_Final( HASHdigest, &HASHcontext );
2397 ber_dupbv( &keys[i], &digest );
2400 keys[i].bv_val = NULL;
2402 return LDAP_SUCCESS;
2405 /* Index generation function */
2406 static int caseExactIA5Filter(
2411 struct berval *prefix,
2417 HASH_CONTEXT HASHcontext;
2418 unsigned char HASHdigest[HASH_BYTES];
2419 struct berval *value;
2420 struct berval digest;
2421 digest.bv_val = HASHdigest;
2422 digest.bv_len = sizeof(HASHdigest);
2424 slen = syntax->ssyn_oidlen;
2425 mlen = mr->smr_oidlen;
2427 value = (struct berval *) assertValue;
2429 keys = ch_malloc( sizeof( struct berval ) * 2 );
2431 HASH_Init( &HASHcontext );
2432 if( prefix != NULL && prefix->bv_len > 0 ) {
2433 HASH_Update( &HASHcontext,
2434 prefix->bv_val, prefix->bv_len );
2436 HASH_Update( &HASHcontext,
2437 syntax->ssyn_oid, slen );
2438 HASH_Update( &HASHcontext,
2439 mr->smr_oid, mlen );
2440 HASH_Update( &HASHcontext,
2441 value->bv_val, value->bv_len );
2442 HASH_Final( HASHdigest, &HASHcontext );
2444 ber_dupbv( &keys[0], &digest );
2445 keys[1].bv_val = NULL;
2448 return LDAP_SUCCESS;
2451 /* Substrings Index generation function */
2452 static int caseExactIA5SubstringsIndexer(
2457 struct berval *prefix,
2464 HASH_CONTEXT HASHcontext;
2465 unsigned char HASHdigest[HASH_BYTES];
2466 struct berval digest;
2467 digest.bv_val = HASHdigest;
2468 digest.bv_len = sizeof(HASHdigest);
2470 /* we should have at least one value at this point */
2471 assert( values != NULL && values[0].bv_val != NULL );
2474 for( i=0; values[i].bv_val != NULL; i++ ) {
2475 /* count number of indices to generate */
2476 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2480 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2481 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2482 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2483 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2485 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2489 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2490 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2491 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2495 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2496 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2497 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2498 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2500 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2506 /* no keys to generate */
2508 return LDAP_SUCCESS;
2511 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2513 slen = syntax->ssyn_oidlen;
2514 mlen = mr->smr_oidlen;
2517 for( i=0; values[i].bv_val != NULL; i++ ) {
2519 struct berval *value;
2522 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2524 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2525 ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2527 char pre = SLAP_INDEX_SUBSTR_PREFIX;
2528 max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2530 for( j=0; j<max; j++ ) {
2531 HASH_Init( &HASHcontext );
2532 if( prefix != NULL && prefix->bv_len > 0 ) {
2533 HASH_Update( &HASHcontext,
2534 prefix->bv_val, prefix->bv_len );
2537 HASH_Update( &HASHcontext,
2538 &pre, sizeof( pre ) );
2539 HASH_Update( &HASHcontext,
2540 syntax->ssyn_oid, slen );
2541 HASH_Update( &HASHcontext,
2542 mr->smr_oid, mlen );
2543 HASH_Update( &HASHcontext,
2545 SLAP_INDEX_SUBSTR_MAXLEN );
2546 HASH_Final( HASHdigest, &HASHcontext );
2548 ber_dupbv( &keys[nkeys++], &digest );
2552 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2553 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2555 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2558 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2559 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2560 HASH_Init( &HASHcontext );
2561 if( prefix != NULL && prefix->bv_len > 0 ) {
2562 HASH_Update( &HASHcontext,
2563 prefix->bv_val, prefix->bv_len );
2565 HASH_Update( &HASHcontext,
2566 &pre, sizeof( pre ) );
2567 HASH_Update( &HASHcontext,
2568 syntax->ssyn_oid, slen );
2569 HASH_Update( &HASHcontext,
2570 mr->smr_oid, mlen );
2571 HASH_Update( &HASHcontext,
2573 HASH_Final( HASHdigest, &HASHcontext );
2575 ber_dupbv( &keys[nkeys++], &digest );
2578 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2579 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2580 HASH_Init( &HASHcontext );
2581 if( prefix != NULL && prefix->bv_len > 0 ) {
2582 HASH_Update( &HASHcontext,
2583 prefix->bv_val, prefix->bv_len );
2585 HASH_Update( &HASHcontext,
2586 &pre, sizeof( pre ) );
2587 HASH_Update( &HASHcontext,
2588 syntax->ssyn_oid, slen );
2589 HASH_Update( &HASHcontext,
2590 mr->smr_oid, mlen );
2591 HASH_Update( &HASHcontext,
2592 &value->bv_val[value->bv_len-j], j );
2593 HASH_Final( HASHdigest, &HASHcontext );
2595 ber_dupbv( &keys[nkeys++], &digest );
2602 keys[nkeys].bv_val = NULL;
2609 return LDAP_SUCCESS;
2612 static int caseExactIA5SubstringsFilter(
2617 struct berval *prefix,
2621 SubstringsAssertion *sa = assertValue;
2623 ber_len_t nkeys = 0;
2624 size_t slen, mlen, klen;
2626 HASH_CONTEXT HASHcontext;
2627 unsigned char HASHdigest[HASH_BYTES];
2628 struct berval *value;
2629 struct berval digest;
2631 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2632 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2637 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2639 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2640 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2641 /* don't bother accounting for stepping */
2642 nkeys += sa->sa_any[i].bv_len -
2643 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2648 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2649 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2656 return LDAP_SUCCESS;
2659 digest.bv_val = HASHdigest;
2660 digest.bv_len = sizeof(HASHdigest);
2662 slen = syntax->ssyn_oidlen;
2663 mlen = mr->smr_oidlen;
2665 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2668 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2669 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2671 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2672 value = &sa->sa_initial;
2674 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2675 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2677 HASH_Init( &HASHcontext );
2678 if( prefix != NULL && prefix->bv_len > 0 ) {
2679 HASH_Update( &HASHcontext,
2680 prefix->bv_val, prefix->bv_len );
2682 HASH_Update( &HASHcontext,
2683 &pre, sizeof( pre ) );
2684 HASH_Update( &HASHcontext,
2685 syntax->ssyn_oid, slen );
2686 HASH_Update( &HASHcontext,
2687 mr->smr_oid, mlen );
2688 HASH_Update( &HASHcontext,
2689 value->bv_val, klen );
2690 HASH_Final( HASHdigest, &HASHcontext );
2692 ber_dupbv( &keys[nkeys++], &digest );
2695 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2697 pre = SLAP_INDEX_SUBSTR_PREFIX;
2698 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2700 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2701 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2705 value = &sa->sa_any[i];
2708 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2709 j += SLAP_INDEX_SUBSTR_STEP )
2711 HASH_Init( &HASHcontext );
2712 if( prefix != NULL && prefix->bv_len > 0 ) {
2713 HASH_Update( &HASHcontext,
2714 prefix->bv_val, prefix->bv_len );
2716 HASH_Update( &HASHcontext,
2717 &pre, sizeof( pre ) );
2718 HASH_Update( &HASHcontext,
2719 syntax->ssyn_oid, slen );
2720 HASH_Update( &HASHcontext,
2721 mr->smr_oid, mlen );
2722 HASH_Update( &HASHcontext,
2723 &value->bv_val[j], klen );
2724 HASH_Final( HASHdigest, &HASHcontext );
2726 ber_dupbv( &keys[nkeys++], &digest );
2731 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2732 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2734 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2735 value = &sa->sa_final;
2737 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2738 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2740 HASH_Init( &HASHcontext );
2741 if( prefix != NULL && prefix->bv_len > 0 ) {
2742 HASH_Update( &HASHcontext,
2743 prefix->bv_val, prefix->bv_len );
2745 HASH_Update( &HASHcontext,
2746 &pre, sizeof( pre ) );
2747 HASH_Update( &HASHcontext,
2748 syntax->ssyn_oid, slen );
2749 HASH_Update( &HASHcontext,
2750 mr->smr_oid, mlen );
2751 HASH_Update( &HASHcontext,
2752 &value->bv_val[value->bv_len-klen], klen );
2753 HASH_Final( HASHdigest, &HASHcontext );
2755 ber_dupbv( &keys[nkeys++], &digest );
2759 keys[nkeys].bv_val = NULL;
2766 return LDAP_SUCCESS;
2775 struct berval *value,
2776 void *assertedValue )
2778 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2780 if( match == 0 && value->bv_len ) {
2781 match = strncasecmp( value->bv_val,
2782 ((struct berval *) assertedValue)->bv_val,
2787 return LDAP_SUCCESS;
2791 caseIgnoreIA5SubstringsMatch(
2796 struct berval *value,
2797 void *assertedValue )
2800 SubstringsAssertion *sub = assertedValue;
2801 struct berval left = *value;
2805 /* Add up asserted input length */
2806 if( sub->sa_initial.bv_val ) {
2807 inlen += sub->sa_initial.bv_len;
2810 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2811 inlen += sub->sa_any[i].bv_len;
2814 if( sub->sa_final.bv_val ) {
2815 inlen += sub->sa_final.bv_len;
2818 if( sub->sa_initial.bv_val ) {
2819 if( inlen > left.bv_len ) {
2824 match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
2825 sub->sa_initial.bv_len );
2831 left.bv_val += sub->sa_initial.bv_len;
2832 left.bv_len -= sub->sa_initial.bv_len;
2833 inlen -= sub->sa_initial.bv_len;
2836 if( sub->sa_final.bv_val ) {
2837 if( inlen > left.bv_len ) {
2842 match = strncasecmp( sub->sa_final.bv_val,
2843 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2844 sub->sa_final.bv_len );
2850 left.bv_len -= sub->sa_final.bv_len;
2851 inlen -= sub->sa_final.bv_len;
2855 for(i=0; sub->sa_any[i].bv_val; i++) {
2860 if( inlen > left.bv_len ) {
2861 /* not enough length */
2866 if( sub->sa_any[i].bv_len == 0 ) {
2870 p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
2877 assert( idx < left.bv_len );
2878 if( idx >= left.bv_len ) {
2879 /* this shouldn't happen */
2886 if( sub->sa_any[i].bv_len > left.bv_len ) {
2887 /* not enough left */
2892 match = strncasecmp( left.bv_val,
2893 sub->sa_any[i].bv_val,
2894 sub->sa_any[i].bv_len );
2903 left.bv_val += sub->sa_any[i].bv_len;
2904 left.bv_len -= sub->sa_any[i].bv_len;
2905 inlen -= sub->sa_any[i].bv_len;
2911 return LDAP_SUCCESS;
2914 /* Index generation function */
2915 static int caseIgnoreIA5Indexer(
2920 struct berval *prefix,
2925 int rc = LDAP_SUCCESS;
2928 HASH_CONTEXT HASHcontext;
2929 unsigned char HASHdigest[HASH_BYTES];
2930 struct berval digest;
2931 digest.bv_val = HASHdigest;
2932 digest.bv_len = sizeof(HASHdigest);
2934 /* we should have at least one value at this point */
2935 assert( values != NULL && values[0].bv_val != NULL );
2937 for( i=0; values[i].bv_val != NULL; i++ ) {
2938 /* just count them */
2941 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2943 slen = syntax->ssyn_oidlen;
2944 mlen = mr->smr_oidlen;
2946 for( i=0; values[i].bv_val != NULL; i++ ) {
2947 struct berval value;
2949 if( mr->smr_normalize ) {
2950 rc = (mr->smr_normalize)( use, syntax, mr, &values[i], &value );
2951 if( rc != LDAP_SUCCESS ) {
2954 } else if ( mr->smr_syntax->ssyn_normalize ) {
2955 rc = (mr->smr_syntax->ssyn_normalize)( syntax, &values[i], &value );
2956 if( rc != LDAP_SUCCESS ) {
2960 ber_dupbv( &value, &values[i] );
2963 ldap_pvt_str2lower( value.bv_val );
2965 HASH_Init( &HASHcontext );
2966 if( prefix != NULL && prefix->bv_len > 0 ) {
2967 HASH_Update( &HASHcontext,
2968 prefix->bv_val, prefix->bv_len );
2970 HASH_Update( &HASHcontext,
2971 syntax->ssyn_oid, slen );
2972 HASH_Update( &HASHcontext,
2973 mr->smr_oid, mlen );
2974 HASH_Update( &HASHcontext,
2975 value.bv_val, value.bv_len );
2976 HASH_Final( HASHdigest, &HASHcontext );
2978 free( value.bv_val );
2980 ber_dupbv( &keys[i], &digest );
2983 keys[i].bv_val = NULL;
2984 if( rc != LDAP_SUCCESS ) {
2985 ber_bvarray_free( keys );
2992 /* Index generation function */
2993 static int caseIgnoreIA5Filter(
2998 struct berval *prefix,
3004 HASH_CONTEXT HASHcontext;
3005 unsigned char HASHdigest[HASH_BYTES];
3006 struct berval value;
3007 struct berval digest;
3008 digest.bv_val = HASHdigest;
3009 digest.bv_len = sizeof(HASHdigest);
3011 slen = syntax->ssyn_oidlen;
3012 mlen = mr->smr_oidlen;
3014 ber_dupbv( &value, (struct berval *) assertValue );
3015 ldap_pvt_str2lower( value.bv_val );
3017 keys = ch_malloc( sizeof( struct berval ) * 2 );
3019 HASH_Init( &HASHcontext );
3020 if( prefix != NULL && prefix->bv_len > 0 ) {
3021 HASH_Update( &HASHcontext,
3022 prefix->bv_val, prefix->bv_len );
3024 HASH_Update( &HASHcontext,
3025 syntax->ssyn_oid, slen );
3026 HASH_Update( &HASHcontext,
3027 mr->smr_oid, mlen );
3028 HASH_Update( &HASHcontext,
3029 value.bv_val, value.bv_len );
3030 HASH_Final( HASHdigest, &HASHcontext );
3032 ber_dupbv( &keys[0], &digest );
3033 keys[1].bv_val = NULL;
3035 free( value.bv_val );
3039 return LDAP_SUCCESS;
3042 /* Substrings Index generation function */
3043 static int caseIgnoreIA5SubstringsIndexer(
3048 struct berval *prefix,
3055 HASH_CONTEXT HASHcontext;
3056 unsigned char HASHdigest[HASH_BYTES];
3057 struct berval digest;
3058 digest.bv_val = HASHdigest;
3059 digest.bv_len = sizeof(HASHdigest);
3061 /* we should have at least one value at this point */
3062 assert( values != NULL && values[0].bv_val != NULL );
3065 for( i=0; values[i].bv_val != NULL; i++ ) {
3066 /* count number of indices to generate */
3067 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3071 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3072 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3073 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3074 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3076 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3080 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3081 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3082 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3086 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3087 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3088 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3089 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3091 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3097 /* no keys to generate */
3099 return LDAP_SUCCESS;
3102 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3104 slen = syntax->ssyn_oidlen;
3105 mlen = mr->smr_oidlen;
3108 for( i=0; values[i].bv_val != NULL; i++ ) {
3110 struct berval value;
3112 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3114 ber_dupbv( &value, &values[i] );
3115 ldap_pvt_str2lower( value.bv_val );
3117 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3118 ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3120 char pre = SLAP_INDEX_SUBSTR_PREFIX;
3121 max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3123 for( j=0; j<max; j++ ) {
3124 HASH_Init( &HASHcontext );
3125 if( prefix != NULL && prefix->bv_len > 0 ) {
3126 HASH_Update( &HASHcontext,
3127 prefix->bv_val, prefix->bv_len );
3130 HASH_Update( &HASHcontext,
3131 &pre, sizeof( pre ) );
3132 HASH_Update( &HASHcontext,
3133 syntax->ssyn_oid, slen );
3134 HASH_Update( &HASHcontext,
3135 mr->smr_oid, mlen );
3136 HASH_Update( &HASHcontext,
3138 SLAP_INDEX_SUBSTR_MAXLEN );
3139 HASH_Final( HASHdigest, &HASHcontext );
3141 ber_dupbv( &keys[nkeys++], &digest );
3145 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3146 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3148 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3151 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3152 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3153 HASH_Init( &HASHcontext );
3154 if( prefix != NULL && prefix->bv_len > 0 ) {
3155 HASH_Update( &HASHcontext,
3156 prefix->bv_val, prefix->bv_len );
3158 HASH_Update( &HASHcontext,
3159 &pre, sizeof( pre ) );
3160 HASH_Update( &HASHcontext,
3161 syntax->ssyn_oid, slen );
3162 HASH_Update( &HASHcontext,
3163 mr->smr_oid, mlen );
3164 HASH_Update( &HASHcontext,
3166 HASH_Final( HASHdigest, &HASHcontext );
3168 ber_dupbv( &keys[nkeys++], &digest );
3171 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3172 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3173 HASH_Init( &HASHcontext );
3174 if( prefix != NULL && prefix->bv_len > 0 ) {
3175 HASH_Update( &HASHcontext,
3176 prefix->bv_val, prefix->bv_len );
3178 HASH_Update( &HASHcontext,
3179 &pre, sizeof( pre ) );
3180 HASH_Update( &HASHcontext,
3181 syntax->ssyn_oid, slen );
3182 HASH_Update( &HASHcontext,
3183 mr->smr_oid, mlen );
3184 HASH_Update( &HASHcontext,
3185 &value.bv_val[value.bv_len-j], j );
3186 HASH_Final( HASHdigest, &HASHcontext );
3188 ber_dupbv( &keys[nkeys++], &digest );
3193 free( value.bv_val );
3197 keys[nkeys].bv_val = NULL;
3204 return LDAP_SUCCESS;
3207 static int caseIgnoreIA5SubstringsFilter(
3212 struct berval *prefix,
3216 SubstringsAssertion *sa = assertValue;
3218 ber_len_t nkeys = 0;
3219 size_t slen, mlen, klen;
3221 HASH_CONTEXT HASHcontext;
3222 unsigned char HASHdigest[HASH_BYTES];
3223 struct berval value;
3224 struct berval digest;
3226 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3227 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3232 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3234 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3235 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3236 /* don't bother accounting for stepping */
3237 nkeys += sa->sa_any[i].bv_len -
3238 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3243 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3244 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3251 return LDAP_SUCCESS;
3254 digest.bv_val = HASHdigest;
3255 digest.bv_len = sizeof(HASHdigest);
3257 slen = syntax->ssyn_oidlen;
3258 mlen = mr->smr_oidlen;
3260 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3263 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3264 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3266 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3267 ber_dupbv( &value, &sa->sa_initial );
3268 ldap_pvt_str2lower( value.bv_val );
3270 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3271 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3273 HASH_Init( &HASHcontext );
3274 if( prefix != NULL && prefix->bv_len > 0 ) {
3275 HASH_Update( &HASHcontext,
3276 prefix->bv_val, prefix->bv_len );
3278 HASH_Update( &HASHcontext,
3279 &pre, sizeof( pre ) );
3280 HASH_Update( &HASHcontext,
3281 syntax->ssyn_oid, slen );
3282 HASH_Update( &HASHcontext,
3283 mr->smr_oid, mlen );
3284 HASH_Update( &HASHcontext,
3285 value.bv_val, klen );
3286 HASH_Final( HASHdigest, &HASHcontext );
3288 free( value.bv_val );
3289 ber_dupbv( &keys[nkeys++], &digest );
3292 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3294 pre = SLAP_INDEX_SUBSTR_PREFIX;
3295 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3297 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3298 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3302 ber_dupbv( &value, &sa->sa_any[i] );
3303 ldap_pvt_str2lower( value.bv_val );
3306 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3307 j += SLAP_INDEX_SUBSTR_STEP )
3309 HASH_Init( &HASHcontext );
3310 if( prefix != NULL && prefix->bv_len > 0 ) {
3311 HASH_Update( &HASHcontext,
3312 prefix->bv_val, prefix->bv_len );
3314 HASH_Update( &HASHcontext,
3315 &pre, sizeof( pre ) );
3316 HASH_Update( &HASHcontext,
3317 syntax->ssyn_oid, slen );
3318 HASH_Update( &HASHcontext,
3319 mr->smr_oid, mlen );
3320 HASH_Update( &HASHcontext,
3321 &value.bv_val[j], klen );
3322 HASH_Final( HASHdigest, &HASHcontext );
3324 ber_dupbv( &keys[nkeys++], &digest );
3327 free( value.bv_val );
3331 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3332 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3334 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3335 ber_dupbv( &value, &sa->sa_final );
3336 ldap_pvt_str2lower( value.bv_val );
3338 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3339 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3341 HASH_Init( &HASHcontext );
3342 if( prefix != NULL && prefix->bv_len > 0 ) {
3343 HASH_Update( &HASHcontext,
3344 prefix->bv_val, prefix->bv_len );
3346 HASH_Update( &HASHcontext,
3347 &pre, sizeof( pre ) );
3348 HASH_Update( &HASHcontext,
3349 syntax->ssyn_oid, slen );
3350 HASH_Update( &HASHcontext,
3351 mr->smr_oid, mlen );
3352 HASH_Update( &HASHcontext,
3353 &value.bv_val[value.bv_len-klen], klen );
3354 HASH_Final( HASHdigest, &HASHcontext );
3356 free( value.bv_val );
3357 ber_dupbv( &keys[nkeys++], &digest );
3361 keys[nkeys].bv_val = NULL;
3368 return LDAP_SUCCESS;
3372 numericStringValidate(
3378 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
3380 for(i=0; i < in->bv_len; i++) {
3381 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3382 return LDAP_INVALID_SYNTAX;
3386 return LDAP_SUCCESS;
3390 numericStringNormalize(
3393 struct berval *normalized )
3395 /* removal all spaces */
3398 assert( val->bv_len );
3400 normalized->bv_val = ch_malloc( val->bv_len + 1 );
3403 q = normalized->bv_val;
3406 if ( ASCII_SPACE( *p ) ) {
3407 /* Ignore whitespace */
3414 /* we should have copied no more then is in val */
3415 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3417 /* null terminate */
3420 normalized->bv_len = q - normalized->bv_val;
3422 if( normalized->bv_len == 0 ) {
3423 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
3424 normalized->bv_val[0] = ' ';
3425 normalized->bv_val[1] = '\0';
3426 normalized->bv_len = 1;
3429 return LDAP_SUCCESS;
3433 objectIdentifierFirstComponentMatch(
3438 struct berval *value,
3439 void *assertedValue )
3441 int rc = LDAP_SUCCESS;
3443 struct berval *asserted = (struct berval *) assertedValue;
3447 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3448 return LDAP_INVALID_SYNTAX;
3451 /* trim leading white space */
3452 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3456 /* grab next word */
3457 oid.bv_val = &value->bv_val[i];
3458 oid.bv_len = value->bv_len - i;
3459 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3464 /* insert attributeTypes, objectclass check here */
3465 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3466 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3469 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3470 MatchingRule *asserted_mr = mr_bvfind( asserted );
3471 MatchingRule *stored_mr = mr_bvfind( &oid );
3473 if( asserted_mr == NULL ) {
3474 rc = SLAPD_COMPARE_UNDEFINED;
3476 match = asserted_mr != stored_mr;
3479 } else if ( !strcmp( syntax->ssyn_oid,
3480 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3482 AttributeType *asserted_at = at_bvfind( asserted );
3483 AttributeType *stored_at = at_bvfind( &oid );
3485 if( asserted_at == NULL ) {
3486 rc = SLAPD_COMPARE_UNDEFINED;
3488 match = asserted_at != stored_at;
3491 } else if ( !strcmp( syntax->ssyn_oid,
3492 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3494 ObjectClass *asserted_oc = oc_bvfind( asserted );
3495 ObjectClass *stored_oc = oc_bvfind( &oid );
3497 if( asserted_oc == NULL ) {
3498 rc = SLAPD_COMPARE_UNDEFINED;
3500 match = asserted_oc != stored_oc;
3506 LDAP_LOG( CONFIG, ENTRY,
3507 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
3508 match, value->bv_val, asserted->bv_val );
3510 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3511 "%d\n\t\"%s\"\n\t\"%s\"\n",
3512 match, value->bv_val, asserted->bv_val );
3516 if( rc == LDAP_SUCCESS ) *matchp = match;
3526 struct berval *value,
3527 void *assertedValue )
3529 long lValue, lAssertedValue;
3531 /* safe to assume integers are NUL terminated? */
3532 lValue = strtoul(value->bv_val, NULL, 10);
3533 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3534 return LDAP_CONSTRAINT_VIOLATION;
3536 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3537 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3538 return LDAP_CONSTRAINT_VIOLATION;
3540 *matchp = (lValue & lAssertedValue);
3541 return LDAP_SUCCESS;
3550 struct berval *value,
3551 void *assertedValue )
3553 long lValue, lAssertedValue;
3555 /* safe to assume integers are NUL terminated? */
3556 lValue = strtoul(value->bv_val, NULL, 10);
3557 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3558 return LDAP_CONSTRAINT_VIOLATION;
3560 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3561 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3562 return LDAP_CONSTRAINT_VIOLATION;
3564 *matchp = (lValue | lAssertedValue);
3565 return LDAP_SUCCESS;
3569 #include <openssl/x509.h>
3570 #include <openssl/err.h>
3571 char digit[] = "0123456789";
3574 * Next function returns a string representation of a ASN1_INTEGER.
3575 * It works for unlimited lengths.
3578 static struct berval *
3579 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3584 /* We work backwards, make it fill from the end of buf */
3585 p = buf + sizeof(buf) - 1;
3588 if ( a == NULL || a->length == 0 ) {
3596 /* We want to preserve the original */
3597 copy = ch_malloc(n*sizeof(unsigned int));
3598 for (i = 0; i<n; i++) {
3599 copy[i] = a->data[i];
3603 * base indicates the index of the most significant
3604 * byte that might be nonzero. When it goes off the
3605 * end, we now there is nothing left to do.
3611 for (i = base; i<n; i++ ) {
3612 copy[i] += carry*256;
3613 carry = copy[i] % 10;
3618 * Way too large, we need to leave
3619 * room for sign if negative
3624 *--p = digit[carry];
3625 if (copy[base] == 0)
3631 if ( a->type == V_ASN1_NEG_INTEGER ) {
3635 return ber_str2bv( p, 0, 1, bv );
3639 * Given a certificate in DER format, extract the corresponding
3640 * assertion value for certificateExactMatch
3643 certificateExactConvert(
3645 struct berval * out )
3648 unsigned char *p = in->bv_val;
3649 struct berval serial;
3650 struct berval issuer_dn;
3652 xcert = d2i_X509(NULL, &p, in->bv_len);
3655 LDAP_LOG( CONFIG, ENTRY,
3656 "certificateExactConvert: error parsing cert: %s\n",
3657 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3659 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3660 "error parsing cert: %s\n",
3661 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3663 return LDAP_INVALID_SYNTAX;
3666 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3668 return LDAP_INVALID_SYNTAX;
3670 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn ) != LDAP_SUCCESS ) {
3672 ber_memfree(serial.bv_val);
3673 return LDAP_INVALID_SYNTAX;
3678 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3679 out->bv_val = ch_malloc(out->bv_len);
3681 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3683 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3685 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3686 p += issuer_dn.bv_len;
3690 LDAP_LOG( CONFIG, ARGS,
3691 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
3693 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3695 out->bv_val, NULL, NULL );
3698 ber_memfree(serial.bv_val);
3699 ber_memfree(issuer_dn.bv_val);
3701 return LDAP_SUCCESS;
3705 serial_and_issuer_parse(
3706 struct berval *assertion,
3707 struct berval *serial,
3708 struct berval *issuer_dn
3716 begin = assertion->bv_val;
3717 end = assertion->bv_val+assertion->bv_len-1;
3718 for (p=begin; p<=end && *p != '$'; p++)
3721 return LDAP_INVALID_SYNTAX;
3723 /* p now points at the $ sign, now use begin and end to delimit the
3725 while (ASCII_SPACE(*begin))
3728 while (ASCII_SPACE(*end))
3731 bv.bv_len = end-begin+1;
3733 ber_dupbv(serial, &bv);
3735 /* now extract the issuer, remember p was at the dollar sign */
3738 end = assertion->bv_val+assertion->bv_len-1;
3739 while (ASCII_SPACE(*begin))
3741 /* should we trim spaces at the end too? is it safe always? */
3743 bv.bv_len = end-begin+1;
3745 dnNormalize2( NULL, &bv, issuer_dn );
3748 return LDAP_SUCCESS;
3752 certificateExactMatch(
3757 struct berval *value,
3758 void *assertedValue )
3761 unsigned char *p = value->bv_val;
3762 struct berval serial;
3763 struct berval issuer_dn;
3764 struct berval asserted_serial;
3765 struct berval asserted_issuer_dn;
3768 xcert = d2i_X509(NULL, &p, value->bv_len);
3771 LDAP_LOG( CONFIG, ENTRY,
3772 "certificateExactMatch: error parsing cert: %s\n",
3773 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3775 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3776 "error parsing cert: %s\n",
3777 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3779 return LDAP_INVALID_SYNTAX;
3782 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3783 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
3787 serial_and_issuer_parse(assertedValue,
3789 &asserted_issuer_dn);
3794 slap_schema.si_syn_integer,
3795 slap_schema.si_mr_integerMatch,
3798 if ( ret == LDAP_SUCCESS ) {
3799 if ( *matchp == 0 ) {
3800 /* We need to normalize everything for dnMatch */
3804 slap_schema.si_syn_distinguishedName,
3805 slap_schema.si_mr_distinguishedNameMatch,
3807 &asserted_issuer_dn);
3812 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
3813 "%d\n\t\"%s $ %s\"\n",
3814 *matchp, serial.bv_val, issuer_dn.bv_val );
3815 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
3816 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3819 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3820 "%d\n\t\"%s $ %s\"\n",
3821 *matchp, serial.bv_val, issuer_dn.bv_val );
3822 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3823 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3827 ber_memfree(serial.bv_val);
3828 ber_memfree(issuer_dn.bv_val);
3829 ber_memfree(asserted_serial.bv_val);
3830 ber_memfree(asserted_issuer_dn.bv_val);
3836 * Index generation function
3837 * We just index the serials, in most scenarios the issuer DN is one of
3838 * a very small set of values.
3840 static int certificateExactIndexer(
3845 struct berval *prefix,
3853 struct berval serial;
3855 /* we should have at least one value at this point */
3856 assert( values != NULL && values[0].bv_val != NULL );
3858 for( i=0; values[i].bv_val != NULL; i++ ) {
3859 /* empty -- just count them */
3862 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3864 for( i=0; values[i].bv_val != NULL; i++ ) {
3865 p = values[i].bv_val;
3866 xcert = d2i_X509(NULL, &p, values[i].bv_len);
3869 LDAP_LOG( CONFIG, ENTRY,
3870 "certificateExactIndexer: error parsing cert: %s\n",
3871 ERR_error_string(ERR_get_error(),NULL), 0, 0);
3873 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3874 "error parsing cert: %s\n",
3875 ERR_error_string(ERR_get_error(),NULL),
3878 /* Do we leak keys on error? */
3879 return LDAP_INVALID_SYNTAX;
3882 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3884 integerNormalize( slap_schema.si_syn_integer,
3887 ber_memfree(serial.bv_val);
3889 LDAP_LOG( CONFIG, ENTRY,
3890 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
3892 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3899 keys[i].bv_val = NULL;
3901 return LDAP_SUCCESS;
3904 /* Index generation function */
3905 /* We think this is always called with a value in matching rule syntax */
3906 static int certificateExactFilter(
3911 struct berval *prefix,
3916 struct berval asserted_serial;
3918 serial_and_issuer_parse(assertValue,
3922 keys = ch_malloc( sizeof( struct berval ) * 2 );
3923 integerNormalize( syntax, &asserted_serial, &keys[0] );
3924 keys[1].bv_val = NULL;
3927 ber_memfree(asserted_serial.bv_val);
3928 return LDAP_SUCCESS;
3933 check_time_syntax (struct berval *val,
3937 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3938 static int mdays[2][12] = {
3939 /* non-leap years */
3940 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3942 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3945 int part, c, tzoffset, leapyear = 0 ;
3947 if( val->bv_len == 0 ) {
3948 return LDAP_INVALID_SYNTAX;
3951 p = (char *)val->bv_val;
3952 e = p + val->bv_len;
3954 /* Ignore initial whitespace */
3955 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3959 if (e - p < 13 - (2 * start)) {
3960 return LDAP_INVALID_SYNTAX;
3963 for (part = 0; part < 9; part++) {
3967 for (part = start; part < 7; part++) {
3969 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3976 return LDAP_INVALID_SYNTAX;
3978 if (c < 0 || c > 9) {
3979 return LDAP_INVALID_SYNTAX;
3985 return LDAP_INVALID_SYNTAX;
3987 if (c < 0 || c > 9) {
3988 return LDAP_INVALID_SYNTAX;
3993 if (part == 2 || part == 3) {
3996 if (parts[part] < 0) {
3997 return LDAP_INVALID_SYNTAX;
3999 if (parts[part] > ceiling[part]) {
4000 return LDAP_INVALID_SYNTAX;
4004 /* leapyear check for the Gregorian calendar (year>1581) */
4005 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
4006 ((parts[0] % 4 == 0) && (parts[1] == 0)))
4011 if (parts[3] > mdays[leapyear][parts[2]]) {
4012 return LDAP_INVALID_SYNTAX;
4017 tzoffset = 0; /* UTC */
4018 } else if (c != '+' && c != '-') {
4019 return LDAP_INVALID_SYNTAX;
4023 } else /* c == '+' */ {
4028 return LDAP_INVALID_SYNTAX;
4031 for (part = 7; part < 9; part++) {
4033 if (c < 0 || c > 9) {
4034 return LDAP_INVALID_SYNTAX;
4039 if (c < 0 || c > 9) {
4040 return LDAP_INVALID_SYNTAX;
4044 if (parts[part] < 0 || parts[part] > ceiling[part]) {
4045 return LDAP_INVALID_SYNTAX;
4050 /* Ignore trailing whitespace */
4051 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4055 return LDAP_INVALID_SYNTAX;
4058 switch ( tzoffset ) {
4059 case -1: /* negativ offset to UTC, ie west of Greenwich */
4060 parts[4] += parts[7];
4061 parts[5] += parts[8];
4062 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4066 c = mdays[leapyear][parts[2]];
4068 if (parts[part] > c) {
4069 parts[part] -= c + 1;
4074 case 1: /* positive offset to UTC, ie east of Greenwich */
4075 parts[4] -= parts[7];
4076 parts[5] -= parts[8];
4077 for (part = 6; --part > 0; ) {
4081 /* first arg to % needs to be non negativ */
4082 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4084 if (parts[part] < 0) {
4085 parts[part] += c + 1;
4090 case 0: /* already UTC */
4094 return LDAP_SUCCESS;
4097 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4102 struct berval *normalized )
4106 rc = check_time_syntax(val, 1, parts);
4107 if (rc != LDAP_SUCCESS) {
4111 normalized->bv_val = ch_malloc( 14 );
4112 if ( normalized->bv_val == NULL ) {
4113 return LBER_ERROR_MEMORY;
4116 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4117 parts[1], parts[2] + 1, parts[3] + 1,
4118 parts[4], parts[5], parts[6] );
4119 normalized->bv_len = 13;
4121 return LDAP_SUCCESS;
4125 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4133 return check_time_syntax(in, 1, parts);
4138 generalizedTimeValidate(
4144 return check_time_syntax(in, 0, parts);
4148 generalizedTimeNormalize(
4151 struct berval *normalized )
4155 rc = check_time_syntax(val, 0, parts);
4156 if (rc != LDAP_SUCCESS) {
4160 normalized->bv_val = ch_malloc( 16 );
4161 if ( normalized->bv_val == NULL ) {
4162 return LBER_ERROR_MEMORY;
4165 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4166 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4167 parts[4], parts[5], parts[6] );
4168 normalized->bv_len = 15;
4170 return LDAP_SUCCESS;
4174 nisNetgroupTripleValidate(
4176 struct berval *val )
4181 if ( val->bv_len == 0 ) {
4182 return LDAP_INVALID_SYNTAX;
4185 p = (char *)val->bv_val;
4186 e = p + val->bv_len;
4188 if ( *p != '(' /*')'*/ ) {
4189 return LDAP_INVALID_SYNTAX;
4192 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4196 return LDAP_INVALID_SYNTAX;
4199 } else if ( !AD_CHAR( *p ) ) {
4200 return LDAP_INVALID_SYNTAX;
4204 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4205 return LDAP_INVALID_SYNTAX;
4211 return LDAP_INVALID_SYNTAX;
4214 return LDAP_SUCCESS;
4218 bootParameterValidate(
4220 struct berval *val )
4224 if ( val->bv_len == 0 ) {
4225 return LDAP_INVALID_SYNTAX;
4228 p = (char *)val->bv_val;
4229 e = p + val->bv_len;
4232 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4233 if ( !AD_CHAR( *p ) ) {
4234 return LDAP_INVALID_SYNTAX;
4239 return LDAP_INVALID_SYNTAX;
4243 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4244 if ( !AD_CHAR( *p ) ) {
4245 return LDAP_INVALID_SYNTAX;
4250 return LDAP_INVALID_SYNTAX;
4254 for ( p++; p < e; p++ ) {
4255 if ( !SLAP_PRINTABLE( *p ) ) {
4256 return LDAP_INVALID_SYNTAX;
4260 return LDAP_SUCCESS;
4263 static struct syntax_defs_rec {
4265 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4266 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4268 slap_syntax_validate_func *sd_validate;
4269 slap_syntax_transform_func *sd_normalize;
4270 slap_syntax_transform_func *sd_pretty;
4271 #ifdef SLAPD_BINARY_CONVERSION
4272 slap_syntax_transform_func *sd_ber2str;
4273 slap_syntax_transform_func *sd_str2ber;
4276 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4277 X_BINARY X_NOT_H_R ")",
4278 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4279 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4280 0, NULL, NULL, NULL},
4281 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4282 0, NULL, NULL, NULL},
4283 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4285 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4286 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4288 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4289 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4290 0, bitStringValidate, bitStringNormalize, NULL },
4291 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4292 0, booleanValidate, NULL, NULL},
4293 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4294 X_BINARY X_NOT_H_R ")",
4295 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4296 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4297 X_BINARY X_NOT_H_R ")",
4298 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4299 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4300 X_BINARY X_NOT_H_R ")",
4301 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4302 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4303 0, countryStringValidate, IA5StringNormalize, NULL},
4304 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4305 0, dnValidate, dnNormalize2, dnPretty2},
4306 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4307 0, NULL, NULL, NULL},
4308 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4309 0, NULL, NULL, NULL},
4310 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4311 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4312 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4313 0, NULL, NULL, NULL},
4314 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4315 0, NULL, NULL, NULL},
4316 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4317 0, NULL, NULL, NULL},
4318 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4319 0, NULL, NULL, NULL},
4320 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4321 0, NULL, NULL, NULL},
4322 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4323 0, printablesStringValidate, telephoneNumberNormalize, NULL},
4324 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4325 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4326 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4327 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4328 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4329 0, NULL, NULL, NULL},
4330 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4331 0, IA5StringValidate, IA5StringNormalize, NULL},
4332 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4333 0, integerValidate, integerNormalize, NULL},
4334 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4335 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4336 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4337 0, NULL, NULL, NULL},
4338 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4339 0, NULL, NULL, NULL},
4340 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4341 0, NULL, NULL, NULL},
4342 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4343 0, NULL, NULL, NULL},
4344 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4345 0, NULL, NULL, NULL},
4346 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4347 0, nameUIDValidate, nameUIDNormalize, NULL},
4348 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4349 0, NULL, NULL, NULL},
4350 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4351 0, numericStringValidate, numericStringNormalize, NULL},
4352 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4353 0, NULL, NULL, NULL},
4354 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4355 0, oidValidate, NULL, NULL},
4356 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4357 0, IA5StringValidate, IA5StringNormalize, NULL},
4358 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4359 0, blobValidate, NULL, NULL},
4360 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4361 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4362 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4363 0, NULL, NULL, NULL},
4364 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4365 0, NULL, NULL, NULL},
4366 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4367 0, printableStringValidate, IA5StringNormalize, NULL},
4368 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4369 X_BINARY X_NOT_H_R ")",
4370 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4371 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4372 X_BINARY X_NOT_H_R ")",
4373 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4374 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4375 0, printableStringValidate, telephoneNumberNormalize, NULL},
4376 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4377 0, NULL, NULL, NULL},
4378 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4379 0, printablesStringValidate, IA5StringNormalize, NULL},
4380 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4381 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4382 0, utcTimeValidate, utcTimeNormalize, NULL},
4384 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4385 0, NULL, NULL, NULL},
4386 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4387 0, NULL, NULL, NULL},
4388 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4389 0, NULL, NULL, NULL},
4390 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4391 0, NULL, NULL, NULL},
4392 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4393 0, NULL, NULL, NULL},
4395 /* RFC 2307 NIS Syntaxes */
4396 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4397 0, nisNetgroupTripleValidate, NULL, NULL},
4398 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4399 0, bootParameterValidate, NULL, NULL},
4403 /* These OIDs are not published yet, but will be in the next
4404 * I-D for PKIX LDAPv3 schema as have been advanced by David
4405 * Chadwick in private mail.
4407 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4408 0, NULL, NULL, NULL},
4411 /* OpenLDAP Experimental Syntaxes */
4412 #ifdef SLAPD_ACI_ENABLED
4413 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4415 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4419 #ifdef SLAPD_AUTHPASSWD
4420 /* needs updating */
4421 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4422 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4425 /* OpenLDAP Void Syntax */
4426 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4427 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4428 {NULL, 0, NULL, NULL, NULL}
4432 * Other matching rules in X.520 that we do not use (yet):
4434 * 2.5.13.9 numericStringOrderingMatch
4435 * 2.5.13.18 octetStringOrderingMatch
4436 * 2.5.13.19 octetStringSubstringsMatch
4437 * 2.5.13.25 uTCTimeMatch
4438 * 2.5.13.26 uTCTimeOrderingMatch
4439 * 2.5.13.31 directoryStringFirstComponentMatch
4440 * 2.5.13.32 wordMatch
4441 * 2.5.13.33 keywordMatch
4442 * 2.5.13.35 certificateMatch
4443 * 2.5.13.36 certificatePairExactMatch
4444 * 2.5.13.37 certificatePairMatch
4445 * 2.5.13.38 certificateListExactMatch
4446 * 2.5.13.39 certificateListMatch
4447 * 2.5.13.40 algorithmIdentifierMatch
4448 * 2.5.13.41 storedPrefixMatch
4449 * 2.5.13.42 attributeCertificateMatch
4450 * 2.5.13.43 readerAndKeyIDMatch
4451 * 2.5.13.44 attributeIntegrityMatch
4453 static struct mrule_defs_rec {
4455 slap_mask_t mrd_usage;
4456 slap_mr_convert_func * mrd_convert;
4457 slap_mr_normalize_func * mrd_normalize;
4458 slap_mr_match_func * mrd_match;
4459 slap_mr_indexer_func * mrd_indexer;
4460 slap_mr_filter_func * mrd_filter;
4462 char * mrd_associated;
4465 * EQUALITY matching rules must be listed after associated APPROX
4466 * matching rules. So, we list all APPROX matching rules first.
4468 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4469 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4470 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4472 directoryStringApproxMatch,
4473 directoryStringApproxIndexer,
4474 directoryStringApproxFilter,
4477 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4478 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4479 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4481 IA5StringApproxMatch,
4482 IA5StringApproxIndexer,
4483 IA5StringApproxFilter,
4487 * Other matching rules
4490 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4491 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4492 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4494 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4497 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4498 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4499 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4501 dnMatch, dnIndexer, dnFilter,
4504 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4505 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4506 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4508 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4509 directoryStringApproxMatchOID },
4511 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4512 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4515 caseIgnoreOrderingMatch, NULL, NULL,
4518 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4519 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4520 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4522 caseExactIgnoreSubstringsMatch,
4523 caseExactIgnoreSubstringsIndexer,
4524 caseExactIgnoreSubstringsFilter,
4527 {"( 2.5.13.5 NAME 'caseExactMatch' "
4528 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4529 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4531 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4532 directoryStringApproxMatchOID },
4534 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4535 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4538 caseExactOrderingMatch, NULL, NULL,
4541 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4542 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4543 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4545 caseExactIgnoreSubstringsMatch,
4546 caseExactIgnoreSubstringsIndexer,
4547 caseExactIgnoreSubstringsFilter,
4550 {"( 2.5.13.8 NAME 'numericStringMatch' "
4551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4552 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4555 caseIgnoreIA5Indexer,
4556 caseIgnoreIA5Filter,
4559 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4560 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4561 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4563 caseIgnoreIA5SubstringsMatch,
4564 caseIgnoreIA5SubstringsIndexer,
4565 caseIgnoreIA5SubstringsFilter,
4568 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4569 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4570 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4572 caseIgnoreListMatch, NULL, NULL,
4575 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4577 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4579 caseIgnoreListSubstringsMatch, NULL, NULL,
4582 {"( 2.5.13.13 NAME 'booleanMatch' "
4583 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4584 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4586 booleanMatch, NULL, NULL,
4589 {"( 2.5.13.14 NAME 'integerMatch' "
4590 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4591 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4593 integerMatch, integerIndexer, integerFilter,
4596 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4597 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4600 integerOrderingMatch, NULL, NULL,
4603 {"( 2.5.13.16 NAME 'bitStringMatch' "
4604 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4605 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4607 bitStringMatch, bitStringIndexer, bitStringFilter,
4610 {"( 2.5.13.17 NAME 'octetStringMatch' "
4611 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4612 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4614 octetStringMatch, octetStringIndexer, octetStringFilter,
4617 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4618 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4619 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4621 telephoneNumberMatch,
4622 telephoneNumberIndexer,
4623 telephoneNumberFilter,
4626 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4628 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4630 telephoneNumberSubstringsMatch,
4631 telephoneNumberSubstringsIndexer,
4632 telephoneNumberSubstringsFilter,
4635 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4636 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4637 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4642 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4643 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4644 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4646 uniqueMemberMatch, NULL, NULL,
4649 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4651 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4653 protocolInformationMatch, NULL, NULL,
4656 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4657 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4658 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4660 generalizedTimeMatch, NULL, NULL,
4663 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4664 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4667 generalizedTimeOrderingMatch, NULL, NULL,
4670 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4671 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4672 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4674 integerFirstComponentMatch, NULL, NULL,
4677 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4678 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4679 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4681 objectIdentifierFirstComponentMatch, NULL, NULL,
4685 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4686 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4687 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4688 certificateExactConvert, NULL,
4689 certificateExactMatch,
4690 certificateExactIndexer, certificateExactFilter,
4694 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4695 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4696 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4698 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4699 IA5StringApproxMatchOID },
4701 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4702 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4703 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4705 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4706 IA5StringApproxMatchOID },
4708 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4709 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4712 caseIgnoreIA5SubstringsMatch,
4713 caseIgnoreIA5SubstringsIndexer,
4714 caseIgnoreIA5SubstringsFilter,
4717 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4718 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4721 caseExactIA5SubstringsMatch,
4722 caseExactIA5SubstringsIndexer,
4723 caseExactIA5SubstringsFilter,
4726 #ifdef SLAPD_AUTHPASSWD
4727 /* needs updating */
4728 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4729 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4732 authPasswordMatch, NULL, NULL,
4736 #ifdef SLAPD_ACI_ENABLED
4737 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4738 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4741 OpenLDAPaciMatch, NULL, NULL,
4745 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4746 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4749 integerBitAndMatch, NULL, NULL,
4752 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4753 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4756 integerBitOrMatch, NULL, NULL,
4759 {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4763 slap_schema_init( void )
4768 /* we should only be called once (from main) */
4769 assert( schema_init_done == 0 );
4771 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4772 res = register_syntax( syntax_defs[i].sd_desc,
4773 syntax_defs[i].sd_flags,
4774 syntax_defs[i].sd_validate,
4775 syntax_defs[i].sd_normalize,
4776 syntax_defs[i].sd_pretty
4777 #ifdef SLAPD_BINARY_CONVERSION
4779 syntax_defs[i].sd_ber2str,
4780 syntax_defs[i].sd_str2ber
4785 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4786 syntax_defs[i].sd_desc );
4791 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4792 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4794 "slap_schema_init: Ingoring unusable matching rule %s\n",
4795 mrule_defs[i].mrd_desc );
4799 res = register_matching_rule(
4800 mrule_defs[i].mrd_desc,
4801 mrule_defs[i].mrd_usage,
4802 mrule_defs[i].mrd_convert,
4803 mrule_defs[i].mrd_normalize,
4804 mrule_defs[i].mrd_match,
4805 mrule_defs[i].mrd_indexer,
4806 mrule_defs[i].mrd_filter,
4807 mrule_defs[i].mrd_associated );
4811 "slap_schema_init: Error registering matching rule %s\n",
4812 mrule_defs[i].mrd_desc );
4817 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4818 *mr_ptr[i].mr = mr_find( mr_ptr[i].oid );
4820 res = slap_schema_load();
4821 schema_init_done = 1;
4826 schema_destroy( void )
4832 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4833 *mr_ptr[i].mr = NULL;