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
63 /* unimplemented matching routines */
64 #define caseIgnoreListMatch NULL
65 #define caseIgnoreListSubstringsMatch NULL
66 #define protocolInformationMatch NULL
68 #ifdef SLAPD_ACI_ENABLED
69 #define OpenLDAPaciMatch NULL
71 #ifdef SLAPD_AUTHPASSWD
72 #define authPasswordMatch NULL
75 /* recycled indexing/filtering routines */
76 #define dnIndexer caseExactIgnoreIndexer
77 #define dnFilter caseExactIgnoreFilter
78 #define bitStringFilter octetStringFilter
79 #define bitStringIndexer octetStringIndexer
81 #define telephoneNumberIndexer caseIgnoreIA5Indexer
82 #define telephoneNumberFilter caseIgnoreIA5Filter
83 #define telephoneNumberSubstringsIndexer caseIgnoreIA5SubstringsIndexer
84 #define telephoneNumberSubstringsFilter caseIgnoreIA5SubstringsFilter
86 static MatchingRule *caseExactMatchingRule;
87 static MatchingRule *caseExactSubstringsMatchingRule;
88 static MatchingRule *integerFirstComponentMatchingRule;
90 static const struct MatchingRulePtr {
94 /* must match OIDs below */
95 { "2.5.13.5", &caseExactMatchingRule },
96 { "2.5.13.7", &caseExactSubstringsMatchingRule },
97 { "2.5.13.29", &integerFirstComponentMatchingRule }
101 static char *bvcasechr( struct berval *bv, unsigned char c, ber_len_t *len )
104 char lower = TOLOWER( c );
105 char upper = TOUPPER( c );
107 if( c == 0 ) return NULL;
109 for( i=0; i < bv->bv_len; i++ ) {
110 if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
112 return &bv->bv_val[i];
125 struct berval *value,
126 void *assertedValue )
128 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
131 match = memcmp( value->bv_val,
132 ((struct berval *) assertedValue)->bv_val,
140 /* Index generation function */
141 int octetStringIndexer(
146 struct berval *prefix,
153 HASH_CONTEXT HASHcontext;
154 unsigned char HASHdigest[HASH_BYTES];
155 struct berval digest;
156 digest.bv_val = HASHdigest;
157 digest.bv_len = sizeof(HASHdigest);
159 for( i=0; values[i].bv_val != NULL; i++ ) {
160 /* just count them */
163 /* we should have at least one value at this point */
166 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
168 slen = syntax->ssyn_oidlen;
169 mlen = mr->smr_oidlen;
171 for( i=0; values[i].bv_val != NULL; i++ ) {
172 HASH_Init( &HASHcontext );
173 if( prefix != NULL && prefix->bv_len > 0 ) {
174 HASH_Update( &HASHcontext,
175 prefix->bv_val, prefix->bv_len );
177 HASH_Update( &HASHcontext,
178 syntax->ssyn_oid, slen );
179 HASH_Update( &HASHcontext,
181 HASH_Update( &HASHcontext,
182 values[i].bv_val, values[i].bv_len );
183 HASH_Final( HASHdigest, &HASHcontext );
185 ber_dupbv( &keys[i], &digest );
188 keys[i].bv_val = NULL;
196 /* Index generation function */
197 int octetStringFilter(
202 struct berval *prefix,
203 void * assertedValue,
208 HASH_CONTEXT HASHcontext;
209 unsigned char HASHdigest[HASH_BYTES];
210 struct berval *value = (struct berval *) assertedValue;
211 struct berval digest;
212 digest.bv_val = HASHdigest;
213 digest.bv_len = sizeof(HASHdigest);
215 slen = syntax->ssyn_oidlen;
216 mlen = mr->smr_oidlen;
218 keys = ch_malloc( sizeof( struct berval ) * 2 );
220 HASH_Init( &HASHcontext );
221 if( prefix != NULL && prefix->bv_len > 0 ) {
222 HASH_Update( &HASHcontext,
223 prefix->bv_val, prefix->bv_len );
225 HASH_Update( &HASHcontext,
226 syntax->ssyn_oid, slen );
227 HASH_Update( &HASHcontext,
229 HASH_Update( &HASHcontext,
230 value->bv_val, value->bv_len );
231 HASH_Final( HASHdigest, &HASHcontext );
233 ber_dupbv( keys, &digest );
234 keys[1].bv_val = NULL;
247 /* no value allowed */
248 return LDAP_INVALID_SYNTAX;
256 /* any value allowed */
267 /* very unforgiving validation, requires no normalization
268 * before simplistic matching
270 if( in->bv_len < 3 ) {
271 return LDAP_INVALID_SYNTAX;
275 * rfc 2252 section 6.3 Bit String
276 * bitstring = "'" *binary-digit "'"
277 * binary-digit = "0" / "1"
278 * example: '0101111101'B
281 if( in->bv_val[0] != '\'' ||
282 in->bv_val[in->bv_len-2] != '\'' ||
283 in->bv_val[in->bv_len-1] != 'B' )
285 return LDAP_INVALID_SYNTAX;
288 for( i=in->bv_len-3; i>0; i-- ) {
289 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
290 return LDAP_INVALID_SYNTAX;
301 struct berval *normalized )
304 * A normalized bitString is has no extaneous (leading) zero bits.
305 * That is, '00010'B is normalized to '10'B
306 * However, as a special case, '0'B requires no normalization.
310 /* start at the first bit */
313 /* Find the first non-zero bit */
314 while ( *p == '0' ) p++;
317 /* no non-zero bits */
318 ber_str2bv( "\'0\'B", sizeof("\'0\'B") - 1, 1, normalized );
322 normalized->bv_val = ch_malloc( val->bv_len + 1 );
324 normalized->bv_val[0] = '\'';
325 normalized->bv_len = 1;
327 for( ; *p != '\0'; p++ ) {
328 normalized->bv_val[normalized->bv_len++] = *p;
331 normalized->bv_val[normalized->bv_len] = '\0';
345 if( in->bv_len == 0 ) return LDAP_SUCCESS;
347 ber_dupbv( &dn, in );
348 if( !dn.bv_val ) return LDAP_OTHER;
350 if( dn.bv_val[dn.bv_len-1] == 'B'
351 && dn.bv_val[dn.bv_len-2] == '\'' )
353 /* assume presence of optional UID */
356 for(i=dn.bv_len-3; i>1; i--) {
357 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
361 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
362 ber_memfree( dn.bv_val );
363 return LDAP_INVALID_SYNTAX;
366 /* trim the UID to allow use of dnValidate */
367 dn.bv_val[i-1] = '\0';
371 rc = dnValidate( NULL, &dn );
373 ber_memfree( dn.bv_val );
381 struct berval *normalized )
386 ber_dupbv( &out, val );
387 if( out.bv_len != 0 ) {
388 struct berval uidin = { 0, NULL };
389 struct berval uidout = { 0, NULL };
391 if( out.bv_val[out.bv_len-1] == 'B'
392 && out.bv_val[out.bv_len-2] == '\'' )
394 /* assume presence of optional UID */
395 uidin.bv_val = strrchr( out.bv_val, '#' );
397 if( uidin.bv_val == NULL ) {
399 return LDAP_INVALID_SYNTAX;
402 uidin.bv_len = out.bv_len - (uidin.bv_val - out.bv_val);
403 out.bv_len -= uidin.bv_len--;
405 /* temporarily trim the UID */
406 *(uidin.bv_val++) = '\0';
408 rc = bitStringNormalize( syntax, &uidin, &uidout );
410 if( rc != LDAP_SUCCESS ) {
412 return LDAP_INVALID_SYNTAX;
416 #ifdef USE_DN_NORMALIZE
417 rc = dnNormalize2( NULL, &out, normalized );
419 rc = dnPretty2( NULL, &out, normalized );
422 if( rc != LDAP_SUCCESS ) {
424 free( uidout.bv_val );
425 return LDAP_INVALID_SYNTAX;
428 if( uidout.bv_len ) {
429 normalized->bv_val = ch_realloc( normalized->bv_val,
430 normalized->bv_len + uidout.bv_len + sizeof("#") );
432 /* insert the separator */
433 normalized->bv_val[normalized->bv_len++] = '#';
436 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
437 uidout.bv_val, uidout.bv_len );
438 normalized->bv_len += uidout.bv_len;
441 normalized->bv_val[normalized->bv_len] = '\0';
451 * Handling boolean syntax and matching is quite rigid.
452 * A more flexible approach would be to allow a variety
453 * of strings to be normalized and prettied into TRUE
461 /* very unforgiving validation, requires no normalization
462 * before simplistic matching
465 if( in->bv_len == 4 ) {
466 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
469 } else if( in->bv_len == 5 ) {
470 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
475 return LDAP_INVALID_SYNTAX;
484 struct berval *value,
485 void *assertedValue )
487 /* simplistic matching allowed by rigid validation */
488 struct berval *asserted = (struct berval *) assertedValue;
489 *matchp = value->bv_len != asserted->bv_len;
493 /*-------------------------------------------------------------------
494 LDAP/X.500 string syntax / matching rules have a few oddities. This
495 comment attempts to detail how slapd(8) treats them.
498 StringSyntax X.500 LDAP Matching
499 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
500 PrintableString subset subset i/e + ignore insignificant spaces
501 NumericString subset subset ignore all spaces
502 IA5String ASCII ASCII i/e + ignore insignificant spaces
503 TeletexString T.61 T.61 i/e + ignore insignificant spaces
505 TelephoneNumber subset subset i + ignore all spaces and "-"
507 See draft-ietf-ldapbis-strpro for details (once published).
511 In X.500(93), a directory string can be either a PrintableString,
512 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
513 In later versions, more CHOICEs were added. In all cases the string
516 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
518 For matching, there are both case ignore and exact rules. Both
519 also require that "insignificant" spaces be ignored.
520 spaces before the first non-space are ignored;
521 spaces after the last non-space are ignored;
522 spaces after a space are ignored.
523 Note: by these rules (and as clarified in X.520), a string of only
524 spaces is to be treated as if held one space, not empty (which
525 would be a syntax error).
528 In ASN.1, numeric string is just a string of digits and spaces
529 and could be empty. However, in X.500, all attribute values of
530 numeric string carry a non-empty constraint. For example:
532 internationalISDNNumber ATTRIBUTE ::= {
533 WITH SYNTAX InternationalISDNNumber
534 EQUALITY MATCHING RULE numericStringMatch
535 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
536 ID id-at-internationalISDNNumber }
537 InternationalISDNNumber ::=
538 NumericString (SIZE(1..ub-international-isdn-number))
540 Unforunately, some assertion values are don't carry the same
541 constraint (but its unclear how such an assertion could ever
542 be true). In LDAP, there is one syntax (numericString) not two
543 (numericString with constraint, numericString without constraint).
544 This should be treated as numericString with non-empty constraint.
545 Note that while someone may have no ISDN number, there are no ISDN
546 numbers which are zero length.
548 In matching, spaces are ignored.
551 In ASN.1, Printable string is just a string of printable characters
552 and can be empty. In X.500, semantics much like NumericString (see
553 serialNumber for a like example) excepting uses insignificant space
554 handling instead of ignore all spaces.
557 Basically same as PrintableString. There are no examples in X.500,
558 but same logic applies. So we require them to be non-empty as
561 -------------------------------------------------------------------*/
570 unsigned char *u = in->bv_val;
572 if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
574 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
575 /* get the length indicated by the first byte */
576 len = LDAP_UTF8_CHARLEN2( u, len );
578 /* very basic checks */
581 if( (u[5] & 0xC0) != 0x80 ) {
582 return LDAP_INVALID_SYNTAX;
585 if( (u[4] & 0xC0) != 0x80 ) {
586 return LDAP_INVALID_SYNTAX;
589 if( (u[3] & 0xC0) != 0x80 ) {
590 return LDAP_INVALID_SYNTAX;
593 if( (u[2] & 0xC0 )!= 0x80 ) {
594 return LDAP_INVALID_SYNTAX;
597 if( (u[1] & 0xC0) != 0x80 ) {
598 return LDAP_INVALID_SYNTAX;
601 /* CHARLEN already validated it */
604 return LDAP_INVALID_SYNTAX;
607 /* make sure len corresponds with the offset
608 to the next character */
609 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
612 if( count != 0 ) return LDAP_INVALID_SYNTAX;
621 struct berval *normalized )
626 /* validator should have refused an empty string */
627 assert( val->bv_len );
631 /* Ignore initial whitespace */
632 /* All space is ASCII. All ASCII is 1 byte */
633 for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
635 normalized->bv_len = val->bv_len - (p - val->bv_val);
637 if( !normalized->bv_len ) {
638 ber_mem2bv( " ", 1, 1, normalized );
642 ber_mem2bv( p, normalized->bv_len, 1, normalized );
643 e = normalized->bv_val + normalized->bv_len;
645 assert( normalized->bv_val );
647 p = q = normalized->bv_val;
652 if ( ASCII_SPACE( *p ) ) {
657 /* Ignore the extra whitespace */
658 while ( ASCII_SPACE( *p ) ) {
662 len = LDAP_UTF8_COPY(q,p);
668 assert( normalized->bv_val <= p );
669 assert( q+len <= p );
671 /* cannot start with a space */
672 assert( !ASCII_SPACE( normalized->bv_val[0] ) );
675 * If the string ended in space, backup the pointer one
676 * position. One is enough because the above loop collapsed
677 * all whitespace to a single space.
685 /* cannot end with a space */
686 assert( !ASCII_SPACE( *q ) );
693 normalized->bv_len = q - normalized->bv_val;
698 /* Returns Unicode canonically normalized copy of a substring assertion
699 * Skipping attribute description */
700 static SubstringsAssertion *
701 UTF8SubstringsassertionNormalize(
702 SubstringsAssertion *sa,
705 SubstringsAssertion *nsa;
708 nsa = (SubstringsAssertion *)ch_calloc( 1, sizeof(SubstringsAssertion) );
713 if( sa->sa_initial.bv_val != NULL ) {
714 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
715 if( nsa->sa_initial.bv_val == NULL ) {
720 if( sa->sa_any != NULL ) {
721 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
724 nsa->sa_any = (struct berval *)
725 ch_malloc( (i + 1) * sizeof(struct berval) );
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>
3579 char digit[] = "0123456789";
3582 * Next function returns a string representation of a ASN1_INTEGER.
3583 * It works for unlimited lengths.
3586 static struct berval *
3587 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
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.18 octetStringOrderingMatch
4462 * 2.5.13.19 octetStringSubstringsMatch
4463 * 2.5.13.25 uTCTimeMatch
4464 * 2.5.13.26 uTCTimeOrderingMatch
4465 * 2.5.13.31 directoryStringFirstComponentMatch
4466 * 2.5.13.32 wordMatch
4467 * 2.5.13.33 keywordMatch
4468 * 2.5.13.35 certificateMatch
4469 * 2.5.13.36 certificatePairExactMatch
4470 * 2.5.13.37 certificatePairMatch
4471 * 2.5.13.38 certificateListExactMatch
4472 * 2.5.13.39 certificateListMatch
4473 * 2.5.13.40 algorithmIdentifierMatch
4474 * 2.5.13.41 storedPrefixMatch
4475 * 2.5.13.42 attributeCertificateMatch
4476 * 2.5.13.43 readerAndKeyIDMatch
4477 * 2.5.13.44 attributeIntegrityMatch
4479 static slap_mrule_defs_rec mrule_defs[] = {
4481 * EQUALITY matching rules must be listed after associated APPROX
4482 * matching rules. So, we list all APPROX matching rules first.
4484 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4485 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4486 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4488 directoryStringApproxMatch,
4489 directoryStringApproxIndexer,
4490 directoryStringApproxFilter,
4493 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4494 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4495 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4497 IA5StringApproxMatch,
4498 IA5StringApproxIndexer,
4499 IA5StringApproxFilter,
4503 * Other matching rules
4506 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4507 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4508 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4510 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4513 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4514 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4515 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4517 dnMatch, dnIndexer, dnFilter,
4520 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4521 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4522 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4523 directoryStringSyntaxes,
4525 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4526 directoryStringApproxMatchOID },
4528 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4529 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4530 SLAP_MR_ORDERING, directoryStringSyntaxes,
4532 caseIgnoreOrderingMatch, NULL, NULL,
4535 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4536 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4537 SLAP_MR_SUBSTR, NULL,
4539 caseExactIgnoreSubstringsMatch,
4540 caseExactIgnoreSubstringsIndexer,
4541 caseExactIgnoreSubstringsFilter,
4544 {"( 2.5.13.5 NAME 'caseExactMatch' "
4545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4546 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4548 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4549 directoryStringApproxMatchOID },
4551 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4552 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4553 SLAP_MR_ORDERING, directoryStringSyntaxes,
4555 caseExactOrderingMatch, NULL, NULL,
4558 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4559 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4560 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4562 caseExactIgnoreSubstringsMatch,
4563 caseExactIgnoreSubstringsIndexer,
4564 caseExactIgnoreSubstringsFilter,
4567 {"( 2.5.13.8 NAME 'numericStringMatch' "
4568 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4569 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4572 caseIgnoreIA5Indexer,
4573 caseIgnoreIA5Filter,
4576 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4577 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4578 SLAP_MR_SUBSTR, NULL,
4580 caseIgnoreIA5SubstringsMatch,
4581 caseIgnoreIA5SubstringsIndexer,
4582 caseIgnoreIA5SubstringsFilter,
4585 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4586 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4587 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4589 caseIgnoreListMatch, NULL, NULL,
4592 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4593 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4594 SLAP_MR_SUBSTR, NULL,
4596 caseIgnoreListSubstringsMatch, NULL, NULL,
4599 {"( 2.5.13.13 NAME 'booleanMatch' "
4600 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4601 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4603 booleanMatch, NULL, NULL,
4606 {"( 2.5.13.14 NAME 'integerMatch' "
4607 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4608 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4610 integerMatch, integerIndexer, integerFilter,
4613 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4614 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4615 SLAP_MR_ORDERING, NULL,
4617 integerOrderingMatch, NULL, NULL,
4620 {"( 2.5.13.16 NAME 'bitStringMatch' "
4621 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4622 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4624 bitStringMatch, bitStringIndexer, bitStringFilter,
4627 {"( 2.5.13.17 NAME 'octetStringMatch' "
4628 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4629 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4631 octetStringMatch, octetStringIndexer, octetStringFilter,
4634 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4635 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4636 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4638 telephoneNumberMatch,
4639 telephoneNumberIndexer,
4640 telephoneNumberFilter,
4643 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4644 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4645 SLAP_MR_SUBSTR, NULL,
4647 telephoneNumberSubstringsMatch,
4648 telephoneNumberSubstringsIndexer,
4649 telephoneNumberSubstringsFilter,
4652 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4653 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4654 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4659 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4660 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4661 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4663 uniqueMemberMatch, NULL, NULL,
4666 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4667 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4668 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4670 protocolInformationMatch, NULL, NULL,
4673 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4674 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4675 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4677 generalizedTimeMatch, NULL, NULL,
4680 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4681 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4682 SLAP_MR_ORDERING, NULL,
4684 generalizedTimeOrderingMatch, NULL, NULL,
4687 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4688 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4689 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
4691 integerFirstComponentMatch, NULL, NULL,
4694 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4695 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4696 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4697 objectIdentifierFirstComponentMatchSyntaxes,
4699 objectIdentifierFirstComponentMatch, NULL, NULL,
4703 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4704 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4705 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4706 certificateExactConvert, NULL,
4707 certificateExactMatch,
4708 certificateExactIndexer, certificateExactFilter,
4712 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4713 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4714 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4716 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4717 IA5StringApproxMatchOID },
4719 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4720 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4721 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4723 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4724 IA5StringApproxMatchOID },
4726 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4727 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4728 SLAP_MR_SUBSTR, NULL,
4730 caseIgnoreIA5SubstringsMatch,
4731 caseIgnoreIA5SubstringsIndexer,
4732 caseIgnoreIA5SubstringsFilter,
4735 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4736 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4737 SLAP_MR_SUBSTR, NULL,
4739 caseExactIA5SubstringsMatch,
4740 caseExactIA5SubstringsIndexer,
4741 caseExactIA5SubstringsFilter,
4744 #ifdef SLAPD_AUTHPASSWD
4745 /* needs updating */
4746 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4747 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4748 SLAP_MR_EQUALITY, NULL,
4750 authPasswordMatch, NULL, NULL,
4754 #ifdef SLAPD_ACI_ENABLED
4755 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4756 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4757 SLAP_MR_EQUALITY, NULL,
4759 OpenLDAPaciMatch, NULL, NULL,
4763 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4764 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4767 integerBitAndMatch, NULL, NULL,
4770 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4771 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4774 integerBitOrMatch, NULL, NULL,
4777 {NULL, SLAP_MR_NONE, NULL,
4778 NULL, NULL, NULL, NULL, NULL,
4783 slap_schema_init( void )
4788 /* we should only be called once (from main) */
4789 assert( schema_init_done == 0 );
4791 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4792 res = register_syntax( &syntax_defs[i] );
4795 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4796 syntax_defs[i].sd_desc );
4801 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4802 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4803 mrule_defs[i].mrd_compat_syntaxes == NULL )
4806 "slap_schema_init: Ingoring unusable matching rule %s\n",
4807 mrule_defs[i].mrd_desc );
4811 res = register_matching_rule( &mrule_defs[i] );
4815 "slap_schema_init: Error registering matching rule %s\n",
4816 mrule_defs[i].mrd_desc );
4821 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4822 *mr_ptr[i].mr = mr_find( mr_ptr[i].oid );
4824 res = slap_schema_load();
4825 schema_init_done = 1;
4830 schema_destroy( void )
4836 for ( i=0; i < (int)(sizeof(mr_ptr)/sizeof(mr_ptr[0])); i++ )
4837 *mr_ptr[i].mr = NULL;