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;
302 struct berval *normalized )
305 * A normalized bitString is has no extaneous (leading) zero bits.
306 * That is, '00010'B is normalized to '10'B
307 * However, as a special case, '0'B requires no normalization.
311 /* start at the first bit */
314 /* Find the first non-zero bit */
315 while ( *p == '0' ) p++;
318 /* no non-zero bits */
319 ber_str2bv( "\'0\'B", sizeof("\'0\'B") - 1, 1, normalized );
323 normalized->bv_val = ch_malloc( val->bv_len + 1 );
325 normalized->bv_val[0] = '\'';
326 normalized->bv_len = 1;
328 for( ; *p != '\0'; p++ ) {
329 normalized->bv_val[normalized->bv_len++] = *p;
332 normalized->bv_val[normalized->bv_len] = '\0';
346 if( in->bv_len == 0 ) return LDAP_SUCCESS;
348 ber_dupbv( &dn, in );
349 if( !dn.bv_val ) return LDAP_OTHER;
351 if( dn.bv_val[dn.bv_len-1] == 'B'
352 && dn.bv_val[dn.bv_len-2] == '\'' )
354 /* assume presence of optional UID */
357 for(i=dn.bv_len-3; i>1; i--) {
358 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
362 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
363 ber_memfree( dn.bv_val );
364 return LDAP_INVALID_SYNTAX;
367 /* trim the UID to allow use of dnValidate */
368 dn.bv_val[i-1] = '\0';
372 rc = dnValidate( NULL, &dn );
374 ber_memfree( dn.bv_val );
382 struct berval *normalized )
387 ber_dupbv( &out, val );
388 if( out.bv_len != 0 ) {
389 struct berval uidin = { 0, NULL };
390 struct berval uidout = { 0, NULL };
392 if( out.bv_val[out.bv_len-1] == 'B'
393 && out.bv_val[out.bv_len-2] == '\'' )
395 /* assume presence of optional UID */
396 uidin.bv_val = strrchr( out.bv_val, '#' );
398 if( uidin.bv_val == NULL ) {
400 return LDAP_INVALID_SYNTAX;
403 uidin.bv_len = out.bv_len - (uidin.bv_val - out.bv_val);
404 out.bv_len -= uidin.bv_len--;
406 /* temporarily trim the UID */
407 *(uidin.bv_val++) = '\0';
409 rc = bitStringNormalize( syntax, &uidin, &uidout );
411 if( rc != LDAP_SUCCESS ) {
413 return LDAP_INVALID_SYNTAX;
417 rc = dnNormalize2( NULL, &out, normalized );
419 if( rc != LDAP_SUCCESS ) {
421 free( uidout.bv_val );
422 return LDAP_INVALID_SYNTAX;
425 if( uidout.bv_len ) {
426 normalized->bv_val = ch_realloc( normalized->bv_val,
427 normalized->bv_len + uidout.bv_len + sizeof("#") );
429 /* insert the separator */
430 normalized->bv_val[normalized->bv_len++] = '#';
433 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
434 uidout.bv_val, uidout.bv_len );
435 normalized->bv_len += uidout.bv_len;
438 normalized->bv_val[normalized->bv_len] = '\0';
448 * Handling boolean syntax and matching is quite rigid.
449 * A more flexible approach would be to allow a variety
450 * of strings to be normalized and prettied into TRUE
458 /* very unforgiving validation, requires no normalization
459 * before simplistic matching
462 if( in->bv_len == 4 ) {
463 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
466 } else if( in->bv_len == 5 ) {
467 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
472 return LDAP_INVALID_SYNTAX;
481 struct berval *value,
482 void *assertedValue )
484 /* simplistic matching allowed by rigid validation */
485 struct berval *asserted = (struct berval *) assertedValue;
486 *matchp = value->bv_len != asserted->bv_len;
490 /*-------------------------------------------------------------------
491 LDAP/X.500 string syntax / matching rules have a few oddities. This
492 comment attempts to detail how slapd(8) treats them.
495 StringSyntax X.500 LDAP Matching
496 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
497 PrintableString subset subset i/e + ignore insignificant spaces
498 NumericString subset subset ignore all spaces
499 IA5String ASCII ASCII i/e + ignore insignificant spaces
500 TeletexString T.61 T.61 i/e + ignore insignificant spaces
502 TelephoneNumber subset subset i + ignore all spaces and "-"
504 See draft-ietf-ldapbis-strpro for details (once published).
508 In X.500(93), a directory string can be either a PrintableString,
509 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
510 In later versions, more CHOICEs were added. In all cases the string
513 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
515 For matching, there are both case ignore and exact rules. Both
516 also require that "insignificant" spaces be ignored.
517 spaces before the first non-space are ignored;
518 spaces after the last non-space are ignored;
519 spaces after a space are ignored.
520 Note: by these rules (and as clarified in X.520), a string of only
521 spaces is to be treated as if held one space, not empty (which
522 would be a syntax error).
525 In ASN.1, numeric string is just a string of digits and spaces
526 and could be empty. However, in X.500, all attribute values of
527 numeric string carry a non-empty constraint. For example:
529 internationalISDNNumber ATTRIBUTE ::= {
530 WITH SYNTAX InternationalISDNNumber
531 EQUALITY MATCHING RULE numericStringMatch
532 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
533 ID id-at-internationalISDNNumber }
534 InternationalISDNNumber ::=
535 NumericString (SIZE(1..ub-international-isdn-number))
537 Unforunately, some assertion values are don't carry the same
538 constraint (but its unclear how such an assertion could ever
539 be true). In LDAP, there is one syntax (numericString) not two
540 (numericString with constraint, numericString without constraint).
541 This should be treated as numericString with non-empty constraint.
542 Note that while someone may have no ISDN number, there are no ISDN
543 numbers which are zero length.
545 In matching, spaces are ignored.
548 In ASN.1, Printable string is just a string of printable characters
549 and can be empty. In X.500, semantics much like NumericString (see
550 serialNumber for a like example) excepting uses insignificant space
551 handling instead of ignore all spaces.
554 Basically same as PrintableString. There are no examples in X.500,
555 but same logic applies. So we require them to be non-empty as
558 -------------------------------------------------------------------*/
567 unsigned char *u = in->bv_val;
569 if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
571 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
572 /* get the length indicated by the first byte */
573 len = LDAP_UTF8_CHARLEN2( u, len );
575 /* very basic checks */
578 if( (u[5] & 0xC0) != 0x80 ) {
579 return LDAP_INVALID_SYNTAX;
582 if( (u[4] & 0xC0) != 0x80 ) {
583 return LDAP_INVALID_SYNTAX;
586 if( (u[3] & 0xC0) != 0x80 ) {
587 return LDAP_INVALID_SYNTAX;
590 if( (u[2] & 0xC0 )!= 0x80 ) {
591 return LDAP_INVALID_SYNTAX;
594 if( (u[1] & 0xC0) != 0x80 ) {
595 return LDAP_INVALID_SYNTAX;
598 /* CHARLEN already validated it */
601 return LDAP_INVALID_SYNTAX;
604 /* make sure len corresponds with the offset
605 to the next character */
606 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
609 if( count != 0 ) return LDAP_INVALID_SYNTAX;
618 struct berval *normalized )
623 /* validator should have refused an empty string */
624 assert( val->bv_len );
628 /* Ignore initial whitespace */
629 /* All space is ASCII. All ASCII is 1 byte */
630 for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
632 normalized->bv_len = val->bv_len - (p - val->bv_val);
634 if( !normalized->bv_len ) {
635 ber_mem2bv( " ", 1, 1, normalized );
639 ber_mem2bv( p, normalized->bv_len, 1, normalized );
640 e = normalized->bv_val + normalized->bv_len;
642 assert( normalized->bv_val );
644 p = q = normalized->bv_val;
649 if ( ASCII_SPACE( *p ) ) {
654 /* Ignore the extra whitespace */
655 while ( ASCII_SPACE( *p ) ) {
659 len = LDAP_UTF8_COPY(q,p);
665 assert( normalized->bv_val <= p );
666 assert( q+len <= p );
668 /* cannot start with a space */
669 assert( !ASCII_SPACE( normalized->bv_val[0] ) );
672 * If the string ended in space, backup the pointer one
673 * position. One is enough because the above loop collapsed
674 * all whitespace to a single space.
682 /* cannot end with a space */
683 assert( !ASCII_SPACE( *q ) );
690 normalized->bv_len = q - normalized->bv_val;
695 /* Returns Unicode canonically normalized copy of a substring assertion
696 * Skipping attribute description */
697 static SubstringsAssertion *
698 UTF8SubstringsassertionNormalize(
699 SubstringsAssertion *sa,
702 SubstringsAssertion *nsa;
705 nsa = (SubstringsAssertion *)SLAP_CALLOC( 1, sizeof(SubstringsAssertion) );
710 if( sa->sa_initial.bv_val != NULL ) {
711 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
712 if( nsa->sa_initial.bv_val == NULL ) {
717 if( sa->sa_any != NULL ) {
718 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
721 nsa->sa_any = (struct berval *)
722 SLAP_MALLOC( (i + 1) * sizeof(struct berval) );
723 if( nsa->sa_any == NULL ) {
727 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
728 UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
730 if( nsa->sa_any[i].bv_val == NULL ) {
734 nsa->sa_any[i].bv_val = NULL;
737 if( sa->sa_final.bv_val != NULL ) {
738 UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
739 if( nsa->sa_final.bv_val == NULL ) {
747 if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
748 if ( nsa->sa_any ) ber_bvarray_free( nsa->sa_any );
749 if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
754 #ifndef SLAPD_APPROX_OLDSINGLESTRING
756 #if defined(SLAPD_APPROX_INITIALS)
757 #define SLAPD_APPROX_DELIMITER "._ "
758 #define SLAPD_APPROX_WORDLEN 2
760 #define SLAPD_APPROX_DELIMITER " "
761 #define SLAPD_APPROX_WORDLEN 1
770 struct berval *value,
771 void *assertedValue )
773 struct berval *nval, *assertv;
774 char *val, **values, **words, *c;
775 int i, count, len, nextchunk=0, nextavail=0;
777 /* Yes, this is necessary */
778 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
784 /* Yes, this is necessary */
785 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
786 NULL, LDAP_UTF8_APPROX );
787 if( assertv == NULL ) {
793 /* Isolate how many words there are */
794 for ( c = nval->bv_val, count = 1; *c; c++ ) {
795 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
796 if ( c == NULL ) break;
801 /* Get a phonetic copy of each word */
802 words = (char **)ch_malloc( count * sizeof(char *) );
803 values = (char **)ch_malloc( count * sizeof(char *) );
804 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
806 values[i] = phonetic(c);
809 /* Work through the asserted value's words, to see if at least some
810 of the words are there, in the same order. */
812 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
813 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
818 #if defined(SLAPD_APPROX_INITIALS)
819 else if( len == 1 ) {
820 /* Single letter words need to at least match one word's initial */
821 for( i=nextavail; i<count; i++ )
822 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
829 /* Isolate the next word in the asserted value and phonetic it */
830 assertv->bv_val[nextchunk+len] = '\0';
831 val = phonetic( assertv->bv_val + nextchunk );
833 /* See if this phonetic chunk is in the remaining words of *value */
834 for( i=nextavail; i<count; i++ ){
835 if( !strcmp( val, values[i] ) ){
843 /* This chunk in the asserted value was NOT within the *value. */
849 /* Go on to the next word in the asserted value */
853 /* If some of the words were seen, call it a match */
854 if( nextavail > 0 ) {
862 ber_bvfree( assertv );
863 for( i=0; i<count; i++ ) {
864 ch_free( values[i] );
879 struct berval *prefix,
884 int i,j, len, wordcount, keycount=0;
885 struct berval *newkeys;
888 for( j=0; values[j].bv_val != NULL; j++ ) {
889 struct berval val = { 0, NULL };
890 /* Yes, this is necessary */
891 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
892 assert( val.bv_val != NULL );
894 /* Isolate how many words there are. There will be a key for each */
895 for( wordcount = 0, c = val.bv_val; *c; c++) {
896 len = strcspn(c, SLAPD_APPROX_DELIMITER);
897 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
899 if (*c == '\0') break;
903 /* Allocate/increase storage to account for new keys */
904 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
905 * sizeof(struct berval) );
906 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
907 if( keys ) ch_free( keys );
910 /* Get a phonetic copy of each word */
911 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
913 if( len < SLAPD_APPROX_WORDLEN ) continue;
914 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
919 ber_memfree( val.bv_val );
921 keys[keycount].bv_val = NULL;
933 struct berval *prefix,
934 void * assertedValue,
942 /* Yes, this is necessary */
943 val = UTF8bvnormalize( ((struct berval *)assertedValue),
944 NULL, LDAP_UTF8_APPROX );
945 if( val == NULL || val->bv_val == NULL ) {
946 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
947 keys[0].bv_val = NULL;
953 /* Isolate how many words there are. There will be a key for each */
954 for( count = 0,c = val->bv_val; *c; c++) {
955 len = strcspn(c, SLAPD_APPROX_DELIMITER);
956 if( len >= SLAPD_APPROX_WORDLEN ) count++;
958 if (*c == '\0') break;
962 /* Allocate storage for new keys */
963 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
965 /* Get a phonetic copy of each word */
966 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
968 if( len < SLAPD_APPROX_WORDLEN ) continue;
969 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
975 keys[count].bv_val = NULL;
983 /* No other form of Approximate Matching is defined */
991 struct berval *value,
992 void *assertedValue )
994 char *vapprox, *avapprox;
997 /* Yes, this is necessary */
998 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1001 return LDAP_SUCCESS;
1004 /* Yes, this is necessary */
1005 t = UTF8normalize( ((struct berval *)assertedValue),
1010 return LDAP_SUCCESS;
1013 vapprox = phonetic( strip8bitChars( s ) );
1014 avapprox = phonetic( strip8bitChars( t ) );
1019 *matchp = strcmp( vapprox, avapprox );
1022 ch_free( avapprox );
1024 return LDAP_SUCCESS;
1033 struct berval *prefix,
1041 for( i=0; values[i].bv_val != NULL; i++ ) {
1042 /* empty - just count them */
1045 /* we should have at least one value at this point */
1048 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1050 /* Copy each value and run it through phonetic() */
1051 for( i=0; values[i].bv_val != NULL; i++ ) {
1052 /* Yes, this is necessary */
1053 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1055 /* strip 8-bit chars and run through phonetic() */
1056 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1059 keys[i].bv_val = NULL;
1062 return LDAP_SUCCESS;
1072 struct berval *prefix,
1073 void * assertedValue,
1079 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1081 /* Yes, this is necessary */
1082 s = UTF8normalize( ((struct berval *)assertedValue),
1087 /* strip 8-bit chars and run through phonetic() */
1088 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1094 return LDAP_SUCCESS;
1105 struct berval *value,
1106 void *assertedValue )
1108 *matchp = UTF8bvnormcmp( value,
1109 (struct berval *) assertedValue,
1110 LDAP_UTF8_NOCASEFOLD );
1111 return LDAP_SUCCESS;
1115 caseExactIgnoreSubstringsMatch(
1120 struct berval *value,
1121 void *assertedValue )
1124 SubstringsAssertion *sub = NULL;
1125 struct berval left = { 0, NULL };
1131 casefold = ( mr != caseExactSubstringsMatchingRule )
1132 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1134 if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1140 sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1146 /* Add up asserted input length */
1147 if( sub->sa_initial.bv_val ) {
1148 inlen += sub->sa_initial.bv_len;
1151 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1152 inlen += sub->sa_any[i].bv_len;
1155 if( sub->sa_final.bv_val ) {
1156 inlen += sub->sa_final.bv_len;
1159 if( sub->sa_initial.bv_val ) {
1160 if( inlen > left.bv_len ) {
1165 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1166 sub->sa_initial.bv_len );
1172 left.bv_val += sub->sa_initial.bv_len;
1173 left.bv_len -= sub->sa_initial.bv_len;
1174 inlen -= sub->sa_initial.bv_len;
1177 if( sub->sa_final.bv_val ) {
1178 if( inlen > left.bv_len ) {
1183 match = memcmp( sub->sa_final.bv_val,
1184 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1185 sub->sa_final.bv_len );
1191 left.bv_len -= sub->sa_final.bv_len;
1192 inlen -= sub->sa_final.bv_len;
1196 for(i=0; sub->sa_any[i].bv_val; i++) {
1201 if( inlen > left.bv_len ) {
1202 /* not enough length */
1207 if( sub->sa_any[i].bv_len == 0 ) {
1211 p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1217 idx = p - left.bv_val;
1219 if( idx >= left.bv_len ) {
1220 /* this shouldn't happen */
1222 if ( sub->sa_final.bv_val )
1223 ch_free( sub->sa_final.bv_val );
1225 ber_bvarray_free( sub->sa_any );
1226 if ( sub->sa_initial.bv_val )
1227 ch_free( sub->sa_initial.bv_val );
1235 if( sub->sa_any[i].bv_len > left.bv_len ) {
1236 /* not enough left */
1241 match = memcmp( left.bv_val,
1242 sub->sa_any[i].bv_val,
1243 sub->sa_any[i].bv_len );
1251 left.bv_val += sub->sa_any[i].bv_len;
1252 left.bv_len -= sub->sa_any[i].bv_len;
1253 inlen -= sub->sa_any[i].bv_len;
1260 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1261 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1262 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1266 return LDAP_SUCCESS;
1269 /* Index generation function */
1270 static int caseExactIgnoreIndexer(
1275 struct berval *prefix,
1283 HASH_CONTEXT HASHcontext;
1284 unsigned char HASHdigest[HASH_BYTES];
1285 struct berval digest;
1286 digest.bv_val = HASHdigest;
1287 digest.bv_len = sizeof(HASHdigest);
1289 for( i=0; values[i].bv_val != NULL; i++ ) {
1290 /* empty - just count them */
1293 /* we should have at least one value at this point */
1296 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1298 slen = syntax->ssyn_oidlen;
1299 mlen = mr->smr_oidlen;
1301 casefold = ( mr != caseExactMatchingRule )
1302 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1304 for( i=0; values[i].bv_val != NULL; i++ ) {
1305 struct berval value;
1306 UTF8bvnormalize( &values[i], &value, casefold );
1308 HASH_Init( &HASHcontext );
1309 if( prefix != NULL && prefix->bv_len > 0 ) {
1310 HASH_Update( &HASHcontext,
1311 prefix->bv_val, prefix->bv_len );
1313 HASH_Update( &HASHcontext,
1314 syntax->ssyn_oid, slen );
1315 HASH_Update( &HASHcontext,
1316 mr->smr_oid, mlen );
1317 HASH_Update( &HASHcontext,
1318 value.bv_val, value.bv_len );
1319 HASH_Final( HASHdigest, &HASHcontext );
1321 free( value.bv_val );
1323 ber_dupbv( &keys[i], &digest );
1326 keys[i].bv_val = NULL;
1328 return LDAP_SUCCESS;
1331 /* Index generation function */
1332 static int caseExactIgnoreFilter(
1337 struct berval *prefix,
1338 void * assertedValue,
1344 HASH_CONTEXT HASHcontext;
1345 unsigned char HASHdigest[HASH_BYTES];
1346 struct berval value = { 0, NULL };
1347 struct berval digest;
1349 digest.bv_val = HASHdigest;
1350 digest.bv_len = sizeof(HASHdigest);
1352 slen = syntax->ssyn_oidlen;
1353 mlen = mr->smr_oidlen;
1355 casefold = ( mr != caseExactMatchingRule )
1356 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1358 UTF8bvnormalize( (struct berval *) assertedValue, &value, casefold );
1359 /* This usually happens if filter contains bad UTF8 */
1360 if( value.bv_val == NULL ) {
1361 keys = ch_malloc( sizeof( struct berval ) );
1362 keys[0].bv_val = NULL;
1363 return LDAP_SUCCESS;
1366 keys = ch_malloc( sizeof( struct berval ) * 2 );
1368 HASH_Init( &HASHcontext );
1369 if( prefix != NULL && prefix->bv_len > 0 ) {
1370 HASH_Update( &HASHcontext,
1371 prefix->bv_val, prefix->bv_len );
1373 HASH_Update( &HASHcontext,
1374 syntax->ssyn_oid, slen );
1375 HASH_Update( &HASHcontext,
1376 mr->smr_oid, mlen );
1377 HASH_Update( &HASHcontext,
1378 value.bv_val, value.bv_len );
1379 HASH_Final( HASHdigest, &HASHcontext );
1381 ber_dupbv( keys, &digest );
1382 keys[1].bv_val = NULL;
1384 free( value.bv_val );
1387 return LDAP_SUCCESS;
1390 /* Substrings Index generation function */
1391 static int caseExactIgnoreSubstringsIndexer(
1396 struct berval *prefix,
1406 HASH_CONTEXT HASHcontext;
1407 unsigned char HASHdigest[HASH_BYTES];
1408 struct berval digest;
1409 digest.bv_val = HASHdigest;
1410 digest.bv_len = sizeof(HASHdigest);
1414 for( i=0; values[i].bv_val != NULL; i++ ) {
1415 /* empty - just count them */
1418 /* we should have at least one value at this point */
1421 casefold = ( mr != caseExactSubstringsMatchingRule )
1422 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1424 nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1425 for( i=0; values[i].bv_val != NULL; i++ ) {
1426 UTF8bvnormalize( &values[i], &nvalues[i], casefold );
1428 nvalues[i].bv_val = NULL;
1431 for( i=0; values[i].bv_val != NULL; i++ ) {
1432 /* count number of indices to generate */
1433 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1437 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1438 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1439 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1440 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1442 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1446 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1447 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1448 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1452 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1453 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1454 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1455 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1457 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1463 /* no keys to generate */
1465 ber_bvarray_free( nvalues );
1466 return LDAP_SUCCESS;
1469 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1471 slen = syntax->ssyn_oidlen;
1472 mlen = mr->smr_oidlen;
1475 for( i=0; values[i].bv_val != NULL; i++ ) {
1478 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1480 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1481 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1483 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1484 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1486 for( j=0; j<max; j++ ) {
1487 HASH_Init( &HASHcontext );
1488 if( prefix != NULL && prefix->bv_len > 0 ) {
1489 HASH_Update( &HASHcontext,
1490 prefix->bv_val, prefix->bv_len );
1493 HASH_Update( &HASHcontext,
1494 &pre, sizeof( pre ) );
1495 HASH_Update( &HASHcontext,
1496 syntax->ssyn_oid, slen );
1497 HASH_Update( &HASHcontext,
1498 mr->smr_oid, mlen );
1499 HASH_Update( &HASHcontext,
1500 &values[i].bv_val[j],
1501 SLAP_INDEX_SUBSTR_MAXLEN );
1502 HASH_Final( HASHdigest, &HASHcontext );
1504 ber_dupbv( &keys[nkeys++], &digest );
1508 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1509 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1511 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1514 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1515 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1516 HASH_Init( &HASHcontext );
1517 if( prefix != NULL && prefix->bv_len > 0 ) {
1518 HASH_Update( &HASHcontext,
1519 prefix->bv_val, prefix->bv_len );
1521 HASH_Update( &HASHcontext,
1522 &pre, sizeof( pre ) );
1523 HASH_Update( &HASHcontext,
1524 syntax->ssyn_oid, slen );
1525 HASH_Update( &HASHcontext,
1526 mr->smr_oid, mlen );
1527 HASH_Update( &HASHcontext,
1528 values[i].bv_val, j );
1529 HASH_Final( HASHdigest, &HASHcontext );
1531 ber_dupbv( &keys[nkeys++], &digest );
1534 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1535 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1536 HASH_Init( &HASHcontext );
1537 if( prefix != NULL && prefix->bv_len > 0 ) {
1538 HASH_Update( &HASHcontext,
1539 prefix->bv_val, prefix->bv_len );
1541 HASH_Update( &HASHcontext,
1542 &pre, sizeof( pre ) );
1543 HASH_Update( &HASHcontext,
1544 syntax->ssyn_oid, slen );
1545 HASH_Update( &HASHcontext,
1546 mr->smr_oid, mlen );
1547 HASH_Update( &HASHcontext,
1548 &values[i].bv_val[values[i].bv_len-j], j );
1549 HASH_Final( HASHdigest, &HASHcontext );
1551 ber_dupbv( &keys[nkeys++], &digest );
1559 keys[nkeys].bv_val = NULL;
1566 ber_bvarray_free( nvalues );
1568 return LDAP_SUCCESS;
1571 static int caseExactIgnoreSubstringsFilter(
1576 struct berval *prefix,
1577 void * assertedValue,
1580 SubstringsAssertion *sa;
1583 ber_len_t nkeys = 0;
1584 size_t slen, mlen, klen;
1586 HASH_CONTEXT HASHcontext;
1587 unsigned char HASHdigest[HASH_BYTES];
1588 struct berval *value;
1589 struct berval digest;
1591 casefold = ( mr != caseExactSubstringsMatchingRule )
1592 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1594 sa = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1597 return LDAP_SUCCESS;
1600 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1601 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1606 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1608 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1609 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1610 /* don't bother accounting for stepping */
1611 nkeys += sa->sa_any[i].bv_len -
1612 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1617 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1618 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1624 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1625 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1626 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1629 return LDAP_SUCCESS;
1632 digest.bv_val = HASHdigest;
1633 digest.bv_len = sizeof(HASHdigest);
1635 slen = syntax->ssyn_oidlen;
1636 mlen = mr->smr_oidlen;
1638 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1641 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1642 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1644 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1645 value = &sa->sa_initial;
1647 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1648 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1650 HASH_Init( &HASHcontext );
1651 if( prefix != NULL && prefix->bv_len > 0 ) {
1652 HASH_Update( &HASHcontext,
1653 prefix->bv_val, prefix->bv_len );
1655 HASH_Update( &HASHcontext,
1656 &pre, sizeof( pre ) );
1657 HASH_Update( &HASHcontext,
1658 syntax->ssyn_oid, slen );
1659 HASH_Update( &HASHcontext,
1660 mr->smr_oid, mlen );
1661 HASH_Update( &HASHcontext,
1662 value->bv_val, klen );
1663 HASH_Final( HASHdigest, &HASHcontext );
1665 ber_dupbv( &keys[nkeys++], &digest );
1668 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1670 pre = SLAP_INDEX_SUBSTR_PREFIX;
1671 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1673 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1674 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1678 value = &sa->sa_any[i];
1681 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1682 j += SLAP_INDEX_SUBSTR_STEP )
1684 HASH_Init( &HASHcontext );
1685 if( prefix != NULL && prefix->bv_len > 0 ) {
1686 HASH_Update( &HASHcontext,
1687 prefix->bv_val, prefix->bv_len );
1689 HASH_Update( &HASHcontext,
1690 &pre, sizeof( pre ) );
1691 HASH_Update( &HASHcontext,
1692 syntax->ssyn_oid, slen );
1693 HASH_Update( &HASHcontext,
1694 mr->smr_oid, mlen );
1695 HASH_Update( &HASHcontext,
1696 &value->bv_val[j], klen );
1697 HASH_Final( HASHdigest, &HASHcontext );
1699 ber_dupbv( &keys[nkeys++], &digest );
1705 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1706 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1708 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1709 value = &sa->sa_final;
1711 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1712 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1714 HASH_Init( &HASHcontext );
1715 if( prefix != NULL && prefix->bv_len > 0 ) {
1716 HASH_Update( &HASHcontext,
1717 prefix->bv_val, prefix->bv_len );
1719 HASH_Update( &HASHcontext,
1720 &pre, sizeof( pre ) );
1721 HASH_Update( &HASHcontext,
1722 syntax->ssyn_oid, slen );
1723 HASH_Update( &HASHcontext,
1724 mr->smr_oid, mlen );
1725 HASH_Update( &HASHcontext,
1726 &value->bv_val[value->bv_len-klen], klen );
1727 HASH_Final( HASHdigest, &HASHcontext );
1729 ber_dupbv( &keys[nkeys++], &digest );
1733 keys[nkeys].bv_val = NULL;
1739 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1740 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1741 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1744 return LDAP_SUCCESS;
1753 struct berval *value,
1754 void *assertedValue )
1756 *matchp = UTF8bvnormcmp( value,
1757 (struct berval *) assertedValue,
1758 LDAP_UTF8_CASEFOLD );
1759 return LDAP_SUCCESS;
1762 /* Remove all spaces and '-' characters */
1764 telephoneNumberNormalize(
1767 struct berval *normalized )
1771 /* validator should have refused an empty string */
1772 assert( val->bv_len );
1774 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1776 for( p = val->bv_val; *p; p++ ) {
1777 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1783 normalized->bv_len = q - normalized->bv_val;
1785 if( normalized->bv_len == 0 ) {
1786 free( normalized->bv_val );
1787 return LDAP_INVALID_SYNTAX;
1790 return LDAP_SUCCESS;
1796 struct berval *val )
1800 if( val->bv_len == 0 ) {
1801 /* disallow empty strings */
1802 return LDAP_INVALID_SYNTAX;
1805 if( OID_LEADCHAR(val->bv_val[0]) ) {
1807 for(i=1; i < val->bv_len; i++) {
1808 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1809 if( dot++ ) return 1;
1810 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1813 return LDAP_INVALID_SYNTAX;
1817 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1819 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1820 for(i=1; i < val->bv_len; i++) {
1821 if( !DESC_CHAR(val->bv_val[i] ) ) {
1822 return LDAP_INVALID_SYNTAX;
1826 return LDAP_SUCCESS;
1829 return LDAP_INVALID_SYNTAX;
1838 struct berval *value,
1839 void *assertedValue )
1842 int vsign = 1, avsign = 1; /* default sign = '+' */
1843 struct berval *asserted;
1844 ber_len_t vlen, avlen;
1847 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1849 vlen = value->bv_len;
1850 if( mr == integerFirstComponentMatchingRule ) {
1851 char *tmp = memchr( v, '$', vlen );
1854 while( vlen && ASCII_SPACE( v[vlen-1] ))
1857 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) /* ANSI 2.2.1 */
1863 /* Do the same with the *assertedValue number */
1864 asserted = (struct berval *) assertedValue;
1865 av = asserted->bv_val;
1866 avlen = asserted->bv_len;
1867 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1873 match = vsign - avsign;
1875 match = (vlen != avlen
1876 ? ( vlen < avlen ? -1 : 1 )
1877 : memcmp( v, av, vlen ));
1883 return LDAP_SUCCESS;
1889 struct berval *val )
1893 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1895 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1896 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1897 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1898 return LDAP_INVALID_SYNTAX;
1901 for( i=1; i < val->bv_len; i++ ) {
1902 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1905 return LDAP_SUCCESS;
1912 struct berval *normalized )
1922 /* Ignore leading spaces */
1923 while ( len && ( *p == ' ' )) {
1930 negative = ( *p == '-' );
1931 if(( *p == '-' ) || ( *p == '+' )) {
1937 /* Ignore leading zeros */
1938 while ( len && ( *p == '0' )) {
1943 /* If there are no non-zero digits left, the number is zero, otherwise
1944 allocate space for the number and copy it into the buffer */
1946 normalized->bv_val = ch_strdup("0");
1947 normalized->bv_len = 1;
1950 normalized->bv_len = len+negative;
1951 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1953 normalized->bv_val[0] = '-';
1955 AC_MEMCPY( normalized->bv_val + negative, p, len );
1956 normalized->bv_val[len+negative] = '\0';
1959 return LDAP_SUCCESS;
1962 /* Index generation function */
1963 static int integerIndexer(
1968 struct berval *prefix,
1975 HASH_CONTEXT HASHcontext;
1976 unsigned char HASHdigest[HASH_BYTES];
1977 struct berval digest;
1978 digest.bv_val = HASHdigest;
1979 digest.bv_len = sizeof(HASHdigest);
1981 for( i=0; values[i].bv_val != NULL; i++ ) {
1982 /* empty - just count them */
1985 /* we should have at least one value at this point */
1988 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1990 slen = syntax->ssyn_oidlen;
1991 mlen = mr->smr_oidlen;
1993 for( i=0; values[i].bv_val != NULL; i++ ) {
1995 integerNormalize( syntax, &values[i], &norm );
1997 HASH_Init( &HASHcontext );
1998 if( prefix != NULL && prefix->bv_len > 0 ) {
1999 HASH_Update( &HASHcontext,
2000 prefix->bv_val, prefix->bv_len );
2002 HASH_Update( &HASHcontext,
2003 syntax->ssyn_oid, slen );
2004 HASH_Update( &HASHcontext,
2005 mr->smr_oid, mlen );
2006 HASH_Update( &HASHcontext,
2007 norm.bv_val, norm.bv_len );
2008 HASH_Final( HASHdigest, &HASHcontext );
2010 ber_dupbv( &keys[i], &digest );
2011 ch_free( norm.bv_val );
2014 keys[i].bv_val = NULL;
2016 return LDAP_SUCCESS;
2019 /* Index generation function */
2020 static int integerFilter(
2025 struct berval *prefix,
2026 void * assertedValue,
2031 HASH_CONTEXT HASHcontext;
2032 unsigned char HASHdigest[HASH_BYTES];
2034 struct berval digest;
2035 digest.bv_val = HASHdigest;
2036 digest.bv_len = sizeof(HASHdigest);
2038 slen = syntax->ssyn_oidlen;
2039 mlen = mr->smr_oidlen;
2041 integerNormalize( syntax, assertedValue, &norm );
2043 keys = ch_malloc( sizeof( struct berval ) * 2 );
2045 HASH_Init( &HASHcontext );
2046 if( prefix != NULL && prefix->bv_len > 0 ) {
2047 HASH_Update( &HASHcontext,
2048 prefix->bv_val, prefix->bv_len );
2050 HASH_Update( &HASHcontext,
2051 syntax->ssyn_oid, slen );
2052 HASH_Update( &HASHcontext,
2053 mr->smr_oid, mlen );
2054 HASH_Update( &HASHcontext,
2055 norm.bv_val, norm.bv_len );
2056 HASH_Final( HASHdigest, &HASHcontext );
2058 ber_dupbv( &keys[0], &digest );
2059 keys[1].bv_val = NULL;
2060 ch_free( norm.bv_val );
2063 return LDAP_SUCCESS;
2068 countryStringValidate(
2070 struct berval *val )
2072 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2074 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2075 return LDAP_INVALID_SYNTAX;
2077 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2078 return LDAP_INVALID_SYNTAX;
2081 return LDAP_SUCCESS;
2085 printableStringValidate(
2087 struct berval *val )
2091 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2093 for(i=0; i < val->bv_len; i++) {
2094 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2095 return LDAP_INVALID_SYNTAX;
2099 return LDAP_SUCCESS;
2103 printablesStringValidate(
2105 struct berval *val )
2109 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2111 for(i=0,len=0; i < val->bv_len; i++) {
2112 int c = val->bv_val[i];
2116 return LDAP_INVALID_SYNTAX;
2120 } else if ( SLAP_PRINTABLE(c) ) {
2123 return LDAP_INVALID_SYNTAX;
2128 return LDAP_INVALID_SYNTAX;
2131 return LDAP_SUCCESS;
2137 struct berval *val )
2141 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2143 for(i=0; i < val->bv_len; i++) {
2144 if( !LDAP_ASCII(val->bv_val[i]) ) {
2145 return LDAP_INVALID_SYNTAX;
2149 return LDAP_SUCCESS;
2156 struct berval *normalized )
2160 assert( val->bv_len );
2164 /* Ignore initial whitespace */
2165 while ( ASCII_SPACE( *p ) ) {
2169 normalized->bv_val = ch_strdup( p );
2170 p = q = normalized->bv_val;
2173 if ( ASCII_SPACE( *p ) ) {
2176 /* Ignore the extra whitespace */
2177 while ( ASCII_SPACE( *p ) ) {
2185 assert( normalized->bv_val <= p );
2189 * If the string ended in space, backup the pointer one
2190 * position. One is enough because the above loop collapsed
2191 * all whitespace to a single space.
2194 if ( ASCII_SPACE( q[-1] ) ) {
2198 /* null terminate */
2201 normalized->bv_len = q - normalized->bv_val;
2203 if( normalized->bv_len == 0 ) {
2204 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
2205 normalized->bv_val[0] = ' ';
2206 normalized->bv_val[1] = '\0';
2207 normalized->bv_len = 1;
2210 return LDAP_SUCCESS;
2219 struct berval *value,
2220 void *assertedValue )
2222 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2225 match = strncmp( value->bv_val,
2226 ((struct berval *) assertedValue)->bv_val,
2231 return LDAP_SUCCESS;
2235 caseExactIA5SubstringsMatch(
2240 struct berval *value,
2241 void *assertedValue )
2244 SubstringsAssertion *sub = assertedValue;
2245 struct berval left = *value;
2249 /* Add up asserted input length */
2250 if( sub->sa_initial.bv_val ) {
2251 inlen += sub->sa_initial.bv_len;
2254 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2255 inlen += sub->sa_any[i].bv_len;
2258 if( sub->sa_final.bv_val ) {
2259 inlen += sub->sa_final.bv_len;
2262 if( sub->sa_initial.bv_val ) {
2263 if( inlen > left.bv_len ) {
2268 match = strncmp( sub->sa_initial.bv_val, left.bv_val,
2269 sub->sa_initial.bv_len );
2275 left.bv_val += sub->sa_initial.bv_len;
2276 left.bv_len -= sub->sa_initial.bv_len;
2277 inlen -= sub->sa_initial.bv_len;
2280 if( sub->sa_final.bv_val ) {
2281 if( inlen > left.bv_len ) {
2286 match = strncmp( sub->sa_final.bv_val,
2287 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2288 sub->sa_final.bv_len );
2294 left.bv_len -= sub->sa_final.bv_len;
2295 inlen -= sub->sa_final.bv_len;
2299 for(i=0; sub->sa_any[i].bv_val; i++) {
2304 if( inlen > left.bv_len ) {
2305 /* not enough length */
2310 if( sub->sa_any[i].bv_len == 0 ) {
2314 p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
2321 idx = p - left.bv_val;
2323 if( idx >= left.bv_len ) {
2324 /* this shouldn't happen */
2331 if( sub->sa_any[i].bv_len > left.bv_len ) {
2332 /* not enough left */
2337 match = strncmp( left.bv_val,
2338 sub->sa_any[i].bv_val,
2339 sub->sa_any[i].bv_len );
2347 left.bv_val += sub->sa_any[i].bv_len;
2348 left.bv_len -= sub->sa_any[i].bv_len;
2349 inlen -= sub->sa_any[i].bv_len;
2355 return LDAP_SUCCESS;
2358 /* Index generation function */
2359 static int caseExactIA5Indexer(
2364 struct berval *prefix,
2371 HASH_CONTEXT HASHcontext;
2372 unsigned char HASHdigest[HASH_BYTES];
2373 struct berval digest;
2374 digest.bv_val = HASHdigest;
2375 digest.bv_len = sizeof(HASHdigest);
2377 for( i=0; values[i].bv_val != NULL; i++ ) {
2378 /* empty - just count them */
2381 /* we should have at least one value at this point */
2384 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2386 slen = syntax->ssyn_oidlen;
2387 mlen = mr->smr_oidlen;
2389 for( i=0; values[i].bv_val != NULL; i++ ) {
2390 struct berval *value = &values[i];
2392 HASH_Init( &HASHcontext );
2393 if( prefix != NULL && prefix->bv_len > 0 ) {
2394 HASH_Update( &HASHcontext,
2395 prefix->bv_val, prefix->bv_len );
2397 HASH_Update( &HASHcontext,
2398 syntax->ssyn_oid, slen );
2399 HASH_Update( &HASHcontext,
2400 mr->smr_oid, mlen );
2401 HASH_Update( &HASHcontext,
2402 value->bv_val, value->bv_len );
2403 HASH_Final( HASHdigest, &HASHcontext );
2405 ber_dupbv( &keys[i], &digest );
2408 keys[i].bv_val = NULL;
2410 return LDAP_SUCCESS;
2413 /* Index generation function */
2414 static int caseExactIA5Filter(
2419 struct berval *prefix,
2420 void * assertedValue,
2425 HASH_CONTEXT HASHcontext;
2426 unsigned char HASHdigest[HASH_BYTES];
2427 struct berval *value;
2428 struct berval digest;
2429 digest.bv_val = HASHdigest;
2430 digest.bv_len = sizeof(HASHdigest);
2432 slen = syntax->ssyn_oidlen;
2433 mlen = mr->smr_oidlen;
2435 value = (struct berval *) assertedValue;
2437 keys = ch_malloc( sizeof( struct berval ) * 2 );
2439 HASH_Init( &HASHcontext );
2440 if( prefix != NULL && prefix->bv_len > 0 ) {
2441 HASH_Update( &HASHcontext,
2442 prefix->bv_val, prefix->bv_len );
2444 HASH_Update( &HASHcontext,
2445 syntax->ssyn_oid, slen );
2446 HASH_Update( &HASHcontext,
2447 mr->smr_oid, mlen );
2448 HASH_Update( &HASHcontext,
2449 value->bv_val, value->bv_len );
2450 HASH_Final( HASHdigest, &HASHcontext );
2452 ber_dupbv( &keys[0], &digest );
2453 keys[1].bv_val = NULL;
2456 return LDAP_SUCCESS;
2459 /* Substrings Index generation function */
2460 static int caseExactIA5SubstringsIndexer(
2465 struct berval *prefix,
2472 HASH_CONTEXT HASHcontext;
2473 unsigned char HASHdigest[HASH_BYTES];
2474 struct berval digest;
2475 digest.bv_val = HASHdigest;
2476 digest.bv_len = sizeof(HASHdigest);
2478 /* we should have at least one value at this point */
2479 assert( values != NULL && values[0].bv_val != NULL );
2482 for( i=0; values[i].bv_val != NULL; i++ ) {
2483 /* count number of indices to generate */
2484 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2488 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2489 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2490 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2491 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2493 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2497 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2498 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2499 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2503 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2504 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2505 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2506 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2508 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2514 /* no keys to generate */
2516 return LDAP_SUCCESS;
2519 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2521 slen = syntax->ssyn_oidlen;
2522 mlen = mr->smr_oidlen;
2525 for( i=0; values[i].bv_val != NULL; i++ ) {
2527 struct berval *value;
2530 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2532 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2533 ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2535 char pre = SLAP_INDEX_SUBSTR_PREFIX;
2536 max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2538 for( j=0; j<max; j++ ) {
2539 HASH_Init( &HASHcontext );
2540 if( prefix != NULL && prefix->bv_len > 0 ) {
2541 HASH_Update( &HASHcontext,
2542 prefix->bv_val, prefix->bv_len );
2545 HASH_Update( &HASHcontext,
2546 &pre, sizeof( pre ) );
2547 HASH_Update( &HASHcontext,
2548 syntax->ssyn_oid, slen );
2549 HASH_Update( &HASHcontext,
2550 mr->smr_oid, mlen );
2551 HASH_Update( &HASHcontext,
2553 SLAP_INDEX_SUBSTR_MAXLEN );
2554 HASH_Final( HASHdigest, &HASHcontext );
2556 ber_dupbv( &keys[nkeys++], &digest );
2560 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2561 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2563 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2566 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2567 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2568 HASH_Init( &HASHcontext );
2569 if( prefix != NULL && prefix->bv_len > 0 ) {
2570 HASH_Update( &HASHcontext,
2571 prefix->bv_val, prefix->bv_len );
2573 HASH_Update( &HASHcontext,
2574 &pre, sizeof( pre ) );
2575 HASH_Update( &HASHcontext,
2576 syntax->ssyn_oid, slen );
2577 HASH_Update( &HASHcontext,
2578 mr->smr_oid, mlen );
2579 HASH_Update( &HASHcontext,
2581 HASH_Final( HASHdigest, &HASHcontext );
2583 ber_dupbv( &keys[nkeys++], &digest );
2586 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2587 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2588 HASH_Init( &HASHcontext );
2589 if( prefix != NULL && prefix->bv_len > 0 ) {
2590 HASH_Update( &HASHcontext,
2591 prefix->bv_val, prefix->bv_len );
2593 HASH_Update( &HASHcontext,
2594 &pre, sizeof( pre ) );
2595 HASH_Update( &HASHcontext,
2596 syntax->ssyn_oid, slen );
2597 HASH_Update( &HASHcontext,
2598 mr->smr_oid, mlen );
2599 HASH_Update( &HASHcontext,
2600 &value->bv_val[value->bv_len-j], j );
2601 HASH_Final( HASHdigest, &HASHcontext );
2603 ber_dupbv( &keys[nkeys++], &digest );
2610 keys[nkeys].bv_val = NULL;
2617 return LDAP_SUCCESS;
2620 static int caseExactIA5SubstringsFilter(
2625 struct berval *prefix,
2626 void * assertedValue,
2629 SubstringsAssertion *sa = assertedValue;
2631 ber_len_t nkeys = 0;
2632 size_t slen, mlen, klen;
2634 HASH_CONTEXT HASHcontext;
2635 unsigned char HASHdigest[HASH_BYTES];
2636 struct berval *value;
2637 struct berval digest;
2639 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2640 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2645 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2647 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2648 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2649 /* don't bother accounting for stepping */
2650 nkeys += sa->sa_any[i].bv_len -
2651 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2656 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2657 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2664 return LDAP_SUCCESS;
2667 digest.bv_val = HASHdigest;
2668 digest.bv_len = sizeof(HASHdigest);
2670 slen = syntax->ssyn_oidlen;
2671 mlen = mr->smr_oidlen;
2673 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2676 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2677 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2679 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2680 value = &sa->sa_initial;
2682 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2683 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2685 HASH_Init( &HASHcontext );
2686 if( prefix != NULL && prefix->bv_len > 0 ) {
2687 HASH_Update( &HASHcontext,
2688 prefix->bv_val, prefix->bv_len );
2690 HASH_Update( &HASHcontext,
2691 &pre, sizeof( pre ) );
2692 HASH_Update( &HASHcontext,
2693 syntax->ssyn_oid, slen );
2694 HASH_Update( &HASHcontext,
2695 mr->smr_oid, mlen );
2696 HASH_Update( &HASHcontext,
2697 value->bv_val, klen );
2698 HASH_Final( HASHdigest, &HASHcontext );
2700 ber_dupbv( &keys[nkeys++], &digest );
2703 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2705 pre = SLAP_INDEX_SUBSTR_PREFIX;
2706 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2708 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2709 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2713 value = &sa->sa_any[i];
2716 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2717 j += SLAP_INDEX_SUBSTR_STEP )
2719 HASH_Init( &HASHcontext );
2720 if( prefix != NULL && prefix->bv_len > 0 ) {
2721 HASH_Update( &HASHcontext,
2722 prefix->bv_val, prefix->bv_len );
2724 HASH_Update( &HASHcontext,
2725 &pre, sizeof( pre ) );
2726 HASH_Update( &HASHcontext,
2727 syntax->ssyn_oid, slen );
2728 HASH_Update( &HASHcontext,
2729 mr->smr_oid, mlen );
2730 HASH_Update( &HASHcontext,
2731 &value->bv_val[j], klen );
2732 HASH_Final( HASHdigest, &HASHcontext );
2734 ber_dupbv( &keys[nkeys++], &digest );
2739 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2740 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2742 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2743 value = &sa->sa_final;
2745 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2746 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2748 HASH_Init( &HASHcontext );
2749 if( prefix != NULL && prefix->bv_len > 0 ) {
2750 HASH_Update( &HASHcontext,
2751 prefix->bv_val, prefix->bv_len );
2753 HASH_Update( &HASHcontext,
2754 &pre, sizeof( pre ) );
2755 HASH_Update( &HASHcontext,
2756 syntax->ssyn_oid, slen );
2757 HASH_Update( &HASHcontext,
2758 mr->smr_oid, mlen );
2759 HASH_Update( &HASHcontext,
2760 &value->bv_val[value->bv_len-klen], klen );
2761 HASH_Final( HASHdigest, &HASHcontext );
2763 ber_dupbv( &keys[nkeys++], &digest );
2767 keys[nkeys].bv_val = NULL;
2774 return LDAP_SUCCESS;
2783 struct berval *value,
2784 void *assertedValue )
2786 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2788 if( match == 0 && value->bv_len ) {
2789 match = strncasecmp( value->bv_val,
2790 ((struct berval *) assertedValue)->bv_val,
2795 return LDAP_SUCCESS;
2799 caseIgnoreIA5SubstringsMatch(
2804 struct berval *value,
2805 void *assertedValue )
2808 SubstringsAssertion *sub = assertedValue;
2809 struct berval left = *value;
2813 /* Add up asserted input length */
2814 if( sub->sa_initial.bv_val ) {
2815 inlen += sub->sa_initial.bv_len;
2818 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2819 inlen += sub->sa_any[i].bv_len;
2822 if( sub->sa_final.bv_val ) {
2823 inlen += sub->sa_final.bv_len;
2826 if( sub->sa_initial.bv_val ) {
2827 if( inlen > left.bv_len ) {
2832 match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
2833 sub->sa_initial.bv_len );
2839 left.bv_val += sub->sa_initial.bv_len;
2840 left.bv_len -= sub->sa_initial.bv_len;
2841 inlen -= sub->sa_initial.bv_len;
2844 if( sub->sa_final.bv_val ) {
2845 if( inlen > left.bv_len ) {
2850 match = strncasecmp( sub->sa_final.bv_val,
2851 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2852 sub->sa_final.bv_len );
2858 left.bv_len -= sub->sa_final.bv_len;
2859 inlen -= sub->sa_final.bv_len;
2863 for(i=0; sub->sa_any[i].bv_val; i++) {
2868 if( inlen > left.bv_len ) {
2869 /* not enough length */
2874 if( sub->sa_any[i].bv_len == 0 ) {
2878 p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
2885 assert( idx < left.bv_len );
2886 if( idx >= left.bv_len ) {
2887 /* this shouldn't happen */
2894 if( sub->sa_any[i].bv_len > left.bv_len ) {
2895 /* not enough left */
2900 match = strncasecmp( left.bv_val,
2901 sub->sa_any[i].bv_val,
2902 sub->sa_any[i].bv_len );
2911 left.bv_val += sub->sa_any[i].bv_len;
2912 left.bv_len -= sub->sa_any[i].bv_len;
2913 inlen -= sub->sa_any[i].bv_len;
2919 return LDAP_SUCCESS;
2922 /* Index generation function */
2923 static int caseIgnoreIA5Indexer(
2928 struct berval *prefix,
2933 int rc = LDAP_SUCCESS;
2936 HASH_CONTEXT HASHcontext;
2937 unsigned char HASHdigest[HASH_BYTES];
2938 struct berval digest;
2939 digest.bv_val = HASHdigest;
2940 digest.bv_len = sizeof(HASHdigest);
2942 /* we should have at least one value at this point */
2943 assert( values != NULL && values[0].bv_val != NULL );
2945 for( i=0; values[i].bv_val != NULL; i++ ) {
2946 /* just count them */
2949 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2951 slen = syntax->ssyn_oidlen;
2952 mlen = mr->smr_oidlen;
2954 for( i=0; values[i].bv_val != NULL; i++ ) {
2955 struct berval value;
2957 if( mr->smr_normalize ) {
2958 rc = (mr->smr_normalize)( use, syntax, mr, &values[i], &value );
2959 if( rc != LDAP_SUCCESS ) {
2962 } else if ( mr->smr_syntax->ssyn_normalize ) {
2963 rc = (mr->smr_syntax->ssyn_normalize)( syntax, &values[i], &value );
2964 if( rc != LDAP_SUCCESS ) {
2968 ber_dupbv( &value, &values[i] );
2971 ldap_pvt_str2lower( value.bv_val );
2973 HASH_Init( &HASHcontext );
2974 if( prefix != NULL && prefix->bv_len > 0 ) {
2975 HASH_Update( &HASHcontext,
2976 prefix->bv_val, prefix->bv_len );
2978 HASH_Update( &HASHcontext,
2979 syntax->ssyn_oid, slen );
2980 HASH_Update( &HASHcontext,
2981 mr->smr_oid, mlen );
2982 HASH_Update( &HASHcontext,
2983 value.bv_val, value.bv_len );
2984 HASH_Final( HASHdigest, &HASHcontext );
2986 free( value.bv_val );
2988 ber_dupbv( &keys[i], &digest );
2991 keys[i].bv_val = NULL;
2992 if( rc != LDAP_SUCCESS ) {
2993 ber_bvarray_free( keys );
3000 /* Index generation function */
3001 static int caseIgnoreIA5Filter(
3006 struct berval *prefix,
3007 void * assertedValue,
3012 HASH_CONTEXT HASHcontext;
3013 unsigned char HASHdigest[HASH_BYTES];
3014 struct berval value;
3015 struct berval digest;
3016 digest.bv_val = HASHdigest;
3017 digest.bv_len = sizeof(HASHdigest);
3019 slen = syntax->ssyn_oidlen;
3020 mlen = mr->smr_oidlen;
3022 ber_dupbv( &value, (struct berval *) assertedValue );
3023 ldap_pvt_str2lower( value.bv_val );
3025 keys = ch_malloc( sizeof( struct berval ) * 2 );
3027 HASH_Init( &HASHcontext );
3028 if( prefix != NULL && prefix->bv_len > 0 ) {
3029 HASH_Update( &HASHcontext,
3030 prefix->bv_val, prefix->bv_len );
3032 HASH_Update( &HASHcontext,
3033 syntax->ssyn_oid, slen );
3034 HASH_Update( &HASHcontext,
3035 mr->smr_oid, mlen );
3036 HASH_Update( &HASHcontext,
3037 value.bv_val, value.bv_len );
3038 HASH_Final( HASHdigest, &HASHcontext );
3040 ber_dupbv( &keys[0], &digest );
3041 keys[1].bv_val = NULL;
3043 free( value.bv_val );
3047 return LDAP_SUCCESS;
3050 /* Substrings Index generation function */
3051 static int caseIgnoreIA5SubstringsIndexer(
3056 struct berval *prefix,
3063 HASH_CONTEXT HASHcontext;
3064 unsigned char HASHdigest[HASH_BYTES];
3065 struct berval digest;
3066 digest.bv_val = HASHdigest;
3067 digest.bv_len = sizeof(HASHdigest);
3069 /* we should have at least one value at this point */
3070 assert( values != NULL && values[0].bv_val != NULL );
3073 for( i=0; values[i].bv_val != NULL; i++ ) {
3074 /* count number of indices to generate */
3075 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3079 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3080 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3081 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3082 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3084 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3088 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3089 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3090 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3094 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3095 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3096 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3097 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3099 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3105 /* no keys to generate */
3107 return LDAP_SUCCESS;
3110 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3112 slen = syntax->ssyn_oidlen;
3113 mlen = mr->smr_oidlen;
3116 for( i=0; values[i].bv_val != NULL; i++ ) {
3118 struct berval value;
3120 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3122 ber_dupbv( &value, &values[i] );
3123 ldap_pvt_str2lower( value.bv_val );
3125 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3126 ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3128 char pre = SLAP_INDEX_SUBSTR_PREFIX;
3129 max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3131 for( j=0; j<max; j++ ) {
3132 HASH_Init( &HASHcontext );
3133 if( prefix != NULL && prefix->bv_len > 0 ) {
3134 HASH_Update( &HASHcontext,
3135 prefix->bv_val, prefix->bv_len );
3138 HASH_Update( &HASHcontext,
3139 &pre, sizeof( pre ) );
3140 HASH_Update( &HASHcontext,
3141 syntax->ssyn_oid, slen );
3142 HASH_Update( &HASHcontext,
3143 mr->smr_oid, mlen );
3144 HASH_Update( &HASHcontext,
3146 SLAP_INDEX_SUBSTR_MAXLEN );
3147 HASH_Final( HASHdigest, &HASHcontext );
3149 ber_dupbv( &keys[nkeys++], &digest );
3153 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3154 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3156 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3159 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3160 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3161 HASH_Init( &HASHcontext );
3162 if( prefix != NULL && prefix->bv_len > 0 ) {
3163 HASH_Update( &HASHcontext,
3164 prefix->bv_val, prefix->bv_len );
3166 HASH_Update( &HASHcontext,
3167 &pre, sizeof( pre ) );
3168 HASH_Update( &HASHcontext,
3169 syntax->ssyn_oid, slen );
3170 HASH_Update( &HASHcontext,
3171 mr->smr_oid, mlen );
3172 HASH_Update( &HASHcontext,
3174 HASH_Final( HASHdigest, &HASHcontext );
3176 ber_dupbv( &keys[nkeys++], &digest );
3179 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3180 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3181 HASH_Init( &HASHcontext );
3182 if( prefix != NULL && prefix->bv_len > 0 ) {
3183 HASH_Update( &HASHcontext,
3184 prefix->bv_val, prefix->bv_len );
3186 HASH_Update( &HASHcontext,
3187 &pre, sizeof( pre ) );
3188 HASH_Update( &HASHcontext,
3189 syntax->ssyn_oid, slen );
3190 HASH_Update( &HASHcontext,
3191 mr->smr_oid, mlen );
3192 HASH_Update( &HASHcontext,
3193 &value.bv_val[value.bv_len-j], j );
3194 HASH_Final( HASHdigest, &HASHcontext );
3196 ber_dupbv( &keys[nkeys++], &digest );
3201 free( value.bv_val );
3205 keys[nkeys].bv_val = NULL;
3212 return LDAP_SUCCESS;
3215 static int caseIgnoreIA5SubstringsFilter(
3220 struct berval *prefix,
3221 void * assertedValue,
3224 SubstringsAssertion *sa = assertedValue;
3226 ber_len_t nkeys = 0;
3227 size_t slen, mlen, klen;
3229 HASH_CONTEXT HASHcontext;
3230 unsigned char HASHdigest[HASH_BYTES];
3231 struct berval value;
3232 struct berval digest;
3234 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3235 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3240 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3242 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3243 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3244 /* don't bother accounting for stepping */
3245 nkeys += sa->sa_any[i].bv_len -
3246 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3251 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3252 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3259 return LDAP_SUCCESS;
3262 digest.bv_val = HASHdigest;
3263 digest.bv_len = sizeof(HASHdigest);
3265 slen = syntax->ssyn_oidlen;
3266 mlen = mr->smr_oidlen;
3268 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3271 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3272 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3274 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3275 ber_dupbv( &value, &sa->sa_initial );
3276 ldap_pvt_str2lower( value.bv_val );
3278 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3279 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3281 HASH_Init( &HASHcontext );
3282 if( prefix != NULL && prefix->bv_len > 0 ) {
3283 HASH_Update( &HASHcontext,
3284 prefix->bv_val, prefix->bv_len );
3286 HASH_Update( &HASHcontext,
3287 &pre, sizeof( pre ) );
3288 HASH_Update( &HASHcontext,
3289 syntax->ssyn_oid, slen );
3290 HASH_Update( &HASHcontext,
3291 mr->smr_oid, mlen );
3292 HASH_Update( &HASHcontext,
3293 value.bv_val, klen );
3294 HASH_Final( HASHdigest, &HASHcontext );
3296 free( value.bv_val );
3297 ber_dupbv( &keys[nkeys++], &digest );
3300 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3302 pre = SLAP_INDEX_SUBSTR_PREFIX;
3303 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3305 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3306 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3310 ber_dupbv( &value, &sa->sa_any[i] );
3311 ldap_pvt_str2lower( value.bv_val );
3314 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3315 j += SLAP_INDEX_SUBSTR_STEP )
3317 HASH_Init( &HASHcontext );
3318 if( prefix != NULL && prefix->bv_len > 0 ) {
3319 HASH_Update( &HASHcontext,
3320 prefix->bv_val, prefix->bv_len );
3322 HASH_Update( &HASHcontext,
3323 &pre, sizeof( pre ) );
3324 HASH_Update( &HASHcontext,
3325 syntax->ssyn_oid, slen );
3326 HASH_Update( &HASHcontext,
3327 mr->smr_oid, mlen );
3328 HASH_Update( &HASHcontext,
3329 &value.bv_val[j], klen );
3330 HASH_Final( HASHdigest, &HASHcontext );
3332 ber_dupbv( &keys[nkeys++], &digest );
3335 free( value.bv_val );
3339 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3340 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3342 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3343 ber_dupbv( &value, &sa->sa_final );
3344 ldap_pvt_str2lower( value.bv_val );
3346 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3347 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3349 HASH_Init( &HASHcontext );
3350 if( prefix != NULL && prefix->bv_len > 0 ) {
3351 HASH_Update( &HASHcontext,
3352 prefix->bv_val, prefix->bv_len );
3354 HASH_Update( &HASHcontext,
3355 &pre, sizeof( pre ) );
3356 HASH_Update( &HASHcontext,
3357 syntax->ssyn_oid, slen );
3358 HASH_Update( &HASHcontext,
3359 mr->smr_oid, mlen );
3360 HASH_Update( &HASHcontext,
3361 &value.bv_val[value.bv_len-klen], klen );
3362 HASH_Final( HASHdigest, &HASHcontext );
3364 free( value.bv_val );
3365 ber_dupbv( &keys[nkeys++], &digest );
3369 keys[nkeys].bv_val = NULL;
3376 return LDAP_SUCCESS;
3380 numericStringValidate(
3386 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
3388 for(i=0; i < in->bv_len; i++) {
3389 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3390 return LDAP_INVALID_SYNTAX;
3394 return LDAP_SUCCESS;
3398 numericStringNormalize(
3401 struct berval *normalized )
3403 /* removal all spaces */
3406 assert( val->bv_len );
3408 normalized->bv_val = ch_malloc( val->bv_len + 1 );
3411 q = normalized->bv_val;
3414 if ( ASCII_SPACE( *p ) ) {
3415 /* Ignore whitespace */
3422 /* we should have copied no more then is in val */
3423 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3425 /* null terminate */
3428 normalized->bv_len = q - normalized->bv_val;
3430 if( normalized->bv_len == 0 ) {
3431 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
3432 normalized->bv_val[0] = ' ';
3433 normalized->bv_val[1] = '\0';
3434 normalized->bv_len = 1;
3437 return LDAP_SUCCESS;
3441 objectIdentifierFirstComponentMatch(
3446 struct berval *value,
3447 void *assertedValue )
3449 int rc = LDAP_SUCCESS;
3451 struct berval *asserted = (struct berval *) assertedValue;
3455 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3456 return LDAP_INVALID_SYNTAX;
3459 /* trim leading white space */
3460 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3464 /* grab next word */
3465 oid.bv_val = &value->bv_val[i];
3466 oid.bv_len = value->bv_len - i;
3467 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3472 /* insert attributeTypes, objectclass check here */
3473 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3474 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3477 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3478 MatchingRule *asserted_mr = mr_bvfind( asserted );
3479 MatchingRule *stored_mr = mr_bvfind( &oid );
3481 if( asserted_mr == NULL ) {
3482 rc = SLAPD_COMPARE_UNDEFINED;
3484 match = asserted_mr != stored_mr;
3487 } else if ( !strcmp( syntax->ssyn_oid,
3488 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3490 AttributeType *asserted_at = at_bvfind( asserted );
3491 AttributeType *stored_at = at_bvfind( &oid );
3493 if( asserted_at == NULL ) {
3494 rc = SLAPD_COMPARE_UNDEFINED;
3496 match = asserted_at != stored_at;
3499 } else if ( !strcmp( syntax->ssyn_oid,
3500 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3502 ObjectClass *asserted_oc = oc_bvfind( asserted );
3503 ObjectClass *stored_oc = oc_bvfind( &oid );
3505 if( asserted_oc == NULL ) {
3506 rc = SLAPD_COMPARE_UNDEFINED;
3508 match = asserted_oc != stored_oc;
3514 LDAP_LOG( CONFIG, ENTRY,
3515 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
3516 match, value->bv_val, asserted->bv_val );
3518 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3519 "%d\n\t\"%s\"\n\t\"%s\"\n",
3520 match, value->bv_val, asserted->bv_val );
3524 if( rc == LDAP_SUCCESS ) *matchp = match;
3534 struct berval *value,
3535 void *assertedValue )
3537 long lValue, lAssertedValue;
3539 /* safe to assume integers are NUL terminated? */
3540 lValue = strtoul(value->bv_val, NULL, 10);
3541 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3542 return LDAP_CONSTRAINT_VIOLATION;
3544 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3545 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3546 return LDAP_CONSTRAINT_VIOLATION;
3548 *matchp = (lValue & lAssertedValue) ? 0 : 1;
3549 return LDAP_SUCCESS;
3558 struct berval *value,
3559 void *assertedValue )
3561 long lValue, lAssertedValue;
3563 /* safe to assume integers are NUL terminated? */
3564 lValue = strtoul(value->bv_val, NULL, 10);
3565 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3566 return LDAP_CONSTRAINT_VIOLATION;
3568 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3569 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3570 return LDAP_CONSTRAINT_VIOLATION;
3572 *matchp = (lValue | lAssertedValue) ? 0 : -1;
3573 return LDAP_SUCCESS;
3577 #include <openssl/x509.h>
3578 #include <openssl/err.h>
3581 * Next function returns a string representation of a ASN1_INTEGER.
3582 * It works for unlimited lengths.
3585 static struct berval *
3586 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3590 static char digit[] = "0123456789";
3592 /* We work backwards, make it fill from the end of buf */
3593 p = buf + sizeof(buf) - 1;
3596 if ( a == NULL || a->length == 0 ) {
3604 /* We want to preserve the original */
3605 copy = ch_malloc(n*sizeof(unsigned int));
3606 for (i = 0; i<n; i++) {
3607 copy[i] = a->data[i];
3611 * base indicates the index of the most significant
3612 * byte that might be nonzero. When it goes off the
3613 * end, we now there is nothing left to do.
3619 for (i = base; i<n; i++ ) {
3620 copy[i] += carry*256;
3621 carry = copy[i] % 10;
3626 * Way too large, we need to leave
3627 * room for sign if negative
3632 *--p = digit[carry];
3633 if (copy[base] == 0)
3639 if ( a->type == V_ASN1_NEG_INTEGER ) {
3643 return ber_str2bv( p, 0, 1, bv );
3647 * Given a certificate in DER format, extract the corresponding
3648 * assertion value for certificateExactMatch
3651 certificateExactConvert(
3653 struct berval * out )
3656 unsigned char *p = in->bv_val;
3657 struct berval serial;
3658 struct berval issuer_dn;
3660 xcert = d2i_X509(NULL, &p, in->bv_len);
3663 LDAP_LOG( CONFIG, ENTRY,
3664 "certificateExactConvert: error parsing cert: %s\n",
3665 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3667 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3668 "error parsing cert: %s\n",
3669 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3671 return LDAP_INVALID_SYNTAX;
3674 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3676 return LDAP_INVALID_SYNTAX;
3678 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn ) != LDAP_SUCCESS ) {
3680 ber_memfree(serial.bv_val);
3681 return LDAP_INVALID_SYNTAX;
3686 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3687 out->bv_val = ch_malloc(out->bv_len);
3689 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3691 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3693 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3694 p += issuer_dn.bv_len;
3698 LDAP_LOG( CONFIG, ARGS,
3699 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
3701 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3703 out->bv_val, NULL, NULL );
3706 ber_memfree(serial.bv_val);
3707 ber_memfree(issuer_dn.bv_val);
3709 return LDAP_SUCCESS;
3713 serial_and_issuer_parse(
3714 struct berval *assertion,
3715 struct berval *serial,
3716 struct berval *issuer_dn
3724 begin = assertion->bv_val;
3725 end = assertion->bv_val+assertion->bv_len-1;
3726 for (p=begin; p<=end && *p != '$'; p++)
3729 return LDAP_INVALID_SYNTAX;
3731 /* p now points at the $ sign, now use begin and end to delimit the
3733 while (ASCII_SPACE(*begin))
3736 while (ASCII_SPACE(*end))
3739 bv.bv_len = end-begin+1;
3741 ber_dupbv(serial, &bv);
3743 /* now extract the issuer, remember p was at the dollar sign */
3746 end = assertion->bv_val+assertion->bv_len-1;
3747 while (ASCII_SPACE(*begin))
3749 /* should we trim spaces at the end too? is it safe always? */
3751 bv.bv_len = end-begin+1;
3753 dnNormalize2( NULL, &bv, issuer_dn );
3756 return LDAP_SUCCESS;
3760 certificateExactMatch(
3765 struct berval *value,
3766 void *assertedValue )
3769 unsigned char *p = value->bv_val;
3770 struct berval serial;
3771 struct berval issuer_dn;
3772 struct berval asserted_serial;
3773 struct berval asserted_issuer_dn;
3776 xcert = d2i_X509(NULL, &p, value->bv_len);
3779 LDAP_LOG( CONFIG, ENTRY,
3780 "certificateExactMatch: error parsing cert: %s\n",
3781 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3783 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3784 "error parsing cert: %s\n",
3785 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3787 return LDAP_INVALID_SYNTAX;
3790 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3791 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
3795 serial_and_issuer_parse(assertedValue,
3797 &asserted_issuer_dn);
3802 slap_schema.si_syn_integer,
3803 slap_schema.si_mr_integerMatch,
3806 if ( ret == LDAP_SUCCESS ) {
3807 if ( *matchp == 0 ) {
3808 /* We need to normalize everything for dnMatch */
3812 slap_schema.si_syn_distinguishedName,
3813 slap_schema.si_mr_distinguishedNameMatch,
3815 &asserted_issuer_dn);
3820 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
3821 "%d\n\t\"%s $ %s\"\n",
3822 *matchp, serial.bv_val, issuer_dn.bv_val );
3823 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
3824 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3827 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3828 "%d\n\t\"%s $ %s\"\n",
3829 *matchp, serial.bv_val, issuer_dn.bv_val );
3830 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3831 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3835 ber_memfree(serial.bv_val);
3836 ber_memfree(issuer_dn.bv_val);
3837 ber_memfree(asserted_serial.bv_val);
3838 ber_memfree(asserted_issuer_dn.bv_val);
3844 * Index generation function
3845 * We just index the serials, in most scenarios the issuer DN is one of
3846 * a very small set of values.
3848 static int certificateExactIndexer(
3853 struct berval *prefix,
3861 struct berval serial;
3863 /* we should have at least one value at this point */
3864 assert( values != NULL && values[0].bv_val != NULL );
3866 for( i=0; values[i].bv_val != NULL; i++ ) {
3867 /* empty -- just count them */
3870 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3872 for( i=0; values[i].bv_val != NULL; i++ ) {
3873 p = values[i].bv_val;
3874 xcert = d2i_X509(NULL, &p, values[i].bv_len);
3877 LDAP_LOG( CONFIG, ENTRY,
3878 "certificateExactIndexer: error parsing cert: %s\n",
3879 ERR_error_string(ERR_get_error(),NULL), 0, 0);
3881 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3882 "error parsing cert: %s\n",
3883 ERR_error_string(ERR_get_error(),NULL),
3886 /* Do we leak keys on error? */
3887 return LDAP_INVALID_SYNTAX;
3890 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3892 integerNormalize( slap_schema.si_syn_integer,
3895 ber_memfree(serial.bv_val);
3897 LDAP_LOG( CONFIG, ENTRY,
3898 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
3900 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3907 keys[i].bv_val = NULL;
3909 return LDAP_SUCCESS;
3912 /* Index generation function */
3913 /* We think this is always called with a value in matching rule syntax */
3914 static int certificateExactFilter(
3919 struct berval *prefix,
3920 void * assertedValue,
3924 struct berval asserted_serial;
3926 serial_and_issuer_parse(assertedValue,
3930 keys = ch_malloc( sizeof( struct berval ) * 2 );
3931 integerNormalize( syntax, &asserted_serial, &keys[0] );
3932 keys[1].bv_val = NULL;
3935 ber_memfree(asserted_serial.bv_val);
3936 return LDAP_SUCCESS;
3941 check_time_syntax (struct berval *val,
3945 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3946 static int mdays[2][12] = {
3947 /* non-leap years */
3948 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3950 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3953 int part, c, tzoffset, leapyear = 0 ;
3955 if( val->bv_len == 0 ) {
3956 return LDAP_INVALID_SYNTAX;
3959 p = (char *)val->bv_val;
3960 e = p + val->bv_len;
3962 /* Ignore initial whitespace */
3963 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3967 if (e - p < 13 - (2 * start)) {
3968 return LDAP_INVALID_SYNTAX;
3971 for (part = 0; part < 9; part++) {
3975 for (part = start; part < 7; part++) {
3977 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3984 return LDAP_INVALID_SYNTAX;
3986 if (c < 0 || c > 9) {
3987 return LDAP_INVALID_SYNTAX;
3993 return LDAP_INVALID_SYNTAX;
3995 if (c < 0 || c > 9) {
3996 return LDAP_INVALID_SYNTAX;
4001 if (part == 2 || part == 3) {
4004 if (parts[part] < 0) {
4005 return LDAP_INVALID_SYNTAX;
4007 if (parts[part] > ceiling[part]) {
4008 return LDAP_INVALID_SYNTAX;
4012 /* leapyear check for the Gregorian calendar (year>1581) */
4013 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
4014 ((parts[0] % 4 == 0) && (parts[1] == 0)))
4019 if (parts[3] > mdays[leapyear][parts[2]]) {
4020 return LDAP_INVALID_SYNTAX;
4025 tzoffset = 0; /* UTC */
4026 } else if (c != '+' && c != '-') {
4027 return LDAP_INVALID_SYNTAX;
4031 } else /* c == '+' */ {
4036 return LDAP_INVALID_SYNTAX;
4039 for (part = 7; part < 9; part++) {
4041 if (c < 0 || c > 9) {
4042 return LDAP_INVALID_SYNTAX;
4047 if (c < 0 || c > 9) {
4048 return LDAP_INVALID_SYNTAX;
4052 if (parts[part] < 0 || parts[part] > ceiling[part]) {
4053 return LDAP_INVALID_SYNTAX;
4058 /* Ignore trailing whitespace */
4059 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4063 return LDAP_INVALID_SYNTAX;
4066 switch ( tzoffset ) {
4067 case -1: /* negativ offset to UTC, ie west of Greenwich */
4068 parts[4] += parts[7];
4069 parts[5] += parts[8];
4070 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4074 c = mdays[leapyear][parts[2]];
4076 if (parts[part] > c) {
4077 parts[part] -= c + 1;
4082 case 1: /* positive offset to UTC, ie east of Greenwich */
4083 parts[4] -= parts[7];
4084 parts[5] -= parts[8];
4085 for (part = 6; --part > 0; ) {
4089 /* first arg to % needs to be non negativ */
4090 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4092 if (parts[part] < 0) {
4093 parts[part] += c + 1;
4098 case 0: /* already UTC */
4102 return LDAP_SUCCESS;
4105 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4110 struct berval *normalized )
4114 rc = check_time_syntax(val, 1, parts);
4115 if (rc != LDAP_SUCCESS) {
4119 normalized->bv_val = ch_malloc( 14 );
4120 if ( normalized->bv_val == NULL ) {
4121 return LBER_ERROR_MEMORY;
4124 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4125 parts[1], parts[2] + 1, parts[3] + 1,
4126 parts[4], parts[5], parts[6] );
4127 normalized->bv_len = 13;
4129 return LDAP_SUCCESS;
4133 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4141 return check_time_syntax(in, 1, parts);
4146 generalizedTimeValidate(
4152 return check_time_syntax(in, 0, parts);
4156 generalizedTimeNormalize(
4159 struct berval *normalized )
4163 rc = check_time_syntax(val, 0, parts);
4164 if (rc != LDAP_SUCCESS) {
4168 normalized->bv_val = ch_malloc( 16 );
4169 if ( normalized->bv_val == NULL ) {
4170 return LBER_ERROR_MEMORY;
4173 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4174 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4175 parts[4], parts[5], parts[6] );
4176 normalized->bv_len = 15;
4178 return LDAP_SUCCESS;
4182 nisNetgroupTripleValidate(
4184 struct berval *val )
4189 if ( val->bv_len == 0 ) {
4190 return LDAP_INVALID_SYNTAX;
4193 p = (char *)val->bv_val;
4194 e = p + val->bv_len;
4196 if ( *p != '(' /*')'*/ ) {
4197 return LDAP_INVALID_SYNTAX;
4200 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4204 return LDAP_INVALID_SYNTAX;
4207 } else if ( !AD_CHAR( *p ) ) {
4208 return LDAP_INVALID_SYNTAX;
4212 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4213 return LDAP_INVALID_SYNTAX;
4219 return LDAP_INVALID_SYNTAX;
4222 return LDAP_SUCCESS;
4226 bootParameterValidate(
4228 struct berval *val )
4232 if ( val->bv_len == 0 ) {
4233 return LDAP_INVALID_SYNTAX;
4236 p = (char *)val->bv_val;
4237 e = p + val->bv_len;
4240 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4241 if ( !AD_CHAR( *p ) ) {
4242 return LDAP_INVALID_SYNTAX;
4247 return LDAP_INVALID_SYNTAX;
4251 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4252 if ( !AD_CHAR( *p ) ) {
4253 return LDAP_INVALID_SYNTAX;
4258 return LDAP_INVALID_SYNTAX;
4262 for ( p++; p < e; p++ ) {
4263 if ( !SLAP_PRINTABLE( *p ) ) {
4264 return LDAP_INVALID_SYNTAX;
4268 return LDAP_SUCCESS;
4271 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4272 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4274 static slap_syntax_defs_rec syntax_defs[] = {
4275 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4276 X_BINARY X_NOT_H_R ")",
4277 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4278 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4279 0, NULL, NULL, NULL},
4280 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4281 0, NULL, NULL, NULL},
4282 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4284 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4285 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4287 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4288 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4289 0, bitStringValidate, bitStringNormalize, NULL },
4290 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4291 0, booleanValidate, NULL, NULL},
4292 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4293 X_BINARY X_NOT_H_R ")",
4294 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4295 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4296 X_BINARY X_NOT_H_R ")",
4297 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4298 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4299 X_BINARY X_NOT_H_R ")",
4300 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4301 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4302 0, countryStringValidate, IA5StringNormalize, NULL},
4303 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4304 0, dnValidate, dnNormalize2, dnPretty2},
4305 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4306 0, NULL, NULL, NULL},
4307 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4308 0, NULL, NULL, NULL},
4309 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4310 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4311 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4312 0, NULL, NULL, NULL},
4313 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4314 0, NULL, NULL, NULL},
4315 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4316 0, NULL, NULL, NULL},
4317 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4318 0, NULL, NULL, NULL},
4319 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4320 0, NULL, NULL, NULL},
4321 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4322 0, printablesStringValidate, telephoneNumberNormalize, NULL},
4323 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4324 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4325 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4326 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4327 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4328 0, NULL, NULL, NULL},
4329 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4330 0, IA5StringValidate, IA5StringNormalize, NULL},
4331 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4332 0, integerValidate, integerNormalize, NULL},
4333 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4334 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4335 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4336 0, NULL, NULL, NULL},
4337 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4338 0, NULL, NULL, NULL},
4339 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4340 0, NULL, NULL, NULL},
4341 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4342 0, NULL, NULL, NULL},
4343 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4344 0, NULL, NULL, NULL},
4345 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4346 0, nameUIDValidate, nameUIDNormalize, NULL},
4347 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4348 0, NULL, NULL, NULL},
4349 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4350 0, numericStringValidate, numericStringNormalize, NULL},
4351 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4352 0, NULL, NULL, NULL},
4353 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4354 0, oidValidate, NULL, NULL},
4355 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4356 0, IA5StringValidate, IA5StringNormalize, NULL},
4357 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4358 0, blobValidate, NULL, NULL},
4359 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4360 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4361 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4362 0, NULL, NULL, NULL},
4363 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4364 0, NULL, NULL, NULL},
4365 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4366 0, printableStringValidate, IA5StringNormalize, NULL},
4367 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4368 X_BINARY X_NOT_H_R ")",
4369 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4370 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4371 X_BINARY X_NOT_H_R ")",
4372 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4373 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4374 0, printableStringValidate, telephoneNumberNormalize, NULL},
4375 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4376 0, NULL, NULL, NULL},
4377 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4378 0, printablesStringValidate, IA5StringNormalize, NULL},
4379 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4380 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4381 0, utcTimeValidate, utcTimeNormalize, NULL},
4383 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4384 0, NULL, NULL, NULL},
4385 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4386 0, NULL, NULL, NULL},
4387 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4388 0, NULL, NULL, NULL},
4389 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4390 0, NULL, NULL, NULL},
4391 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4392 0, NULL, NULL, NULL},
4394 /* RFC 2307 NIS Syntaxes */
4395 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4396 0, nisNetgroupTripleValidate, NULL, NULL},
4397 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4398 0, bootParameterValidate, NULL, NULL},
4402 /* These OIDs are not published yet, but will be in the next
4403 * I-D for PKIX LDAPv3 schema as have been advanced by David
4404 * Chadwick in private mail.
4406 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4407 0, NULL, NULL, NULL},
4410 /* OpenLDAP Experimental Syntaxes */
4411 #ifdef SLAPD_ACI_ENABLED
4412 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4414 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4418 #ifdef SLAPD_AUTHPASSWD
4419 /* needs updating */
4420 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4421 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4424 /* OpenLDAP Void Syntax */
4425 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4426 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4427 {NULL, 0, NULL, NULL, NULL}
4431 char *certificateExactMatchSyntaxes[] = {
4432 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4436 char *directoryStringSyntaxes[] = {
4437 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4440 char *integerFirstComponentMatchSyntaxes[] = {
4441 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4442 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
4445 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4446 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4447 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4448 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
4449 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4450 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4451 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4452 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4453 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4458 * Other matching rules in X.520 that we do not use (yet):
4460 * 2.5.13.9 numericStringOrderingMatch
4461 * 2.5.13.19 octetStringSubstringsMatch
4462 * 2.5.13.25 uTCTimeMatch
4463 * 2.5.13.26 uTCTimeOrderingMatch
4464 * 2.5.13.31 directoryStringFirstComponentMatch
4465 * 2.5.13.32 wordMatch
4466 * 2.5.13.33 keywordMatch
4467 * 2.5.13.35 certificateMatch
4468 * 2.5.13.36 certificatePairExactMatch
4469 * 2.5.13.37 certificatePairMatch
4470 * 2.5.13.38 certificateListExactMatch
4471 * 2.5.13.39 certificateListMatch
4472 * 2.5.13.40 algorithmIdentifierMatch
4473 * 2.5.13.41 storedPrefixMatch
4474 * 2.5.13.42 attributeCertificateMatch
4475 * 2.5.13.43 readerAndKeyIDMatch
4476 * 2.5.13.44 attributeIntegrityMatch
4478 static slap_mrule_defs_rec mrule_defs[] = {
4480 * EQUALITY matching rules must be listed after associated APPROX
4481 * matching rules. So, we list all APPROX matching rules first.
4483 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4484 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4485 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4487 directoryStringApproxMatch,
4488 directoryStringApproxIndexer,
4489 directoryStringApproxFilter,
4492 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4493 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4494 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4496 IA5StringApproxMatch,
4497 IA5StringApproxIndexer,
4498 IA5StringApproxFilter,
4502 * Other matching rules
4505 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4506 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4507 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4509 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4512 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4513 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4514 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4516 dnMatch, dnIndexer, dnFilter,
4519 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4520 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4521 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4522 directoryStringSyntaxes,
4524 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4525 directoryStringApproxMatchOID },
4527 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4528 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4529 SLAP_MR_ORDERING, directoryStringSyntaxes,
4531 caseIgnoreOrderingMatch, NULL, NULL,
4534 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4535 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4536 SLAP_MR_SUBSTR, NULL,
4538 caseExactIgnoreSubstringsMatch,
4539 caseExactIgnoreSubstringsIndexer,
4540 caseExactIgnoreSubstringsFilter,
4543 {"( 2.5.13.5 NAME 'caseExactMatch' "
4544 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4545 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4547 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4548 directoryStringApproxMatchOID },
4550 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4551 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4552 SLAP_MR_ORDERING, directoryStringSyntaxes,
4554 caseExactOrderingMatch, NULL, NULL,
4557 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4558 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4559 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4561 caseExactIgnoreSubstringsMatch,
4562 caseExactIgnoreSubstringsIndexer,
4563 caseExactIgnoreSubstringsFilter,
4566 {"( 2.5.13.8 NAME 'numericStringMatch' "
4567 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4568 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4571 caseIgnoreIA5Indexer,
4572 caseIgnoreIA5Filter,
4575 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4576 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4577 SLAP_MR_SUBSTR, NULL,
4579 caseIgnoreIA5SubstringsMatch,
4580 caseIgnoreIA5SubstringsIndexer,
4581 caseIgnoreIA5SubstringsFilter,
4584 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4585 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4586 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4588 caseIgnoreListMatch, NULL, NULL,
4591 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4592 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4593 SLAP_MR_SUBSTR, NULL,
4595 caseIgnoreListSubstringsMatch, NULL, NULL,
4598 {"( 2.5.13.13 NAME 'booleanMatch' "
4599 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4600 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4602 booleanMatch, NULL, NULL,
4605 {"( 2.5.13.14 NAME 'integerMatch' "
4606 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4607 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4609 integerMatch, integerIndexer, integerFilter,
4612 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4613 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4614 SLAP_MR_ORDERING, NULL,
4616 integerOrderingMatch, NULL, NULL,
4619 {"( 2.5.13.16 NAME 'bitStringMatch' "
4620 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4621 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4623 bitStringMatch, bitStringIndexer, bitStringFilter,
4626 {"( 2.5.13.17 NAME 'octetStringMatch' "
4627 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4628 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4630 octetStringMatch, octetStringIndexer, octetStringFilter,
4633 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4634 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4635 SLAP_MR_ORDERING, NULL,
4637 octetStringOrderingMatch, NULL, NULL,
4640 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4641 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4642 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4644 telephoneNumberMatch,
4645 telephoneNumberIndexer,
4646 telephoneNumberFilter,
4649 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4650 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4651 SLAP_MR_SUBSTR, NULL,
4653 telephoneNumberSubstringsMatch,
4654 telephoneNumberSubstringsIndexer,
4655 telephoneNumberSubstringsFilter,
4658 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4659 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4660 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4665 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4666 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4667 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4669 uniqueMemberMatch, NULL, NULL,
4672 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4673 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4674 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4676 protocolInformationMatch, NULL, NULL,
4679 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4680 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4681 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4683 generalizedTimeMatch, NULL, NULL,
4686 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4687 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4688 SLAP_MR_ORDERING, NULL,
4690 generalizedTimeOrderingMatch, NULL, NULL,
4693 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4695 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
4697 integerFirstComponentMatch, NULL, NULL,
4700 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4702 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4703 objectIdentifierFirstComponentMatchSyntaxes,
4705 objectIdentifierFirstComponentMatch, NULL, NULL,
4709 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4710 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4711 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4712 certificateExactConvert, NULL,
4713 certificateExactMatch,
4714 certificateExactIndexer, certificateExactFilter,
4718 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4719 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4720 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4722 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4723 IA5StringApproxMatchOID },
4725 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4726 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4727 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4729 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4730 IA5StringApproxMatchOID },
4732 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4733 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4734 SLAP_MR_SUBSTR, NULL,
4736 caseIgnoreIA5SubstringsMatch,
4737 caseIgnoreIA5SubstringsIndexer,
4738 caseIgnoreIA5SubstringsFilter,
4741 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4742 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4743 SLAP_MR_SUBSTR, NULL,
4745 caseExactIA5SubstringsMatch,
4746 caseExactIA5SubstringsIndexer,
4747 caseExactIA5SubstringsFilter,
4750 #ifdef SLAPD_AUTHPASSWD
4751 /* needs updating */
4752 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4753 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4754 SLAP_MR_EQUALITY, NULL,
4756 authPasswordMatch, NULL, NULL,
4760 #ifdef SLAPD_ACI_ENABLED
4761 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4762 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4763 SLAP_MR_EQUALITY, NULL,
4765 OpenLDAPaciMatch, NULL, NULL,
4769 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4770 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4773 integerBitAndMatch, NULL, NULL,
4776 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4777 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4780 integerBitOrMatch, NULL, NULL,
4783 {NULL, SLAP_MR_NONE, NULL,
4784 NULL, NULL, NULL, NULL, NULL,
4789 slap_schema_init( void )
4794 /* we should only be called once (from main) */
4795 assert( schema_init_done == 0 );
4797 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4798 res = register_syntax( &syntax_defs[i] );
4801 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4802 syntax_defs[i].sd_desc );
4807 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4808 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4809 mrule_defs[i].mrd_compat_syntaxes == NULL )
4812 "slap_schema_init: Ingoring unusable matching rule %s\n",
4813 mrule_defs[i].mrd_desc );
4817 res = register_matching_rule( &mrule_defs[i] );
4821 "slap_schema_init: Error registering matching rule %s\n",
4822 mrule_defs[i].mrd_desc );
4827 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4828 *mr_ptr[i].mr = mr_find( mr_ptr[i].oid );
4830 res = slap_schema_load();
4831 schema_init_done = 1;
4836 schema_destroy( void )
4842 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4843 *mr_ptr[i].mr = NULL;