1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
15 #include <ac/string.h>
16 #include <ac/socket.h>
22 #include "ldap_utf8.h"
24 #include "lutil_hash.h"
25 #define HASH_BYTES LUTIL_HASH_BYTES
26 #define HASH_CONTEXT lutil_HASH_CTX
27 #define HASH_Init(c) lutil_HASHInit(c)
28 #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
29 #define HASH_Final(d,c) lutil_HASHFinal(d,c)
31 /* recycled validatation routines */
32 #define berValidate blobValidate
34 /* unimplemented pretters */
35 #define integerPretty NULL
37 /* recycled matching routines */
38 #define bitStringMatch octetStringMatch
39 #define numericStringMatch caseIgnoreIA5Match
40 #define objectIdentifierMatch octetStringMatch
41 #define telephoneNumberMatch caseIgnoreIA5Match
42 #define telephoneNumberSubstringsMatch caseIgnoreIA5SubstringsMatch
43 #define generalizedTimeMatch caseIgnoreIA5Match
44 #define generalizedTimeOrderingMatch caseIgnoreIA5Match
45 #define uniqueMemberMatch dnMatch
46 #define integerFirstComponentMatch integerMatch
48 /* approx matching rules */
49 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
50 #define directoryStringApproxMatch approxMatch
51 #define directoryStringApproxIndexer approxIndexer
52 #define directoryStringApproxFilter approxFilter
53 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
54 #define IA5StringApproxMatch approxMatch
55 #define IA5StringApproxIndexer approxIndexer
56 #define IA5StringApproxFilter approxFilter
58 /* ordering matching rules */
59 #define caseIgnoreOrderingMatch caseIgnoreMatch
60 #define caseExactOrderingMatch caseExactMatch
61 #define integerOrderingMatch integerMatch
62 #define octetStringOrderingMatch octetStringMatch
64 /* unimplemented matching routines */
65 #define caseIgnoreListMatch NULL
66 #define caseIgnoreListSubstringsMatch NULL
67 #define protocolInformationMatch NULL
69 #ifdef SLAPD_ACI_ENABLED
70 #define OpenLDAPaciMatch NULL
72 #ifdef SLAPD_AUTHPASSWD
73 #define authPasswordMatch NULL
76 /* recycled indexing/filtering routines */
77 #define dnIndexer caseExactIgnoreIndexer
78 #define dnFilter caseExactIgnoreFilter
79 #define bitStringFilter octetStringFilter
80 #define bitStringIndexer octetStringIndexer
82 #define telephoneNumberIndexer caseIgnoreIA5Indexer
83 #define telephoneNumberFilter caseIgnoreIA5Filter
84 #define telephoneNumberSubstringsIndexer caseIgnoreIA5SubstringsIndexer
85 #define telephoneNumberSubstringsFilter caseIgnoreIA5SubstringsFilter
87 static MatchingRule *caseExactMatchingRule;
88 static MatchingRule *caseExactSubstringsMatchingRule;
89 static MatchingRule *integerFirstComponentMatchingRule;
91 static const struct MatchingRulePtr {
95 /* must match OIDs below */
96 { "2.5.13.5", &caseExactMatchingRule },
97 { "2.5.13.7", &caseExactSubstringsMatchingRule },
98 { "2.5.13.29", &integerFirstComponentMatchingRule }
102 static char *bvcasechr( struct berval *bv, unsigned char c, ber_len_t *len )
105 char lower = TOLOWER( c );
106 char upper = TOUPPER( c );
108 if( c == 0 ) return NULL;
110 for( i=0; i < bv->bv_len; i++ ) {
111 if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
113 return &bv->bv_val[i];
126 struct berval *value,
127 void *assertedValue )
129 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
132 match = memcmp( value->bv_val,
133 ((struct berval *) assertedValue)->bv_val,
141 /* Index generation function */
142 int octetStringIndexer(
147 struct berval *prefix,
154 HASH_CONTEXT HASHcontext;
155 unsigned char HASHdigest[HASH_BYTES];
156 struct berval digest;
157 digest.bv_val = HASHdigest;
158 digest.bv_len = sizeof(HASHdigest);
160 for( i=0; values[i].bv_val != NULL; i++ ) {
161 /* just count them */
164 /* we should have at least one value at this point */
167 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
169 slen = syntax->ssyn_oidlen;
170 mlen = mr->smr_oidlen;
172 for( i=0; values[i].bv_val != NULL; i++ ) {
173 HASH_Init( &HASHcontext );
174 if( prefix != NULL && prefix->bv_len > 0 ) {
175 HASH_Update( &HASHcontext,
176 prefix->bv_val, prefix->bv_len );
178 HASH_Update( &HASHcontext,
179 syntax->ssyn_oid, slen );
180 HASH_Update( &HASHcontext,
182 HASH_Update( &HASHcontext,
183 values[i].bv_val, values[i].bv_len );
184 HASH_Final( HASHdigest, &HASHcontext );
186 ber_dupbv( &keys[i], &digest );
189 keys[i].bv_val = NULL;
197 /* Index generation function */
198 int octetStringFilter(
203 struct berval *prefix,
204 void * assertedValue,
209 HASH_CONTEXT HASHcontext;
210 unsigned char HASHdigest[HASH_BYTES];
211 struct berval *value = (struct berval *) assertedValue;
212 struct berval digest;
213 digest.bv_val = HASHdigest;
214 digest.bv_len = sizeof(HASHdigest);
216 slen = syntax->ssyn_oidlen;
217 mlen = mr->smr_oidlen;
219 keys = ch_malloc( sizeof( struct berval ) * 2 );
221 HASH_Init( &HASHcontext );
222 if( prefix != NULL && prefix->bv_len > 0 ) {
223 HASH_Update( &HASHcontext,
224 prefix->bv_val, prefix->bv_len );
226 HASH_Update( &HASHcontext,
227 syntax->ssyn_oid, slen );
228 HASH_Update( &HASHcontext,
230 HASH_Update( &HASHcontext,
231 value->bv_val, value->bv_len );
232 HASH_Final( HASHdigest, &HASHcontext );
234 ber_dupbv( keys, &digest );
235 keys[1].bv_val = NULL;
248 /* no value allowed */
249 return LDAP_INVALID_SYNTAX;
257 /* any value allowed */
268 /* very unforgiving validation, requires no normalization
269 * before simplistic matching
271 if( in->bv_len < 3 ) {
272 return LDAP_INVALID_SYNTAX;
276 * rfc 2252 section 6.3 Bit String
277 * bitstring = "'" *binary-digit "'"
278 * binary-digit = "0" / "1"
279 * example: '0101111101'B
282 if( in->bv_val[0] != '\'' ||
283 in->bv_val[in->bv_len-2] != '\'' ||
284 in->bv_val[in->bv_len-1] != 'B' )
286 return LDAP_INVALID_SYNTAX;
289 for( i=in->bv_len-3; i>0; i-- ) {
290 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
291 return LDAP_INVALID_SYNTAX;
306 if( in->bv_len == 0 ) return LDAP_SUCCESS;
308 ber_dupbv( &dn, in );
309 if( !dn.bv_val ) return LDAP_OTHER;
311 if( dn.bv_val[dn.bv_len-1] == 'B'
312 && dn.bv_val[dn.bv_len-2] == '\'' )
314 /* assume presence of optional UID */
317 for(i=dn.bv_len-3; i>1; i--) {
318 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
322 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
323 ber_memfree( dn.bv_val );
324 return LDAP_INVALID_SYNTAX;
327 /* trim the UID to allow use of dnValidate */
328 dn.bv_val[i-1] = '\0';
332 rc = dnValidate( NULL, &dn );
334 ber_memfree( dn.bv_val );
342 struct berval *normalized )
347 ber_dupbv( &out, val );
348 if( out.bv_len != 0 ) {
349 struct berval uid = { 0, NULL };
351 if( out.bv_val[out.bv_len-1] == 'B'
352 && out.bv_val[out.bv_len-2] == '\'' )
354 /* assume presence of optional UID */
355 uid.bv_val = strrchr( out.bv_val, '#' );
357 if( uid.bv_val == NULL ) {
359 return LDAP_INVALID_SYNTAX;
362 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
363 out.bv_len -= uid.bv_len--;
365 /* temporarily trim the UID */
366 *(uid.bv_val++) = '\0';
369 rc = dnNormalize2( NULL, &out, normalized );
371 if( rc != LDAP_SUCCESS ) {
373 return LDAP_INVALID_SYNTAX;
377 normalized->bv_val = ch_realloc( normalized->bv_val,
378 normalized->bv_len + uid.bv_len + sizeof("#") );
380 /* insert the separator */
381 normalized->bv_val[normalized->bv_len++] = '#';
384 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
385 uid.bv_val, uid.bv_len );
386 normalized->bv_len += uid.bv_len;
389 normalized->bv_val[normalized->bv_len] = '\0';
399 * Handling boolean syntax and matching is quite rigid.
400 * A more flexible approach would be to allow a variety
401 * of strings to be normalized and prettied into TRUE
409 /* very unforgiving validation, requires no normalization
410 * before simplistic matching
413 if( in->bv_len == 4 ) {
414 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
417 } else if( in->bv_len == 5 ) {
418 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
423 return LDAP_INVALID_SYNTAX;
432 struct berval *value,
433 void *assertedValue )
435 /* simplistic matching allowed by rigid validation */
436 struct berval *asserted = (struct berval *) assertedValue;
437 *matchp = value->bv_len != asserted->bv_len;
441 /*-------------------------------------------------------------------
442 LDAP/X.500 string syntax / matching rules have a few oddities. This
443 comment attempts to detail how slapd(8) treats them.
446 StringSyntax X.500 LDAP Matching
447 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
448 PrintableString subset subset i/e + ignore insignificant spaces
449 NumericString subset subset ignore all spaces
450 IA5String ASCII ASCII i/e + ignore insignificant spaces
451 TeletexString T.61 T.61 i/e + ignore insignificant spaces
453 TelephoneNumber subset subset i + ignore all spaces and "-"
455 See draft-ietf-ldapbis-strpro for details (once published).
459 In X.500(93), a directory string can be either a PrintableString,
460 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
461 In later versions, more CHOICEs were added. In all cases the string
464 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
466 For matching, there are both case ignore and exact rules. Both
467 also require that "insignificant" spaces be ignored.
468 spaces before the first non-space are ignored;
469 spaces after the last non-space are ignored;
470 spaces after a space are ignored.
471 Note: by these rules (and as clarified in X.520), a string of only
472 spaces is to be treated as if held one space, not empty (which
473 would be a syntax error).
476 In ASN.1, numeric string is just a string of digits and spaces
477 and could be empty. However, in X.500, all attribute values of
478 numeric string carry a non-empty constraint. For example:
480 internationalISDNNumber ATTRIBUTE ::= {
481 WITH SYNTAX InternationalISDNNumber
482 EQUALITY MATCHING RULE numericStringMatch
483 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
484 ID id-at-internationalISDNNumber }
485 InternationalISDNNumber ::=
486 NumericString (SIZE(1..ub-international-isdn-number))
488 Unforunately, some assertion values are don't carry the same
489 constraint (but its unclear how such an assertion could ever
490 be true). In LDAP, there is one syntax (numericString) not two
491 (numericString with constraint, numericString without constraint).
492 This should be treated as numericString with non-empty constraint.
493 Note that while someone may have no ISDN number, there are no ISDN
494 numbers which are zero length.
496 In matching, spaces are ignored.
499 In ASN.1, Printable string is just a string of printable characters
500 and can be empty. In X.500, semantics much like NumericString (see
501 serialNumber for a like example) excepting uses insignificant space
502 handling instead of ignore all spaces.
505 Basically same as PrintableString. There are no examples in X.500,
506 but same logic applies. So we require them to be non-empty as
509 -------------------------------------------------------------------*/
518 unsigned char *u = in->bv_val;
520 if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
522 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
523 /* get the length indicated by the first byte */
524 len = LDAP_UTF8_CHARLEN2( u, len );
526 /* very basic checks */
529 if( (u[5] & 0xC0) != 0x80 ) {
530 return LDAP_INVALID_SYNTAX;
533 if( (u[4] & 0xC0) != 0x80 ) {
534 return LDAP_INVALID_SYNTAX;
537 if( (u[3] & 0xC0) != 0x80 ) {
538 return LDAP_INVALID_SYNTAX;
541 if( (u[2] & 0xC0 )!= 0x80 ) {
542 return LDAP_INVALID_SYNTAX;
545 if( (u[1] & 0xC0) != 0x80 ) {
546 return LDAP_INVALID_SYNTAX;
549 /* CHARLEN already validated it */
552 return LDAP_INVALID_SYNTAX;
555 /* make sure len corresponds with the offset
556 to the next character */
557 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
560 if( count != 0 ) return LDAP_INVALID_SYNTAX;
569 struct berval *normalized )
574 /* validator should have refused an empty string */
575 assert( val->bv_len );
579 /* Ignore initial whitespace */
580 /* All space is ASCII. All ASCII is 1 byte */
581 for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
583 normalized->bv_len = val->bv_len - (p - val->bv_val);
585 if( !normalized->bv_len ) {
586 ber_mem2bv( " ", 1, 1, normalized );
590 ber_mem2bv( p, normalized->bv_len, 1, normalized );
591 e = normalized->bv_val + normalized->bv_len;
593 assert( normalized->bv_val );
595 p = q = normalized->bv_val;
600 if ( ASCII_SPACE( *p ) ) {
605 /* Ignore the extra whitespace */
606 while ( ASCII_SPACE( *p ) ) {
610 len = LDAP_UTF8_COPY(q,p);
616 assert( normalized->bv_val <= p );
617 assert( q+len <= p );
619 /* cannot start with a space */
620 assert( !ASCII_SPACE( normalized->bv_val[0] ) );
623 * If the string ended in space, backup the pointer one
624 * position. One is enough because the above loop collapsed
625 * all whitespace to a single space.
633 /* cannot end with a space */
634 assert( !ASCII_SPACE( *q ) );
641 normalized->bv_len = q - normalized->bv_val;
646 /* Returns Unicode canonically normalized copy of a substring assertion
647 * Skipping attribute description */
648 static SubstringsAssertion *
649 UTF8SubstringsassertionNormalize(
650 SubstringsAssertion *sa,
653 SubstringsAssertion *nsa;
656 nsa = (SubstringsAssertion *)SLAP_CALLOC( 1, sizeof(SubstringsAssertion) );
661 if( sa->sa_initial.bv_val != NULL ) {
662 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
663 if( nsa->sa_initial.bv_val == NULL ) {
668 if( sa->sa_any != NULL ) {
669 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
672 nsa->sa_any = (struct berval *)
673 SLAP_MALLOC( (i + 1) * sizeof(struct berval) );
674 if( nsa->sa_any == NULL ) {
678 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
679 UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
681 if( nsa->sa_any[i].bv_val == NULL ) {
685 nsa->sa_any[i].bv_val = NULL;
688 if( sa->sa_final.bv_val != NULL ) {
689 UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
690 if( nsa->sa_final.bv_val == NULL ) {
698 if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
699 if ( nsa->sa_any ) ber_bvarray_free( nsa->sa_any );
700 if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
705 #ifndef SLAPD_APPROX_OLDSINGLESTRING
707 #if defined(SLAPD_APPROX_INITIALS)
708 #define SLAPD_APPROX_DELIMITER "._ "
709 #define SLAPD_APPROX_WORDLEN 2
711 #define SLAPD_APPROX_DELIMITER " "
712 #define SLAPD_APPROX_WORDLEN 1
721 struct berval *value,
722 void *assertedValue )
724 struct berval *nval, *assertv;
725 char *val, **values, **words, *c;
726 int i, count, len, nextchunk=0, nextavail=0;
728 /* Yes, this is necessary */
729 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
735 /* Yes, this is necessary */
736 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
737 NULL, LDAP_UTF8_APPROX );
738 if( assertv == NULL ) {
744 /* Isolate how many words there are */
745 for ( c = nval->bv_val, count = 1; *c; c++ ) {
746 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
747 if ( c == NULL ) break;
752 /* Get a phonetic copy of each word */
753 words = (char **)ch_malloc( count * sizeof(char *) );
754 values = (char **)ch_malloc( count * sizeof(char *) );
755 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
757 values[i] = phonetic(c);
760 /* Work through the asserted value's words, to see if at least some
761 of the words are there, in the same order. */
763 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
764 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
769 #if defined(SLAPD_APPROX_INITIALS)
770 else if( len == 1 ) {
771 /* Single letter words need to at least match one word's initial */
772 for( i=nextavail; i<count; i++ )
773 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
780 /* Isolate the next word in the asserted value and phonetic it */
781 assertv->bv_val[nextchunk+len] = '\0';
782 val = phonetic( assertv->bv_val + nextchunk );
784 /* See if this phonetic chunk is in the remaining words of *value */
785 for( i=nextavail; i<count; i++ ){
786 if( !strcmp( val, values[i] ) ){
794 /* This chunk in the asserted value was NOT within the *value. */
800 /* Go on to the next word in the asserted value */
804 /* If some of the words were seen, call it a match */
805 if( nextavail > 0 ) {
813 ber_bvfree( assertv );
814 for( i=0; i<count; i++ ) {
815 ch_free( values[i] );
830 struct berval *prefix,
835 int i,j, len, wordcount, keycount=0;
836 struct berval *newkeys;
839 for( j=0; values[j].bv_val != NULL; j++ ) {
840 struct berval val = { 0, NULL };
841 /* Yes, this is necessary */
842 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
843 assert( val.bv_val != NULL );
845 /* Isolate how many words there are. There will be a key for each */
846 for( wordcount = 0, c = val.bv_val; *c; c++) {
847 len = strcspn(c, SLAPD_APPROX_DELIMITER);
848 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
850 if (*c == '\0') break;
854 /* Allocate/increase storage to account for new keys */
855 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
856 * sizeof(struct berval) );
857 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
858 if( keys ) ch_free( keys );
861 /* Get a phonetic copy of each word */
862 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
864 if( len < SLAPD_APPROX_WORDLEN ) continue;
865 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
870 ber_memfree( val.bv_val );
872 keys[keycount].bv_val = NULL;
884 struct berval *prefix,
885 void * assertedValue,
893 /* Yes, this is necessary */
894 val = UTF8bvnormalize( ((struct berval *)assertedValue),
895 NULL, LDAP_UTF8_APPROX );
896 if( val == NULL || val->bv_val == NULL ) {
897 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
898 keys[0].bv_val = NULL;
904 /* Isolate how many words there are. There will be a key for each */
905 for( count = 0,c = val->bv_val; *c; c++) {
906 len = strcspn(c, SLAPD_APPROX_DELIMITER);
907 if( len >= SLAPD_APPROX_WORDLEN ) count++;
909 if (*c == '\0') break;
913 /* Allocate storage for new keys */
914 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
916 /* Get a phonetic copy of each word */
917 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
919 if( len < SLAPD_APPROX_WORDLEN ) continue;
920 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
926 keys[count].bv_val = NULL;
934 /* No other form of Approximate Matching is defined */
942 struct berval *value,
943 void *assertedValue )
945 char *vapprox, *avapprox;
948 /* Yes, this is necessary */
949 s = UTF8normalize( value, UTF8_NOCASEFOLD );
955 /* Yes, this is necessary */
956 t = UTF8normalize( ((struct berval *)assertedValue),
964 vapprox = phonetic( strip8bitChars( s ) );
965 avapprox = phonetic( strip8bitChars( t ) );
970 *matchp = strcmp( vapprox, avapprox );
984 struct berval *prefix,
992 for( i=0; values[i].bv_val != NULL; i++ ) {
993 /* empty - just count them */
996 /* we should have at least one value at this point */
999 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1001 /* Copy each value and run it through phonetic() */
1002 for( i=0; values[i].bv_val != NULL; i++ ) {
1003 /* Yes, this is necessary */
1004 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1006 /* strip 8-bit chars and run through phonetic() */
1007 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1010 keys[i].bv_val = NULL;
1013 return LDAP_SUCCESS;
1023 struct berval *prefix,
1024 void * assertedValue,
1030 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1032 /* Yes, this is necessary */
1033 s = UTF8normalize( ((struct berval *)assertedValue),
1038 /* strip 8-bit chars and run through phonetic() */
1039 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1045 return LDAP_SUCCESS;
1056 struct berval *value,
1057 void *assertedValue )
1059 *matchp = UTF8bvnormcmp( value,
1060 (struct berval *) assertedValue,
1061 LDAP_UTF8_NOCASEFOLD );
1062 return LDAP_SUCCESS;
1066 caseExactIgnoreSubstringsMatch(
1071 struct berval *value,
1072 void *assertedValue )
1075 SubstringsAssertion *sub = NULL;
1076 struct berval left = { 0, NULL };
1082 casefold = ( mr != caseExactSubstringsMatchingRule )
1083 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1085 if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1091 sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1097 /* Add up asserted input length */
1098 if( sub->sa_initial.bv_val ) {
1099 inlen += sub->sa_initial.bv_len;
1102 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1103 inlen += sub->sa_any[i].bv_len;
1106 if( sub->sa_final.bv_val ) {
1107 inlen += sub->sa_final.bv_len;
1110 if( sub->sa_initial.bv_val ) {
1111 if( inlen > left.bv_len ) {
1116 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1117 sub->sa_initial.bv_len );
1123 left.bv_val += sub->sa_initial.bv_len;
1124 left.bv_len -= sub->sa_initial.bv_len;
1125 inlen -= sub->sa_initial.bv_len;
1128 if( sub->sa_final.bv_val ) {
1129 if( inlen > left.bv_len ) {
1134 match = memcmp( sub->sa_final.bv_val,
1135 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1136 sub->sa_final.bv_len );
1142 left.bv_len -= sub->sa_final.bv_len;
1143 inlen -= sub->sa_final.bv_len;
1147 for(i=0; sub->sa_any[i].bv_val; i++) {
1152 if( inlen > left.bv_len ) {
1153 /* not enough length */
1158 if( sub->sa_any[i].bv_len == 0 ) {
1162 p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1168 idx = p - left.bv_val;
1170 if( idx >= left.bv_len ) {
1171 /* this shouldn't happen */
1173 if ( sub->sa_final.bv_val )
1174 ch_free( sub->sa_final.bv_val );
1176 ber_bvarray_free( sub->sa_any );
1177 if ( sub->sa_initial.bv_val )
1178 ch_free( sub->sa_initial.bv_val );
1186 if( sub->sa_any[i].bv_len > left.bv_len ) {
1187 /* not enough left */
1192 match = memcmp( left.bv_val,
1193 sub->sa_any[i].bv_val,
1194 sub->sa_any[i].bv_len );
1202 left.bv_val += sub->sa_any[i].bv_len;
1203 left.bv_len -= sub->sa_any[i].bv_len;
1204 inlen -= sub->sa_any[i].bv_len;
1211 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1212 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1213 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1217 return LDAP_SUCCESS;
1220 /* Index generation function */
1221 static int caseExactIgnoreIndexer(
1226 struct berval *prefix,
1234 HASH_CONTEXT HASHcontext;
1235 unsigned char HASHdigest[HASH_BYTES];
1236 struct berval digest;
1237 digest.bv_val = HASHdigest;
1238 digest.bv_len = sizeof(HASHdigest);
1240 for( i=0; values[i].bv_val != NULL; i++ ) {
1241 /* empty - just count them */
1244 /* we should have at least one value at this point */
1247 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1249 slen = syntax->ssyn_oidlen;
1250 mlen = mr->smr_oidlen;
1252 casefold = ( mr != caseExactMatchingRule )
1253 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1255 for( i=0; values[i].bv_val != NULL; i++ ) {
1256 struct berval value;
1257 UTF8bvnormalize( &values[i], &value, casefold );
1259 HASH_Init( &HASHcontext );
1260 if( prefix != NULL && prefix->bv_len > 0 ) {
1261 HASH_Update( &HASHcontext,
1262 prefix->bv_val, prefix->bv_len );
1264 HASH_Update( &HASHcontext,
1265 syntax->ssyn_oid, slen );
1266 HASH_Update( &HASHcontext,
1267 mr->smr_oid, mlen );
1268 HASH_Update( &HASHcontext,
1269 value.bv_val, value.bv_len );
1270 HASH_Final( HASHdigest, &HASHcontext );
1272 free( value.bv_val );
1274 ber_dupbv( &keys[i], &digest );
1277 keys[i].bv_val = NULL;
1279 return LDAP_SUCCESS;
1282 /* Index generation function */
1283 static int caseExactIgnoreFilter(
1288 struct berval *prefix,
1289 void * assertedValue,
1295 HASH_CONTEXT HASHcontext;
1296 unsigned char HASHdigest[HASH_BYTES];
1297 struct berval value = { 0, NULL };
1298 struct berval digest;
1300 digest.bv_val = HASHdigest;
1301 digest.bv_len = sizeof(HASHdigest);
1303 slen = syntax->ssyn_oidlen;
1304 mlen = mr->smr_oidlen;
1306 casefold = ( mr != caseExactMatchingRule )
1307 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1309 UTF8bvnormalize( (struct berval *) assertedValue, &value, casefold );
1310 /* This usually happens if filter contains bad UTF8 */
1311 if( value.bv_val == NULL ) {
1312 keys = ch_malloc( sizeof( struct berval ) );
1313 keys[0].bv_val = NULL;
1314 return LDAP_SUCCESS;
1317 keys = ch_malloc( sizeof( struct berval ) * 2 );
1319 HASH_Init( &HASHcontext );
1320 if( prefix != NULL && prefix->bv_len > 0 ) {
1321 HASH_Update( &HASHcontext,
1322 prefix->bv_val, prefix->bv_len );
1324 HASH_Update( &HASHcontext,
1325 syntax->ssyn_oid, slen );
1326 HASH_Update( &HASHcontext,
1327 mr->smr_oid, mlen );
1328 HASH_Update( &HASHcontext,
1329 value.bv_val, value.bv_len );
1330 HASH_Final( HASHdigest, &HASHcontext );
1332 ber_dupbv( keys, &digest );
1333 keys[1].bv_val = NULL;
1335 free( value.bv_val );
1338 return LDAP_SUCCESS;
1341 /* Substrings Index generation function */
1342 static int caseExactIgnoreSubstringsIndexer(
1347 struct berval *prefix,
1357 HASH_CONTEXT HASHcontext;
1358 unsigned char HASHdigest[HASH_BYTES];
1359 struct berval digest;
1360 digest.bv_val = HASHdigest;
1361 digest.bv_len = sizeof(HASHdigest);
1365 for( i=0; values[i].bv_val != NULL; i++ ) {
1366 /* empty - just count them */
1369 /* we should have at least one value at this point */
1372 casefold = ( mr != caseExactSubstringsMatchingRule )
1373 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1375 nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1376 for( i=0; values[i].bv_val != NULL; i++ ) {
1377 UTF8bvnormalize( &values[i], &nvalues[i], casefold );
1379 nvalues[i].bv_val = NULL;
1382 for( i=0; values[i].bv_val != NULL; i++ ) {
1383 /* count number of indices to generate */
1384 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1388 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1389 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1390 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1391 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1393 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1397 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1398 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1399 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1403 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1404 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1405 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1406 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1408 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1414 /* no keys to generate */
1416 ber_bvarray_free( nvalues );
1417 return LDAP_SUCCESS;
1420 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1422 slen = syntax->ssyn_oidlen;
1423 mlen = mr->smr_oidlen;
1426 for( i=0; values[i].bv_val != NULL; i++ ) {
1429 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1431 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1432 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1434 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1435 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1437 for( j=0; j<max; j++ ) {
1438 HASH_Init( &HASHcontext );
1439 if( prefix != NULL && prefix->bv_len > 0 ) {
1440 HASH_Update( &HASHcontext,
1441 prefix->bv_val, prefix->bv_len );
1444 HASH_Update( &HASHcontext,
1445 &pre, sizeof( pre ) );
1446 HASH_Update( &HASHcontext,
1447 syntax->ssyn_oid, slen );
1448 HASH_Update( &HASHcontext,
1449 mr->smr_oid, mlen );
1450 HASH_Update( &HASHcontext,
1451 &values[i].bv_val[j],
1452 SLAP_INDEX_SUBSTR_MAXLEN );
1453 HASH_Final( HASHdigest, &HASHcontext );
1455 ber_dupbv( &keys[nkeys++], &digest );
1459 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1460 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1462 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1465 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1466 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1467 HASH_Init( &HASHcontext );
1468 if( prefix != NULL && prefix->bv_len > 0 ) {
1469 HASH_Update( &HASHcontext,
1470 prefix->bv_val, prefix->bv_len );
1472 HASH_Update( &HASHcontext,
1473 &pre, sizeof( pre ) );
1474 HASH_Update( &HASHcontext,
1475 syntax->ssyn_oid, slen );
1476 HASH_Update( &HASHcontext,
1477 mr->smr_oid, mlen );
1478 HASH_Update( &HASHcontext,
1479 values[i].bv_val, j );
1480 HASH_Final( HASHdigest, &HASHcontext );
1482 ber_dupbv( &keys[nkeys++], &digest );
1485 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1486 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1487 HASH_Init( &HASHcontext );
1488 if( prefix != NULL && prefix->bv_len > 0 ) {
1489 HASH_Update( &HASHcontext,
1490 prefix->bv_val, prefix->bv_len );
1492 HASH_Update( &HASHcontext,
1493 &pre, sizeof( pre ) );
1494 HASH_Update( &HASHcontext,
1495 syntax->ssyn_oid, slen );
1496 HASH_Update( &HASHcontext,
1497 mr->smr_oid, mlen );
1498 HASH_Update( &HASHcontext,
1499 &values[i].bv_val[values[i].bv_len-j], j );
1500 HASH_Final( HASHdigest, &HASHcontext );
1502 ber_dupbv( &keys[nkeys++], &digest );
1510 keys[nkeys].bv_val = NULL;
1517 ber_bvarray_free( nvalues );
1519 return LDAP_SUCCESS;
1522 static int caseExactIgnoreSubstringsFilter(
1527 struct berval *prefix,
1528 void * assertedValue,
1531 SubstringsAssertion *sa;
1534 ber_len_t nkeys = 0;
1535 size_t slen, mlen, klen;
1537 HASH_CONTEXT HASHcontext;
1538 unsigned char HASHdigest[HASH_BYTES];
1539 struct berval *value;
1540 struct berval digest;
1542 casefold = ( mr != caseExactSubstringsMatchingRule )
1543 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1545 sa = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1548 return LDAP_SUCCESS;
1551 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1552 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1557 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1559 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1560 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1561 /* don't bother accounting for stepping */
1562 nkeys += sa->sa_any[i].bv_len -
1563 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1568 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1569 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1575 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1576 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1577 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1580 return LDAP_SUCCESS;
1583 digest.bv_val = HASHdigest;
1584 digest.bv_len = sizeof(HASHdigest);
1586 slen = syntax->ssyn_oidlen;
1587 mlen = mr->smr_oidlen;
1589 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1592 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1593 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1595 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1596 value = &sa->sa_initial;
1598 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1599 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1601 HASH_Init( &HASHcontext );
1602 if( prefix != NULL && prefix->bv_len > 0 ) {
1603 HASH_Update( &HASHcontext,
1604 prefix->bv_val, prefix->bv_len );
1606 HASH_Update( &HASHcontext,
1607 &pre, sizeof( pre ) );
1608 HASH_Update( &HASHcontext,
1609 syntax->ssyn_oid, slen );
1610 HASH_Update( &HASHcontext,
1611 mr->smr_oid, mlen );
1612 HASH_Update( &HASHcontext,
1613 value->bv_val, klen );
1614 HASH_Final( HASHdigest, &HASHcontext );
1616 ber_dupbv( &keys[nkeys++], &digest );
1619 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1621 pre = SLAP_INDEX_SUBSTR_PREFIX;
1622 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1624 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1625 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1629 value = &sa->sa_any[i];
1632 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1633 j += SLAP_INDEX_SUBSTR_STEP )
1635 HASH_Init( &HASHcontext );
1636 if( prefix != NULL && prefix->bv_len > 0 ) {
1637 HASH_Update( &HASHcontext,
1638 prefix->bv_val, prefix->bv_len );
1640 HASH_Update( &HASHcontext,
1641 &pre, sizeof( pre ) );
1642 HASH_Update( &HASHcontext,
1643 syntax->ssyn_oid, slen );
1644 HASH_Update( &HASHcontext,
1645 mr->smr_oid, mlen );
1646 HASH_Update( &HASHcontext,
1647 &value->bv_val[j], klen );
1648 HASH_Final( HASHdigest, &HASHcontext );
1650 ber_dupbv( &keys[nkeys++], &digest );
1656 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1657 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1659 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1660 value = &sa->sa_final;
1662 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1663 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1665 HASH_Init( &HASHcontext );
1666 if( prefix != NULL && prefix->bv_len > 0 ) {
1667 HASH_Update( &HASHcontext,
1668 prefix->bv_val, prefix->bv_len );
1670 HASH_Update( &HASHcontext,
1671 &pre, sizeof( pre ) );
1672 HASH_Update( &HASHcontext,
1673 syntax->ssyn_oid, slen );
1674 HASH_Update( &HASHcontext,
1675 mr->smr_oid, mlen );
1676 HASH_Update( &HASHcontext,
1677 &value->bv_val[value->bv_len-klen], klen );
1678 HASH_Final( HASHdigest, &HASHcontext );
1680 ber_dupbv( &keys[nkeys++], &digest );
1684 keys[nkeys].bv_val = NULL;
1690 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1691 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1692 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1695 return LDAP_SUCCESS;
1704 struct berval *value,
1705 void *assertedValue )
1707 *matchp = UTF8bvnormcmp( value,
1708 (struct berval *) assertedValue,
1709 LDAP_UTF8_CASEFOLD );
1710 return LDAP_SUCCESS;
1713 /* Remove all spaces and '-' characters */
1715 telephoneNumberNormalize(
1718 struct berval *normalized )
1722 /* validator should have refused an empty string */
1723 assert( val->bv_len );
1725 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1727 for( p = val->bv_val; *p; p++ ) {
1728 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1734 normalized->bv_len = q - normalized->bv_val;
1736 if( normalized->bv_len == 0 ) {
1737 free( normalized->bv_val );
1738 return LDAP_INVALID_SYNTAX;
1741 return LDAP_SUCCESS;
1747 struct berval *val )
1751 if( val->bv_len == 0 ) {
1752 /* disallow empty strings */
1753 return LDAP_INVALID_SYNTAX;
1756 if( OID_LEADCHAR(val->bv_val[0]) ) {
1758 for(i=1; i < val->bv_len; i++) {
1759 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1760 if( dot++ ) return 1;
1761 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1764 return LDAP_INVALID_SYNTAX;
1768 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1770 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1771 for(i=1; i < val->bv_len; i++) {
1772 if( !DESC_CHAR(val->bv_val[i] ) ) {
1773 return LDAP_INVALID_SYNTAX;
1777 return LDAP_SUCCESS;
1780 return LDAP_INVALID_SYNTAX;
1789 struct berval *value,
1790 void *assertedValue )
1793 int vsign = 1, avsign = 1; /* default sign = '+' */
1794 struct berval *asserted;
1795 ber_len_t vlen, avlen;
1798 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1800 vlen = value->bv_len;
1801 if( mr == integerFirstComponentMatchingRule ) {
1802 char *tmp = memchr( v, '$', vlen );
1805 while( vlen && ASCII_SPACE( v[vlen-1] ))
1808 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) /* ANSI 2.2.1 */
1814 /* Do the same with the *assertedValue number */
1815 asserted = (struct berval *) assertedValue;
1816 av = asserted->bv_val;
1817 avlen = asserted->bv_len;
1818 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1824 match = vsign - avsign;
1826 match = (vlen != avlen
1827 ? ( vlen < avlen ? -1 : 1 )
1828 : memcmp( v, av, vlen ));
1834 return LDAP_SUCCESS;
1840 struct berval *val )
1844 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1846 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1847 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1848 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1849 return LDAP_INVALID_SYNTAX;
1852 for( i=1; i < val->bv_len; i++ ) {
1853 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1856 return LDAP_SUCCESS;
1863 struct berval *normalized )
1873 /* Ignore leading spaces */
1874 while ( len && ( *p == ' ' )) {
1881 negative = ( *p == '-' );
1882 if(( *p == '-' ) || ( *p == '+' )) {
1888 /* Ignore leading zeros */
1889 while ( len && ( *p == '0' )) {
1894 /* If there are no non-zero digits left, the number is zero, otherwise
1895 allocate space for the number and copy it into the buffer */
1897 normalized->bv_val = ch_strdup("0");
1898 normalized->bv_len = 1;
1901 normalized->bv_len = len+negative;
1902 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1904 normalized->bv_val[0] = '-';
1906 AC_MEMCPY( normalized->bv_val + negative, p, len );
1907 normalized->bv_val[len+negative] = '\0';
1910 return LDAP_SUCCESS;
1913 /* Index generation function */
1914 static int integerIndexer(
1919 struct berval *prefix,
1926 HASH_CONTEXT HASHcontext;
1927 unsigned char HASHdigest[HASH_BYTES];
1928 struct berval digest;
1929 digest.bv_val = HASHdigest;
1930 digest.bv_len = sizeof(HASHdigest);
1932 for( i=0; values[i].bv_val != NULL; i++ ) {
1933 /* empty - just count them */
1936 /* we should have at least one value at this point */
1939 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1941 slen = syntax->ssyn_oidlen;
1942 mlen = mr->smr_oidlen;
1944 for( i=0; values[i].bv_val != NULL; i++ ) {
1946 integerNormalize( syntax, &values[i], &norm );
1948 HASH_Init( &HASHcontext );
1949 if( prefix != NULL && prefix->bv_len > 0 ) {
1950 HASH_Update( &HASHcontext,
1951 prefix->bv_val, prefix->bv_len );
1953 HASH_Update( &HASHcontext,
1954 syntax->ssyn_oid, slen );
1955 HASH_Update( &HASHcontext,
1956 mr->smr_oid, mlen );
1957 HASH_Update( &HASHcontext,
1958 norm.bv_val, norm.bv_len );
1959 HASH_Final( HASHdigest, &HASHcontext );
1961 ber_dupbv( &keys[i], &digest );
1962 ch_free( norm.bv_val );
1965 keys[i].bv_val = NULL;
1967 return LDAP_SUCCESS;
1970 /* Index generation function */
1971 static int integerFilter(
1976 struct berval *prefix,
1977 void * assertedValue,
1982 HASH_CONTEXT HASHcontext;
1983 unsigned char HASHdigest[HASH_BYTES];
1985 struct berval digest;
1986 digest.bv_val = HASHdigest;
1987 digest.bv_len = sizeof(HASHdigest);
1989 slen = syntax->ssyn_oidlen;
1990 mlen = mr->smr_oidlen;
1992 integerNormalize( syntax, assertedValue, &norm );
1994 keys = ch_malloc( sizeof( struct berval ) * 2 );
1996 HASH_Init( &HASHcontext );
1997 if( prefix != NULL && prefix->bv_len > 0 ) {
1998 HASH_Update( &HASHcontext,
1999 prefix->bv_val, prefix->bv_len );
2001 HASH_Update( &HASHcontext,
2002 syntax->ssyn_oid, slen );
2003 HASH_Update( &HASHcontext,
2004 mr->smr_oid, mlen );
2005 HASH_Update( &HASHcontext,
2006 norm.bv_val, norm.bv_len );
2007 HASH_Final( HASHdigest, &HASHcontext );
2009 ber_dupbv( &keys[0], &digest );
2010 keys[1].bv_val = NULL;
2011 ch_free( norm.bv_val );
2014 return LDAP_SUCCESS;
2019 countryStringValidate(
2021 struct berval *val )
2023 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2025 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2026 return LDAP_INVALID_SYNTAX;
2028 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2029 return LDAP_INVALID_SYNTAX;
2032 return LDAP_SUCCESS;
2036 printableStringValidate(
2038 struct berval *val )
2042 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2044 for(i=0; i < val->bv_len; i++) {
2045 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2046 return LDAP_INVALID_SYNTAX;
2050 return LDAP_SUCCESS;
2054 printablesStringValidate(
2056 struct berval *val )
2060 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2062 for(i=0,len=0; i < val->bv_len; i++) {
2063 int c = val->bv_val[i];
2067 return LDAP_INVALID_SYNTAX;
2071 } else if ( SLAP_PRINTABLE(c) ) {
2074 return LDAP_INVALID_SYNTAX;
2079 return LDAP_INVALID_SYNTAX;
2082 return LDAP_SUCCESS;
2088 struct berval *val )
2092 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2094 for(i=0; i < val->bv_len; i++) {
2095 if( !LDAP_ASCII(val->bv_val[i]) ) {
2096 return LDAP_INVALID_SYNTAX;
2100 return LDAP_SUCCESS;
2107 struct berval *normalized )
2111 assert( val->bv_len );
2115 /* Ignore initial whitespace */
2116 while ( ASCII_SPACE( *p ) ) {
2120 normalized->bv_val = ch_strdup( p );
2121 p = q = normalized->bv_val;
2124 if ( ASCII_SPACE( *p ) ) {
2127 /* Ignore the extra whitespace */
2128 while ( ASCII_SPACE( *p ) ) {
2136 assert( normalized->bv_val <= p );
2140 * If the string ended in space, backup the pointer one
2141 * position. One is enough because the above loop collapsed
2142 * all whitespace to a single space.
2145 if ( ASCII_SPACE( q[-1] ) ) {
2149 /* null terminate */
2152 normalized->bv_len = q - normalized->bv_val;
2154 if( normalized->bv_len == 0 ) {
2155 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
2156 normalized->bv_val[0] = ' ';
2157 normalized->bv_val[1] = '\0';
2158 normalized->bv_len = 1;
2161 return LDAP_SUCCESS;
2170 struct berval *value,
2171 void *assertedValue )
2173 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2176 match = strncmp( value->bv_val,
2177 ((struct berval *) assertedValue)->bv_val,
2182 return LDAP_SUCCESS;
2186 caseExactIA5SubstringsMatch(
2191 struct berval *value,
2192 void *assertedValue )
2195 SubstringsAssertion *sub = assertedValue;
2196 struct berval left = *value;
2200 /* Add up asserted input length */
2201 if( sub->sa_initial.bv_val ) {
2202 inlen += sub->sa_initial.bv_len;
2205 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2206 inlen += sub->sa_any[i].bv_len;
2209 if( sub->sa_final.bv_val ) {
2210 inlen += sub->sa_final.bv_len;
2213 if( sub->sa_initial.bv_val ) {
2214 if( inlen > left.bv_len ) {
2219 match = strncmp( sub->sa_initial.bv_val, left.bv_val,
2220 sub->sa_initial.bv_len );
2226 left.bv_val += sub->sa_initial.bv_len;
2227 left.bv_len -= sub->sa_initial.bv_len;
2228 inlen -= sub->sa_initial.bv_len;
2231 if( sub->sa_final.bv_val ) {
2232 if( inlen > left.bv_len ) {
2237 match = strncmp( sub->sa_final.bv_val,
2238 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2239 sub->sa_final.bv_len );
2245 left.bv_len -= sub->sa_final.bv_len;
2246 inlen -= sub->sa_final.bv_len;
2250 for(i=0; sub->sa_any[i].bv_val; i++) {
2255 if( inlen > left.bv_len ) {
2256 /* not enough length */
2261 if( sub->sa_any[i].bv_len == 0 ) {
2265 p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
2272 idx = p - left.bv_val;
2274 if( idx >= left.bv_len ) {
2275 /* this shouldn't happen */
2282 if( sub->sa_any[i].bv_len > left.bv_len ) {
2283 /* not enough left */
2288 match = strncmp( left.bv_val,
2289 sub->sa_any[i].bv_val,
2290 sub->sa_any[i].bv_len );
2298 left.bv_val += sub->sa_any[i].bv_len;
2299 left.bv_len -= sub->sa_any[i].bv_len;
2300 inlen -= sub->sa_any[i].bv_len;
2306 return LDAP_SUCCESS;
2309 /* Index generation function */
2310 static int caseExactIA5Indexer(
2315 struct berval *prefix,
2322 HASH_CONTEXT HASHcontext;
2323 unsigned char HASHdigest[HASH_BYTES];
2324 struct berval digest;
2325 digest.bv_val = HASHdigest;
2326 digest.bv_len = sizeof(HASHdigest);
2328 for( i=0; values[i].bv_val != NULL; i++ ) {
2329 /* empty - just count them */
2332 /* we should have at least one value at this point */
2335 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2337 slen = syntax->ssyn_oidlen;
2338 mlen = mr->smr_oidlen;
2340 for( i=0; values[i].bv_val != NULL; i++ ) {
2341 struct berval *value = &values[i];
2343 HASH_Init( &HASHcontext );
2344 if( prefix != NULL && prefix->bv_len > 0 ) {
2345 HASH_Update( &HASHcontext,
2346 prefix->bv_val, prefix->bv_len );
2348 HASH_Update( &HASHcontext,
2349 syntax->ssyn_oid, slen );
2350 HASH_Update( &HASHcontext,
2351 mr->smr_oid, mlen );
2352 HASH_Update( &HASHcontext,
2353 value->bv_val, value->bv_len );
2354 HASH_Final( HASHdigest, &HASHcontext );
2356 ber_dupbv( &keys[i], &digest );
2359 keys[i].bv_val = NULL;
2361 return LDAP_SUCCESS;
2364 /* Index generation function */
2365 static int caseExactIA5Filter(
2370 struct berval *prefix,
2371 void * assertedValue,
2376 HASH_CONTEXT HASHcontext;
2377 unsigned char HASHdigest[HASH_BYTES];
2378 struct berval *value;
2379 struct berval digest;
2380 digest.bv_val = HASHdigest;
2381 digest.bv_len = sizeof(HASHdigest);
2383 slen = syntax->ssyn_oidlen;
2384 mlen = mr->smr_oidlen;
2386 value = (struct berval *) assertedValue;
2388 keys = ch_malloc( sizeof( struct berval ) * 2 );
2390 HASH_Init( &HASHcontext );
2391 if( prefix != NULL && prefix->bv_len > 0 ) {
2392 HASH_Update( &HASHcontext,
2393 prefix->bv_val, prefix->bv_len );
2395 HASH_Update( &HASHcontext,
2396 syntax->ssyn_oid, slen );
2397 HASH_Update( &HASHcontext,
2398 mr->smr_oid, mlen );
2399 HASH_Update( &HASHcontext,
2400 value->bv_val, value->bv_len );
2401 HASH_Final( HASHdigest, &HASHcontext );
2403 ber_dupbv( &keys[0], &digest );
2404 keys[1].bv_val = NULL;
2407 return LDAP_SUCCESS;
2410 /* Substrings Index generation function */
2411 static int caseExactIA5SubstringsIndexer(
2416 struct berval *prefix,
2423 HASH_CONTEXT HASHcontext;
2424 unsigned char HASHdigest[HASH_BYTES];
2425 struct berval digest;
2426 digest.bv_val = HASHdigest;
2427 digest.bv_len = sizeof(HASHdigest);
2429 /* we should have at least one value at this point */
2430 assert( values != NULL && values[0].bv_val != NULL );
2433 for( i=0; values[i].bv_val != NULL; i++ ) {
2434 /* count number of indices to generate */
2435 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2439 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2440 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2441 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2442 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2444 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2448 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2449 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2450 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2454 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2455 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2456 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2457 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2459 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2465 /* no keys to generate */
2467 return LDAP_SUCCESS;
2470 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2472 slen = syntax->ssyn_oidlen;
2473 mlen = mr->smr_oidlen;
2476 for( i=0; values[i].bv_val != NULL; i++ ) {
2478 struct berval *value;
2481 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2483 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2484 ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2486 char pre = SLAP_INDEX_SUBSTR_PREFIX;
2487 max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2489 for( j=0; j<max; j++ ) {
2490 HASH_Init( &HASHcontext );
2491 if( prefix != NULL && prefix->bv_len > 0 ) {
2492 HASH_Update( &HASHcontext,
2493 prefix->bv_val, prefix->bv_len );
2496 HASH_Update( &HASHcontext,
2497 &pre, sizeof( pre ) );
2498 HASH_Update( &HASHcontext,
2499 syntax->ssyn_oid, slen );
2500 HASH_Update( &HASHcontext,
2501 mr->smr_oid, mlen );
2502 HASH_Update( &HASHcontext,
2504 SLAP_INDEX_SUBSTR_MAXLEN );
2505 HASH_Final( HASHdigest, &HASHcontext );
2507 ber_dupbv( &keys[nkeys++], &digest );
2511 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2512 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2514 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2517 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2518 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2519 HASH_Init( &HASHcontext );
2520 if( prefix != NULL && prefix->bv_len > 0 ) {
2521 HASH_Update( &HASHcontext,
2522 prefix->bv_val, prefix->bv_len );
2524 HASH_Update( &HASHcontext,
2525 &pre, sizeof( pre ) );
2526 HASH_Update( &HASHcontext,
2527 syntax->ssyn_oid, slen );
2528 HASH_Update( &HASHcontext,
2529 mr->smr_oid, mlen );
2530 HASH_Update( &HASHcontext,
2532 HASH_Final( HASHdigest, &HASHcontext );
2534 ber_dupbv( &keys[nkeys++], &digest );
2537 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2538 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2539 HASH_Init( &HASHcontext );
2540 if( prefix != NULL && prefix->bv_len > 0 ) {
2541 HASH_Update( &HASHcontext,
2542 prefix->bv_val, prefix->bv_len );
2544 HASH_Update( &HASHcontext,
2545 &pre, sizeof( pre ) );
2546 HASH_Update( &HASHcontext,
2547 syntax->ssyn_oid, slen );
2548 HASH_Update( &HASHcontext,
2549 mr->smr_oid, mlen );
2550 HASH_Update( &HASHcontext,
2551 &value->bv_val[value->bv_len-j], j );
2552 HASH_Final( HASHdigest, &HASHcontext );
2554 ber_dupbv( &keys[nkeys++], &digest );
2561 keys[nkeys].bv_val = NULL;
2568 return LDAP_SUCCESS;
2571 static int caseExactIA5SubstringsFilter(
2576 struct berval *prefix,
2577 void * assertedValue,
2580 SubstringsAssertion *sa = assertedValue;
2582 ber_len_t nkeys = 0;
2583 size_t slen, mlen, klen;
2585 HASH_CONTEXT HASHcontext;
2586 unsigned char HASHdigest[HASH_BYTES];
2587 struct berval *value;
2588 struct berval digest;
2590 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2591 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2596 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2598 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2599 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2600 /* don't bother accounting for stepping */
2601 nkeys += sa->sa_any[i].bv_len -
2602 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2607 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2608 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2615 return LDAP_SUCCESS;
2618 digest.bv_val = HASHdigest;
2619 digest.bv_len = sizeof(HASHdigest);
2621 slen = syntax->ssyn_oidlen;
2622 mlen = mr->smr_oidlen;
2624 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2627 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2628 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2630 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2631 value = &sa->sa_initial;
2633 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2634 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2636 HASH_Init( &HASHcontext );
2637 if( prefix != NULL && prefix->bv_len > 0 ) {
2638 HASH_Update( &HASHcontext,
2639 prefix->bv_val, prefix->bv_len );
2641 HASH_Update( &HASHcontext,
2642 &pre, sizeof( pre ) );
2643 HASH_Update( &HASHcontext,
2644 syntax->ssyn_oid, slen );
2645 HASH_Update( &HASHcontext,
2646 mr->smr_oid, mlen );
2647 HASH_Update( &HASHcontext,
2648 value->bv_val, klen );
2649 HASH_Final( HASHdigest, &HASHcontext );
2651 ber_dupbv( &keys[nkeys++], &digest );
2654 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2656 pre = SLAP_INDEX_SUBSTR_PREFIX;
2657 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2659 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2660 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2664 value = &sa->sa_any[i];
2667 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2668 j += SLAP_INDEX_SUBSTR_STEP )
2670 HASH_Init( &HASHcontext );
2671 if( prefix != NULL && prefix->bv_len > 0 ) {
2672 HASH_Update( &HASHcontext,
2673 prefix->bv_val, prefix->bv_len );
2675 HASH_Update( &HASHcontext,
2676 &pre, sizeof( pre ) );
2677 HASH_Update( &HASHcontext,
2678 syntax->ssyn_oid, slen );
2679 HASH_Update( &HASHcontext,
2680 mr->smr_oid, mlen );
2681 HASH_Update( &HASHcontext,
2682 &value->bv_val[j], klen );
2683 HASH_Final( HASHdigest, &HASHcontext );
2685 ber_dupbv( &keys[nkeys++], &digest );
2690 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2691 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2693 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2694 value = &sa->sa_final;
2696 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2697 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2699 HASH_Init( &HASHcontext );
2700 if( prefix != NULL && prefix->bv_len > 0 ) {
2701 HASH_Update( &HASHcontext,
2702 prefix->bv_val, prefix->bv_len );
2704 HASH_Update( &HASHcontext,
2705 &pre, sizeof( pre ) );
2706 HASH_Update( &HASHcontext,
2707 syntax->ssyn_oid, slen );
2708 HASH_Update( &HASHcontext,
2709 mr->smr_oid, mlen );
2710 HASH_Update( &HASHcontext,
2711 &value->bv_val[value->bv_len-klen], klen );
2712 HASH_Final( HASHdigest, &HASHcontext );
2714 ber_dupbv( &keys[nkeys++], &digest );
2718 keys[nkeys].bv_val = NULL;
2725 return LDAP_SUCCESS;
2734 struct berval *value,
2735 void *assertedValue )
2737 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2739 if( match == 0 && value->bv_len ) {
2740 match = strncasecmp( value->bv_val,
2741 ((struct berval *) assertedValue)->bv_val,
2746 return LDAP_SUCCESS;
2750 caseIgnoreIA5SubstringsMatch(
2755 struct berval *value,
2756 void *assertedValue )
2759 SubstringsAssertion *sub = assertedValue;
2760 struct berval left = *value;
2764 /* Add up asserted input length */
2765 if( sub->sa_initial.bv_val ) {
2766 inlen += sub->sa_initial.bv_len;
2769 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2770 inlen += sub->sa_any[i].bv_len;
2773 if( sub->sa_final.bv_val ) {
2774 inlen += sub->sa_final.bv_len;
2777 if( sub->sa_initial.bv_val ) {
2778 if( inlen > left.bv_len ) {
2783 match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
2784 sub->sa_initial.bv_len );
2790 left.bv_val += sub->sa_initial.bv_len;
2791 left.bv_len -= sub->sa_initial.bv_len;
2792 inlen -= sub->sa_initial.bv_len;
2795 if( sub->sa_final.bv_val ) {
2796 if( inlen > left.bv_len ) {
2801 match = strncasecmp( sub->sa_final.bv_val,
2802 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2803 sub->sa_final.bv_len );
2809 left.bv_len -= sub->sa_final.bv_len;
2810 inlen -= sub->sa_final.bv_len;
2814 for(i=0; sub->sa_any[i].bv_val; i++) {
2819 if( inlen > left.bv_len ) {
2820 /* not enough length */
2825 if( sub->sa_any[i].bv_len == 0 ) {
2829 p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
2836 assert( idx < left.bv_len );
2837 if( idx >= left.bv_len ) {
2838 /* this shouldn't happen */
2845 if( sub->sa_any[i].bv_len > left.bv_len ) {
2846 /* not enough left */
2851 match = strncasecmp( left.bv_val,
2852 sub->sa_any[i].bv_val,
2853 sub->sa_any[i].bv_len );
2862 left.bv_val += sub->sa_any[i].bv_len;
2863 left.bv_len -= sub->sa_any[i].bv_len;
2864 inlen -= sub->sa_any[i].bv_len;
2870 return LDAP_SUCCESS;
2873 /* Index generation function */
2874 static int caseIgnoreIA5Indexer(
2879 struct berval *prefix,
2884 int rc = LDAP_SUCCESS;
2887 HASH_CONTEXT HASHcontext;
2888 unsigned char HASHdigest[HASH_BYTES];
2889 struct berval digest;
2890 digest.bv_val = HASHdigest;
2891 digest.bv_len = sizeof(HASHdigest);
2893 /* we should have at least one value at this point */
2894 assert( values != NULL && values[0].bv_val != NULL );
2896 for( i=0; values[i].bv_val != NULL; i++ ) {
2897 /* just count them */
2900 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2902 slen = syntax->ssyn_oidlen;
2903 mlen = mr->smr_oidlen;
2905 for( i=0; values[i].bv_val != NULL; i++ ) {
2906 struct berval value;
2908 if( mr->smr_normalize ) {
2909 rc = (mr->smr_normalize)( use, syntax, mr, &values[i], &value );
2910 if( rc != LDAP_SUCCESS ) {
2913 } else if ( mr->smr_syntax->ssyn_normalize ) {
2914 rc = (mr->smr_syntax->ssyn_normalize)( syntax, &values[i], &value );
2915 if( rc != LDAP_SUCCESS ) {
2919 ber_dupbv( &value, &values[i] );
2922 ldap_pvt_str2lower( value.bv_val );
2924 HASH_Init( &HASHcontext );
2925 if( prefix != NULL && prefix->bv_len > 0 ) {
2926 HASH_Update( &HASHcontext,
2927 prefix->bv_val, prefix->bv_len );
2929 HASH_Update( &HASHcontext,
2930 syntax->ssyn_oid, slen );
2931 HASH_Update( &HASHcontext,
2932 mr->smr_oid, mlen );
2933 HASH_Update( &HASHcontext,
2934 value.bv_val, value.bv_len );
2935 HASH_Final( HASHdigest, &HASHcontext );
2937 free( value.bv_val );
2939 ber_dupbv( &keys[i], &digest );
2942 keys[i].bv_val = NULL;
2943 if( rc != LDAP_SUCCESS ) {
2944 ber_bvarray_free( keys );
2951 /* Index generation function */
2952 static int caseIgnoreIA5Filter(
2957 struct berval *prefix,
2958 void * assertedValue,
2963 HASH_CONTEXT HASHcontext;
2964 unsigned char HASHdigest[HASH_BYTES];
2965 struct berval value;
2966 struct berval digest;
2967 digest.bv_val = HASHdigest;
2968 digest.bv_len = sizeof(HASHdigest);
2970 slen = syntax->ssyn_oidlen;
2971 mlen = mr->smr_oidlen;
2973 ber_dupbv( &value, (struct berval *) assertedValue );
2974 ldap_pvt_str2lower( value.bv_val );
2976 keys = ch_malloc( sizeof( struct berval ) * 2 );
2978 HASH_Init( &HASHcontext );
2979 if( prefix != NULL && prefix->bv_len > 0 ) {
2980 HASH_Update( &HASHcontext,
2981 prefix->bv_val, prefix->bv_len );
2983 HASH_Update( &HASHcontext,
2984 syntax->ssyn_oid, slen );
2985 HASH_Update( &HASHcontext,
2986 mr->smr_oid, mlen );
2987 HASH_Update( &HASHcontext,
2988 value.bv_val, value.bv_len );
2989 HASH_Final( HASHdigest, &HASHcontext );
2991 ber_dupbv( &keys[0], &digest );
2992 keys[1].bv_val = NULL;
2994 free( value.bv_val );
2998 return LDAP_SUCCESS;
3001 /* Substrings Index generation function */
3002 static int caseIgnoreIA5SubstringsIndexer(
3007 struct berval *prefix,
3014 HASH_CONTEXT HASHcontext;
3015 unsigned char HASHdigest[HASH_BYTES];
3016 struct berval digest;
3017 digest.bv_val = HASHdigest;
3018 digest.bv_len = sizeof(HASHdigest);
3020 /* we should have at least one value at this point */
3021 assert( values != NULL && values[0].bv_val != NULL );
3024 for( i=0; values[i].bv_val != NULL; i++ ) {
3025 /* count number of indices to generate */
3026 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3030 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3031 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3032 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3033 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3035 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3039 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3040 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3041 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3045 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3046 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3047 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3048 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3050 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3056 /* no keys to generate */
3058 return LDAP_SUCCESS;
3061 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3063 slen = syntax->ssyn_oidlen;
3064 mlen = mr->smr_oidlen;
3067 for( i=0; values[i].bv_val != NULL; i++ ) {
3069 struct berval value;
3071 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3073 ber_dupbv( &value, &values[i] );
3074 ldap_pvt_str2lower( value.bv_val );
3076 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3077 ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3079 char pre = SLAP_INDEX_SUBSTR_PREFIX;
3080 max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3082 for( j=0; j<max; j++ ) {
3083 HASH_Init( &HASHcontext );
3084 if( prefix != NULL && prefix->bv_len > 0 ) {
3085 HASH_Update( &HASHcontext,
3086 prefix->bv_val, prefix->bv_len );
3089 HASH_Update( &HASHcontext,
3090 &pre, sizeof( pre ) );
3091 HASH_Update( &HASHcontext,
3092 syntax->ssyn_oid, slen );
3093 HASH_Update( &HASHcontext,
3094 mr->smr_oid, mlen );
3095 HASH_Update( &HASHcontext,
3097 SLAP_INDEX_SUBSTR_MAXLEN );
3098 HASH_Final( HASHdigest, &HASHcontext );
3100 ber_dupbv( &keys[nkeys++], &digest );
3104 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3105 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3107 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3110 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3111 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3112 HASH_Init( &HASHcontext );
3113 if( prefix != NULL && prefix->bv_len > 0 ) {
3114 HASH_Update( &HASHcontext,
3115 prefix->bv_val, prefix->bv_len );
3117 HASH_Update( &HASHcontext,
3118 &pre, sizeof( pre ) );
3119 HASH_Update( &HASHcontext,
3120 syntax->ssyn_oid, slen );
3121 HASH_Update( &HASHcontext,
3122 mr->smr_oid, mlen );
3123 HASH_Update( &HASHcontext,
3125 HASH_Final( HASHdigest, &HASHcontext );
3127 ber_dupbv( &keys[nkeys++], &digest );
3130 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3131 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3132 HASH_Init( &HASHcontext );
3133 if( prefix != NULL && prefix->bv_len > 0 ) {
3134 HASH_Update( &HASHcontext,
3135 prefix->bv_val, prefix->bv_len );
3137 HASH_Update( &HASHcontext,
3138 &pre, sizeof( pre ) );
3139 HASH_Update( &HASHcontext,
3140 syntax->ssyn_oid, slen );
3141 HASH_Update( &HASHcontext,
3142 mr->smr_oid, mlen );
3143 HASH_Update( &HASHcontext,
3144 &value.bv_val[value.bv_len-j], j );
3145 HASH_Final( HASHdigest, &HASHcontext );
3147 ber_dupbv( &keys[nkeys++], &digest );
3152 free( value.bv_val );
3156 keys[nkeys].bv_val = NULL;
3163 return LDAP_SUCCESS;
3166 static int caseIgnoreIA5SubstringsFilter(
3171 struct berval *prefix,
3172 void * assertedValue,
3175 SubstringsAssertion *sa = assertedValue;
3177 ber_len_t nkeys = 0;
3178 size_t slen, mlen, klen;
3180 HASH_CONTEXT HASHcontext;
3181 unsigned char HASHdigest[HASH_BYTES];
3182 struct berval value;
3183 struct berval digest;
3185 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3186 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3191 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3193 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3194 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3195 /* don't bother accounting for stepping */
3196 nkeys += sa->sa_any[i].bv_len -
3197 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3202 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3203 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3210 return LDAP_SUCCESS;
3213 digest.bv_val = HASHdigest;
3214 digest.bv_len = sizeof(HASHdigest);
3216 slen = syntax->ssyn_oidlen;
3217 mlen = mr->smr_oidlen;
3219 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3222 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3223 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3225 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3226 ber_dupbv( &value, &sa->sa_initial );
3227 ldap_pvt_str2lower( value.bv_val );
3229 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3230 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3232 HASH_Init( &HASHcontext );
3233 if( prefix != NULL && prefix->bv_len > 0 ) {
3234 HASH_Update( &HASHcontext,
3235 prefix->bv_val, prefix->bv_len );
3237 HASH_Update( &HASHcontext,
3238 &pre, sizeof( pre ) );
3239 HASH_Update( &HASHcontext,
3240 syntax->ssyn_oid, slen );
3241 HASH_Update( &HASHcontext,
3242 mr->smr_oid, mlen );
3243 HASH_Update( &HASHcontext,
3244 value.bv_val, klen );
3245 HASH_Final( HASHdigest, &HASHcontext );
3247 free( value.bv_val );
3248 ber_dupbv( &keys[nkeys++], &digest );
3251 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3253 pre = SLAP_INDEX_SUBSTR_PREFIX;
3254 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3256 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3257 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3261 ber_dupbv( &value, &sa->sa_any[i] );
3262 ldap_pvt_str2lower( value.bv_val );
3265 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3266 j += SLAP_INDEX_SUBSTR_STEP )
3268 HASH_Init( &HASHcontext );
3269 if( prefix != NULL && prefix->bv_len > 0 ) {
3270 HASH_Update( &HASHcontext,
3271 prefix->bv_val, prefix->bv_len );
3273 HASH_Update( &HASHcontext,
3274 &pre, sizeof( pre ) );
3275 HASH_Update( &HASHcontext,
3276 syntax->ssyn_oid, slen );
3277 HASH_Update( &HASHcontext,
3278 mr->smr_oid, mlen );
3279 HASH_Update( &HASHcontext,
3280 &value.bv_val[j], klen );
3281 HASH_Final( HASHdigest, &HASHcontext );
3283 ber_dupbv( &keys[nkeys++], &digest );
3286 free( value.bv_val );
3290 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3291 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3293 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3294 ber_dupbv( &value, &sa->sa_final );
3295 ldap_pvt_str2lower( value.bv_val );
3297 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3298 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3300 HASH_Init( &HASHcontext );
3301 if( prefix != NULL && prefix->bv_len > 0 ) {
3302 HASH_Update( &HASHcontext,
3303 prefix->bv_val, prefix->bv_len );
3305 HASH_Update( &HASHcontext,
3306 &pre, sizeof( pre ) );
3307 HASH_Update( &HASHcontext,
3308 syntax->ssyn_oid, slen );
3309 HASH_Update( &HASHcontext,
3310 mr->smr_oid, mlen );
3311 HASH_Update( &HASHcontext,
3312 &value.bv_val[value.bv_len-klen], klen );
3313 HASH_Final( HASHdigest, &HASHcontext );
3315 free( value.bv_val );
3316 ber_dupbv( &keys[nkeys++], &digest );
3320 keys[nkeys].bv_val = NULL;
3327 return LDAP_SUCCESS;
3331 numericStringValidate(
3337 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
3339 for(i=0; i < in->bv_len; i++) {
3340 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3341 return LDAP_INVALID_SYNTAX;
3345 return LDAP_SUCCESS;
3349 numericStringNormalize(
3352 struct berval *normalized )
3354 /* removal all spaces */
3357 assert( val->bv_len );
3359 normalized->bv_val = ch_malloc( val->bv_len + 1 );
3362 q = normalized->bv_val;
3365 if ( ASCII_SPACE( *p ) ) {
3366 /* Ignore whitespace */
3373 /* we should have copied no more then is in val */
3374 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3376 /* null terminate */
3379 normalized->bv_len = q - normalized->bv_val;
3381 if( normalized->bv_len == 0 ) {
3382 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
3383 normalized->bv_val[0] = ' ';
3384 normalized->bv_val[1] = '\0';
3385 normalized->bv_len = 1;
3388 return LDAP_SUCCESS;
3392 objectIdentifierFirstComponentMatch(
3397 struct berval *value,
3398 void *assertedValue )
3400 int rc = LDAP_SUCCESS;
3402 struct berval *asserted = (struct berval *) assertedValue;
3406 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3407 return LDAP_INVALID_SYNTAX;
3410 /* trim leading white space */
3411 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3415 /* grab next word */
3416 oid.bv_val = &value->bv_val[i];
3417 j = value->bv_len - i;
3418 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
3423 /* insert attributeTypes, objectclass check here */
3424 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3425 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3428 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3429 MatchingRule *asserted_mr = mr_bvfind( asserted );
3430 MatchingRule *stored_mr = mr_bvfind( &oid );
3432 if( asserted_mr == NULL ) {
3433 rc = SLAPD_COMPARE_UNDEFINED;
3435 match = asserted_mr != stored_mr;
3438 } else if ( !strcmp( syntax->ssyn_oid,
3439 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3441 AttributeType *asserted_at = at_bvfind( asserted );
3442 AttributeType *stored_at = at_bvfind( &oid );
3444 if( asserted_at == NULL ) {
3445 rc = SLAPD_COMPARE_UNDEFINED;
3447 match = asserted_at != stored_at;
3450 } else if ( !strcmp( syntax->ssyn_oid,
3451 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3453 ObjectClass *asserted_oc = oc_bvfind( asserted );
3454 ObjectClass *stored_oc = oc_bvfind( &oid );
3456 if( asserted_oc == NULL ) {
3457 rc = SLAPD_COMPARE_UNDEFINED;
3459 match = asserted_oc != stored_oc;
3465 LDAP_LOG( CONFIG, ENTRY,
3466 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
3467 match, value->bv_val, asserted->bv_val );
3469 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3470 "%d\n\t\"%s\"\n\t\"%s\"\n",
3471 match, value->bv_val, asserted->bv_val );
3474 if( rc == LDAP_SUCCESS ) *matchp = match;
3484 struct berval *value,
3485 void *assertedValue )
3487 long lValue, lAssertedValue;
3489 /* safe to assume integers are NUL terminated? */
3490 lValue = strtoul(value->bv_val, NULL, 10);
3491 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
3492 return LDAP_CONSTRAINT_VIOLATION;
3495 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3496 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
3497 && errno == ERANGE )
3499 return LDAP_CONSTRAINT_VIOLATION;
3502 *matchp = (lValue & lAssertedValue) ? 0 : 1;
3503 return LDAP_SUCCESS;
3512 struct berval *value,
3513 void *assertedValue )
3515 long lValue, lAssertedValue;
3517 /* safe to assume integers are NUL terminated? */
3518 lValue = strtoul(value->bv_val, NULL, 10);
3519 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
3520 return LDAP_CONSTRAINT_VIOLATION;
3523 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3524 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
3525 && errno == ERANGE )
3527 return LDAP_CONSTRAINT_VIOLATION;
3530 *matchp = (lValue | lAssertedValue) ? 0 : -1;
3531 return LDAP_SUCCESS;
3535 #include <openssl/x509.h>
3536 #include <openssl/err.h>
3539 * Next function returns a string representation of a ASN1_INTEGER.
3540 * It works for unlimited lengths.
3543 static struct berval *
3544 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3548 static char digit[] = "0123456789";
3550 /* We work backwards, make it fill from the end of buf */
3551 p = buf + sizeof(buf) - 1;
3554 if ( a == NULL || a->length == 0 ) {
3562 /* We want to preserve the original */
3563 copy = ch_malloc(n*sizeof(unsigned int));
3564 for (i = 0; i<n; i++) {
3565 copy[i] = a->data[i];
3569 * base indicates the index of the most significant
3570 * byte that might be nonzero. When it goes off the
3571 * end, we now there is nothing left to do.
3577 for (i = base; i<n; i++ ) {
3578 copy[i] += carry*256;
3579 carry = copy[i] % 10;
3584 * Way too large, we need to leave
3585 * room for sign if negative
3590 *--p = digit[carry];
3592 if (copy[base] == 0) base++;
3597 if ( a->type == V_ASN1_NEG_INTEGER ) {
3601 return ber_str2bv( p, 0, 1, bv );
3605 * Given a certificate in DER format, extract the corresponding
3606 * assertion value for certificateExactMatch
3609 certificateExactConvert(
3611 struct berval * out )
3614 unsigned char *p = in->bv_val;
3615 struct berval serial;
3616 struct berval issuer_dn;
3618 xcert = d2i_X509(NULL, &p, in->bv_len);
3621 LDAP_LOG( CONFIG, ENTRY,
3622 "certificateExactConvert: error parsing cert: %s\n",
3623 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3625 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3626 "error parsing cert: %s\n",
3627 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3629 return LDAP_INVALID_SYNTAX;
3632 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3634 return LDAP_INVALID_SYNTAX;
3636 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
3640 ber_memfree(serial.bv_val);
3641 return LDAP_INVALID_SYNTAX;
3646 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3647 out->bv_val = ch_malloc(out->bv_len);
3649 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3651 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3653 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3654 p += issuer_dn.bv_len;
3658 LDAP_LOG( CONFIG, ARGS,
3659 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
3661 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3663 out->bv_val, NULL, NULL );
3666 ber_memfree(serial.bv_val);
3667 ber_memfree(issuer_dn.bv_val);
3669 return LDAP_SUCCESS;
3673 serial_and_issuer_parse(
3674 struct berval *assertion,
3675 struct berval *serial,
3676 struct berval *issuer_dn
3684 begin = assertion->bv_val;
3685 end = assertion->bv_val+assertion->bv_len-1;
3686 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
3687 if ( p > end ) return LDAP_INVALID_SYNTAX;
3689 /* p now points at the $ sign, now use
3690 * begin and end to delimit the serial number
3692 while (ASCII_SPACE(*begin)) begin++;
3694 while (ASCII_SPACE(*end)) end--;
3696 if( end <= begin ) return LDAP_INVALID_SYNTAX;
3698 bv.bv_len = end-begin+1;
3700 ber_dupbv(serial, &bv);
3702 /* now extract the issuer, remember p was at the dollar sign */
3704 end = assertion->bv_val+assertion->bv_len-1;
3705 while (ASCII_SPACE(*begin)) begin++;
3706 /* should we trim spaces at the end too? is it safe always? no, no */
3708 if( end <= begin ) return LDAP_INVALID_SYNTAX;
3711 bv.bv_len = end-begin+1;
3714 dnNormalize2( NULL, &bv, issuer_dn );
3717 return LDAP_SUCCESS;
3721 certificateExactMatch(
3726 struct berval *value,
3727 void *assertedValue )
3730 unsigned char *p = value->bv_val;
3731 struct berval serial;
3732 struct berval issuer_dn;
3733 struct berval asserted_serial;
3734 struct berval asserted_issuer_dn;
3737 xcert = d2i_X509(NULL, &p, value->bv_len);
3740 LDAP_LOG( CONFIG, ENTRY,
3741 "certificateExactMatch: error parsing cert: %s\n",
3742 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3744 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3745 "error parsing cert: %s\n",
3746 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3748 return LDAP_INVALID_SYNTAX;
3751 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3752 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
3756 serial_and_issuer_parse(assertedValue,
3757 &asserted_serial, &asserted_issuer_dn);
3762 slap_schema.si_syn_integer,
3763 slap_schema.si_mr_integerMatch,
3766 if ( ret == LDAP_SUCCESS ) {
3767 if ( *matchp == 0 ) {
3768 /* We need to normalize everything for dnMatch */
3772 slap_schema.si_syn_distinguishedName,
3773 slap_schema.si_mr_distinguishedNameMatch,
3775 &asserted_issuer_dn);
3780 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
3781 "%d\n\t\"%s $ %s\"\n",
3782 *matchp, serial.bv_val, issuer_dn.bv_val );
3783 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
3784 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3787 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3788 "%d\n\t\"%s $ %s\"\n",
3789 *matchp, serial.bv_val, issuer_dn.bv_val );
3790 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3791 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3795 ber_memfree(serial.bv_val);
3796 ber_memfree(issuer_dn.bv_val);
3797 ber_memfree(asserted_serial.bv_val);
3798 ber_memfree(asserted_issuer_dn.bv_val);
3804 * Index generation function
3805 * We just index the serials, in most scenarios the issuer DN is one of
3806 * a very small set of values.
3808 static int certificateExactIndexer(
3813 struct berval *prefix,
3821 struct berval serial;
3823 /* we should have at least one value at this point */
3824 assert( values != NULL && values[0].bv_val != NULL );
3826 for( i=0; values[i].bv_val != NULL; i++ ) {
3827 /* empty -- just count them */
3830 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3832 for( i=0; values[i].bv_val != NULL; i++ ) {
3833 p = values[i].bv_val;
3834 xcert = d2i_X509(NULL, &p, values[i].bv_len);
3837 LDAP_LOG( CONFIG, ENTRY,
3838 "certificateExactIndexer: error parsing cert: %s\n",
3839 ERR_error_string(ERR_get_error(),NULL), 0, 0);
3841 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3842 "error parsing cert: %s\n",
3843 ERR_error_string(ERR_get_error(),NULL),
3846 /* Do we leak keys on error? */
3847 return LDAP_INVALID_SYNTAX;
3850 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3852 integerNormalize( slap_schema.si_syn_integer,
3853 &serial, &keys[i] );
3854 ber_memfree(serial.bv_val);
3856 LDAP_LOG( CONFIG, ENTRY,
3857 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
3859 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3866 keys[i].bv_val = NULL;
3868 return LDAP_SUCCESS;
3871 /* Index generation function */
3872 /* We think this is always called with a value in matching rule syntax */
3873 static int certificateExactFilter(
3878 struct berval *prefix,
3879 void * assertedValue,
3883 struct berval asserted_serial;
3886 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
3887 if( ret != LDAP_SUCCESS ) return ret;
3889 keys = ch_malloc( sizeof( struct berval ) * 2 );
3890 integerNormalize( syntax, &asserted_serial, &keys[0] );
3891 keys[1].bv_val = NULL;
3894 ber_memfree(asserted_serial.bv_val);
3895 return LDAP_SUCCESS;
3900 check_time_syntax (struct berval *val,
3904 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3905 static int mdays[2][12] = {
3906 /* non-leap years */
3907 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3909 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3912 int part, c, tzoffset, leapyear = 0 ;
3914 if( val->bv_len == 0 ) {
3915 return LDAP_INVALID_SYNTAX;
3918 p = (char *)val->bv_val;
3919 e = p + val->bv_len;
3921 /* Ignore initial whitespace */
3922 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3926 if (e - p < 13 - (2 * start)) {
3927 return LDAP_INVALID_SYNTAX;
3930 for (part = 0; part < 9; part++) {
3934 for (part = start; part < 7; part++) {
3936 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3943 return LDAP_INVALID_SYNTAX;
3945 if (c < 0 || c > 9) {
3946 return LDAP_INVALID_SYNTAX;
3952 return LDAP_INVALID_SYNTAX;
3954 if (c < 0 || c > 9) {
3955 return LDAP_INVALID_SYNTAX;
3960 if (part == 2 || part == 3) {
3963 if (parts[part] < 0) {
3964 return LDAP_INVALID_SYNTAX;
3966 if (parts[part] > ceiling[part]) {
3967 return LDAP_INVALID_SYNTAX;
3971 /* leapyear check for the Gregorian calendar (year>1581) */
3972 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
3973 ((parts[0] % 4 == 0) && (parts[1] == 0)))
3978 if (parts[3] > mdays[leapyear][parts[2]]) {
3979 return LDAP_INVALID_SYNTAX;
3984 tzoffset = 0; /* UTC */
3985 } else if (c != '+' && c != '-') {
3986 return LDAP_INVALID_SYNTAX;
3990 } else /* c == '+' */ {
3995 return LDAP_INVALID_SYNTAX;
3998 for (part = 7; part < 9; part++) {
4000 if (c < 0 || c > 9) {
4001 return LDAP_INVALID_SYNTAX;
4006 if (c < 0 || c > 9) {
4007 return LDAP_INVALID_SYNTAX;
4011 if (parts[part] < 0 || parts[part] > ceiling[part]) {
4012 return LDAP_INVALID_SYNTAX;
4017 /* Ignore trailing whitespace */
4018 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4022 return LDAP_INVALID_SYNTAX;
4025 switch ( tzoffset ) {
4026 case -1: /* negativ offset to UTC, ie west of Greenwich */
4027 parts[4] += parts[7];
4028 parts[5] += parts[8];
4029 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4033 c = mdays[leapyear][parts[2]];
4035 if (parts[part] > c) {
4036 parts[part] -= c + 1;
4041 case 1: /* positive offset to UTC, ie east of Greenwich */
4042 parts[4] -= parts[7];
4043 parts[5] -= parts[8];
4044 for (part = 6; --part > 0; ) {
4048 /* first arg to % needs to be non negativ */
4049 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4051 if (parts[part] < 0) {
4052 parts[part] += c + 1;
4057 case 0: /* already UTC */
4061 return LDAP_SUCCESS;
4064 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4069 struct berval *normalized )
4073 rc = check_time_syntax(val, 1, parts);
4074 if (rc != LDAP_SUCCESS) {
4078 normalized->bv_val = ch_malloc( 14 );
4079 if ( normalized->bv_val == NULL ) {
4080 return LBER_ERROR_MEMORY;
4083 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4084 parts[1], parts[2] + 1, parts[3] + 1,
4085 parts[4], parts[5], parts[6] );
4086 normalized->bv_len = 13;
4088 return LDAP_SUCCESS;
4092 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4100 return check_time_syntax(in, 1, parts);
4105 generalizedTimeValidate(
4111 return check_time_syntax(in, 0, parts);
4115 generalizedTimeNormalize(
4118 struct berval *normalized )
4122 rc = check_time_syntax(val, 0, parts);
4123 if (rc != LDAP_SUCCESS) {
4127 normalized->bv_val = ch_malloc( 16 );
4128 if ( normalized->bv_val == NULL ) {
4129 return LBER_ERROR_MEMORY;
4132 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4133 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4134 parts[4], parts[5], parts[6] );
4135 normalized->bv_len = 15;
4137 return LDAP_SUCCESS;
4141 nisNetgroupTripleValidate(
4143 struct berval *val )
4148 if ( val->bv_len == 0 ) {
4149 return LDAP_INVALID_SYNTAX;
4152 p = (char *)val->bv_val;
4153 e = p + val->bv_len;
4155 if ( *p != '(' /*')'*/ ) {
4156 return LDAP_INVALID_SYNTAX;
4159 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4163 return LDAP_INVALID_SYNTAX;
4166 } else if ( !AD_CHAR( *p ) ) {
4167 return LDAP_INVALID_SYNTAX;
4171 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4172 return LDAP_INVALID_SYNTAX;
4178 return LDAP_INVALID_SYNTAX;
4181 return LDAP_SUCCESS;
4185 bootParameterValidate(
4187 struct berval *val )
4191 if ( val->bv_len == 0 ) {
4192 return LDAP_INVALID_SYNTAX;
4195 p = (char *)val->bv_val;
4196 e = p + val->bv_len;
4199 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4200 if ( !AD_CHAR( *p ) ) {
4201 return LDAP_INVALID_SYNTAX;
4206 return LDAP_INVALID_SYNTAX;
4210 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4211 if ( !AD_CHAR( *p ) ) {
4212 return LDAP_INVALID_SYNTAX;
4217 return LDAP_INVALID_SYNTAX;
4221 for ( p++; p < e; p++ ) {
4222 if ( !SLAP_PRINTABLE( *p ) ) {
4223 return LDAP_INVALID_SYNTAX;
4227 return LDAP_SUCCESS;
4230 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4231 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4233 static slap_syntax_defs_rec syntax_defs[] = {
4234 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4235 X_BINARY X_NOT_H_R ")",
4236 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4237 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4238 0, NULL, NULL, NULL},
4239 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4240 0, NULL, NULL, NULL},
4241 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4243 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4244 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4246 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4247 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4248 0, bitStringValidate, NULL, NULL },
4249 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4250 0, booleanValidate, NULL, NULL},
4251 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4252 X_BINARY X_NOT_H_R ")",
4253 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4254 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4255 X_BINARY X_NOT_H_R ")",
4256 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4257 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4258 X_BINARY X_NOT_H_R ")",
4259 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4260 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4261 0, countryStringValidate, IA5StringNormalize, NULL},
4262 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4263 0, dnValidate, dnNormalize2, dnPretty2},
4264 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4265 0, NULL, NULL, NULL},
4266 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4267 0, NULL, NULL, NULL},
4268 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4269 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4270 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4271 0, NULL, NULL, NULL},
4272 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4273 0, NULL, NULL, NULL},
4274 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4275 0, NULL, NULL, NULL},
4276 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4277 0, NULL, NULL, NULL},
4278 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4279 0, NULL, NULL, NULL},
4280 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4281 0, printablesStringValidate, telephoneNumberNormalize, NULL},
4282 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4283 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4284 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4285 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4286 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4287 0, NULL, NULL, NULL},
4288 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4289 0, IA5StringValidate, IA5StringNormalize, NULL},
4290 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4291 0, integerValidate, integerNormalize, NULL},
4292 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4293 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4294 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4295 0, NULL, NULL, NULL},
4296 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4297 0, NULL, NULL, NULL},
4298 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4299 0, NULL, NULL, NULL},
4300 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4301 0, NULL, NULL, NULL},
4302 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4303 0, NULL, NULL, NULL},
4304 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4305 0, nameUIDValidate, nameUIDNormalize, NULL},
4306 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4307 0, NULL, NULL, NULL},
4308 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4309 0, numericStringValidate, numericStringNormalize, NULL},
4310 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4311 0, NULL, NULL, NULL},
4312 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4313 0, oidValidate, NULL, NULL},
4314 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4315 0, IA5StringValidate, IA5StringNormalize, NULL},
4316 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4317 0, blobValidate, NULL, NULL},
4318 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4319 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4320 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4321 0, NULL, NULL, NULL},
4322 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4323 0, NULL, NULL, NULL},
4324 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4325 0, printableStringValidate, IA5StringNormalize, NULL},
4326 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4327 X_BINARY X_NOT_H_R ")",
4328 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4329 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4330 X_BINARY X_NOT_H_R ")",
4331 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4332 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4333 0, printableStringValidate, telephoneNumberNormalize, NULL},
4334 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4335 0, NULL, NULL, NULL},
4336 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4337 0, printablesStringValidate, IA5StringNormalize, NULL},
4338 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4339 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4340 0, utcTimeValidate, utcTimeNormalize, NULL},
4342 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4343 0, NULL, NULL, NULL},
4344 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4345 0, NULL, NULL, NULL},
4346 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4347 0, NULL, NULL, NULL},
4348 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4349 0, NULL, NULL, NULL},
4350 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4351 0, NULL, NULL, NULL},
4353 /* RFC 2307 NIS Syntaxes */
4354 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4355 0, nisNetgroupTripleValidate, NULL, NULL},
4356 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4357 0, bootParameterValidate, NULL, NULL},
4361 /* These OIDs are not published yet, but will be in the next
4362 * I-D for PKIX LDAPv3 schema as have been advanced by David
4363 * Chadwick in private mail.
4365 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4366 0, UTF8StringValidate, NULL, NULL},
4369 /* OpenLDAP Experimental Syntaxes */
4370 #ifdef SLAPD_ACI_ENABLED
4371 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4373 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4377 #ifdef SLAPD_AUTHPASSWD
4378 /* needs updating */
4379 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4380 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4383 /* OpenLDAP Void Syntax */
4384 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4385 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4386 {NULL, 0, NULL, NULL, NULL}
4390 char *certificateExactMatchSyntaxes[] = {
4391 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4395 char *directoryStringSyntaxes[] = {
4396 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4399 char *integerFirstComponentMatchSyntaxes[] = {
4400 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4401 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
4404 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4405 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4406 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4407 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
4408 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4409 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4410 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4411 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4412 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4417 * Other matching rules in X.520 that we do not use (yet):
4419 * 2.5.13.9 numericStringOrderingMatch
4420 * 2.5.13.19 octetStringSubstringsMatch
4421 * 2.5.13.25 uTCTimeMatch
4422 * 2.5.13.26 uTCTimeOrderingMatch
4423 * 2.5.13.31 directoryStringFirstComponentMatch
4424 * 2.5.13.32 wordMatch
4425 * 2.5.13.33 keywordMatch
4426 * 2.5.13.35 certificateMatch
4427 * 2.5.13.36 certificatePairExactMatch
4428 * 2.5.13.37 certificatePairMatch
4429 * 2.5.13.38 certificateListExactMatch
4430 * 2.5.13.39 certificateListMatch
4431 * 2.5.13.40 algorithmIdentifierMatch
4432 * 2.5.13.41 storedPrefixMatch
4433 * 2.5.13.42 attributeCertificateMatch
4434 * 2.5.13.43 readerAndKeyIDMatch
4435 * 2.5.13.44 attributeIntegrityMatch
4437 static slap_mrule_defs_rec mrule_defs[] = {
4439 * EQUALITY matching rules must be listed after associated APPROX
4440 * matching rules. So, we list all APPROX matching rules first.
4442 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4443 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4444 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4446 directoryStringApproxMatch,
4447 directoryStringApproxIndexer,
4448 directoryStringApproxFilter,
4451 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4452 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4453 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4455 IA5StringApproxMatch,
4456 IA5StringApproxIndexer,
4457 IA5StringApproxFilter,
4461 * Other matching rules
4464 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4465 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4466 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4468 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4471 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4472 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4473 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4475 dnMatch, dnIndexer, dnFilter,
4478 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4479 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4480 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4481 directoryStringSyntaxes,
4483 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4484 directoryStringApproxMatchOID },
4486 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4487 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4488 SLAP_MR_ORDERING, directoryStringSyntaxes,
4490 caseIgnoreOrderingMatch, NULL, NULL,
4493 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4495 SLAP_MR_SUBSTR, NULL,
4497 caseExactIgnoreSubstringsMatch,
4498 caseExactIgnoreSubstringsIndexer,
4499 caseExactIgnoreSubstringsFilter,
4502 {"( 2.5.13.5 NAME 'caseExactMatch' "
4503 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4504 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4506 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4507 directoryStringApproxMatchOID },
4509 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4510 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4511 SLAP_MR_ORDERING, directoryStringSyntaxes,
4513 caseExactOrderingMatch, NULL, NULL,
4516 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4517 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4518 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4520 caseExactIgnoreSubstringsMatch,
4521 caseExactIgnoreSubstringsIndexer,
4522 caseExactIgnoreSubstringsFilter,
4525 {"( 2.5.13.8 NAME 'numericStringMatch' "
4526 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4527 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4530 caseIgnoreIA5Indexer,
4531 caseIgnoreIA5Filter,
4534 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4535 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4536 SLAP_MR_SUBSTR, NULL,
4538 caseIgnoreIA5SubstringsMatch,
4539 caseIgnoreIA5SubstringsIndexer,
4540 caseIgnoreIA5SubstringsFilter,
4543 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4545 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4547 caseIgnoreListMatch, NULL, NULL,
4550 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4552 SLAP_MR_SUBSTR, NULL,
4554 caseIgnoreListSubstringsMatch, NULL, NULL,
4557 {"( 2.5.13.13 NAME 'booleanMatch' "
4558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4559 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4561 booleanMatch, NULL, NULL,
4564 {"( 2.5.13.14 NAME 'integerMatch' "
4565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4566 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4568 integerMatch, integerIndexer, integerFilter,
4571 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4572 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4573 SLAP_MR_ORDERING, NULL,
4575 integerOrderingMatch, NULL, NULL,
4578 {"( 2.5.13.16 NAME 'bitStringMatch' "
4579 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4580 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4582 bitStringMatch, bitStringIndexer, bitStringFilter,
4585 {"( 2.5.13.17 NAME 'octetStringMatch' "
4586 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4587 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4589 octetStringMatch, octetStringIndexer, octetStringFilter,
4592 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4593 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4594 SLAP_MR_ORDERING, NULL,
4596 octetStringOrderingMatch, NULL, NULL,
4599 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4600 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4601 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4603 telephoneNumberMatch,
4604 telephoneNumberIndexer,
4605 telephoneNumberFilter,
4608 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4609 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4610 SLAP_MR_SUBSTR, NULL,
4612 telephoneNumberSubstringsMatch,
4613 telephoneNumberSubstringsIndexer,
4614 telephoneNumberSubstringsFilter,
4617 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4618 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4619 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4624 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4625 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4626 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4628 uniqueMemberMatch, NULL, NULL,
4631 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4632 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4633 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4635 protocolInformationMatch, NULL, NULL,
4638 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4639 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4640 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4642 generalizedTimeMatch, NULL, NULL,
4645 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4646 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4647 SLAP_MR_ORDERING, NULL,
4649 generalizedTimeOrderingMatch, NULL, NULL,
4652 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4653 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4654 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
4656 integerFirstComponentMatch, NULL, NULL,
4659 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4660 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4661 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4662 objectIdentifierFirstComponentMatchSyntaxes,
4664 objectIdentifierFirstComponentMatch, NULL, NULL,
4668 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4669 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4670 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4671 certificateExactConvert, NULL,
4672 certificateExactMatch,
4673 certificateExactIndexer, certificateExactFilter,
4677 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4678 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4679 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4681 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4682 IA5StringApproxMatchOID },
4684 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4685 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4686 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4688 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4689 IA5StringApproxMatchOID },
4691 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4692 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4693 SLAP_MR_SUBSTR, NULL,
4695 caseIgnoreIA5SubstringsMatch,
4696 caseIgnoreIA5SubstringsIndexer,
4697 caseIgnoreIA5SubstringsFilter,
4700 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4702 SLAP_MR_SUBSTR, NULL,
4704 caseExactIA5SubstringsMatch,
4705 caseExactIA5SubstringsIndexer,
4706 caseExactIA5SubstringsFilter,
4709 #ifdef SLAPD_AUTHPASSWD
4710 /* needs updating */
4711 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4712 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4713 SLAP_MR_EQUALITY, NULL,
4715 authPasswordMatch, NULL, NULL,
4719 #ifdef SLAPD_ACI_ENABLED
4720 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4721 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4722 SLAP_MR_EQUALITY, NULL,
4724 OpenLDAPaciMatch, NULL, NULL,
4728 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4729 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4732 integerBitAndMatch, NULL, NULL,
4735 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4736 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4739 integerBitOrMatch, NULL, NULL,
4742 {NULL, SLAP_MR_NONE, NULL,
4743 NULL, NULL, NULL, NULL, NULL,
4748 slap_schema_init( void )
4753 /* we should only be called once (from main) */
4754 assert( schema_init_done == 0 );
4756 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4757 res = register_syntax( &syntax_defs[i] );
4760 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4761 syntax_defs[i].sd_desc );
4766 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4767 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4768 mrule_defs[i].mrd_compat_syntaxes == NULL )
4771 "slap_schema_init: Ingoring unusable matching rule %s\n",
4772 mrule_defs[i].mrd_desc );
4776 res = register_matching_rule( &mrule_defs[i] );
4780 "slap_schema_init: Error registering matching rule %s\n",
4781 mrule_defs[i].mrd_desc );
4786 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4787 *mr_ptr[i].mr = mr_find( mr_ptr[i].oid );
4789 res = slap_schema_load();
4790 schema_init_done = 1;
4795 schema_destroy( void )
4801 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4802 *mr_ptr[i].mr = NULL;