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 caseIgnoreIA5Match
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 static 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;
195 /* Index generation function */
196 static int octetStringFilter(
201 struct berval *prefix,
207 HASH_CONTEXT HASHcontext;
208 unsigned char HASHdigest[HASH_BYTES];
209 struct berval *value = (struct berval *) assertValue;
210 struct berval digest;
211 digest.bv_val = HASHdigest;
212 digest.bv_len = sizeof(HASHdigest);
214 slen = syntax->ssyn_oidlen;
215 mlen = mr->smr_oidlen;
217 keys = ch_malloc( sizeof( struct berval ) * 2 );
219 HASH_Init( &HASHcontext );
220 if( prefix != NULL && prefix->bv_len > 0 ) {
221 HASH_Update( &HASHcontext,
222 prefix->bv_val, prefix->bv_len );
224 HASH_Update( &HASHcontext,
225 syntax->ssyn_oid, slen );
226 HASH_Update( &HASHcontext,
228 HASH_Update( &HASHcontext,
229 value->bv_val, value->bv_len );
230 HASH_Final( HASHdigest, &HASHcontext );
232 ber_dupbv( keys, &digest );
233 keys[1].bv_val = NULL;
245 /* no value allowed */
246 return LDAP_INVALID_SYNTAX;
254 /* any value allowed */
265 /* very unforgiving validation, requires no normalization
266 * before simplistic matching
268 if( in->bv_len < 3 ) {
269 return LDAP_INVALID_SYNTAX;
273 * rfc 2252 section 6.3 Bit String
274 * bitstring = "'" *binary-digit "'"
275 * binary-digit = "0" / "1"
276 * example: '0101111101'B
279 if( in->bv_val[0] != '\'' ||
280 in->bv_val[in->bv_len-2] != '\'' ||
281 in->bv_val[in->bv_len-1] != 'B' )
283 return LDAP_INVALID_SYNTAX;
286 for( i=in->bv_len-3; i>0; i-- ) {
287 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
288 return LDAP_INVALID_SYNTAX;
299 struct berval *normalized )
302 * A normalized bitString is has no extaneous (leading) zero bits.
303 * That is, '00010'B is normalized to '10'B
304 * However, as a special case, '0'B requires no normalization.
308 /* start at the first bit */
311 /* Find the first non-zero bit */
312 while ( *p == '0' ) p++;
315 /* no non-zero bits */
316 ber_str2bv( "\'0\'B", sizeof("\'0\'B") - 1, 1, normalized );
320 normalized->bv_val = ch_malloc( val->bv_len + 1 );
322 normalized->bv_val[0] = '\'';
323 normalized->bv_len = 1;
325 for( ; *p != '\0'; p++ ) {
326 normalized->bv_val[normalized->bv_len++] = *p;
329 normalized->bv_val[normalized->bv_len] = '\0';
343 if( in->bv_len == 0 ) return LDAP_SUCCESS;
345 ber_dupbv( &dn, in );
346 if( !dn.bv_val ) return LDAP_OTHER;
348 if( dn.bv_val[dn.bv_len-1] == 'B'
349 && dn.bv_val[dn.bv_len-2] == '\'' )
351 /* assume presence of optional UID */
354 for(i=dn.bv_len-3; i>1; i--) {
355 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
359 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
360 ber_memfree( dn.bv_val );
361 return LDAP_INVALID_SYNTAX;
364 /* trim the UID to allow use of dnValidate */
365 dn.bv_val[i-1] = '\0';
369 rc = dnValidate( NULL, &dn );
371 ber_memfree( dn.bv_val );
379 struct berval *normalized )
384 ber_dupbv( &out, val );
385 if( out.bv_len != 0 ) {
386 struct berval uidin = { 0, NULL };
387 struct berval uidout = { 0, NULL };
389 if( out.bv_val[out.bv_len-1] == 'B'
390 && out.bv_val[out.bv_len-2] == '\'' )
392 /* assume presence of optional UID */
393 uidin.bv_val = strrchr( out.bv_val, '#' );
395 if( uidin.bv_val == NULL ) {
397 return LDAP_INVALID_SYNTAX;
400 uidin.bv_len = out.bv_len - (uidin.bv_val - out.bv_val);
401 out.bv_len -= uidin.bv_len--;
403 /* temporarily trim the UID */
404 *(uidin.bv_val++) = '\0';
406 rc = bitStringNormalize( syntax, &uidin, &uidout );
408 if( rc != LDAP_SUCCESS ) {
410 return LDAP_INVALID_SYNTAX;
414 #ifdef USE_DN_NORMALIZE
415 rc = dnNormalize2( NULL, &out, normalized );
417 rc = dnPretty2( NULL, &out, normalized );
420 if( rc != LDAP_SUCCESS ) {
422 free( uidout.bv_val );
423 return LDAP_INVALID_SYNTAX;
426 if( uidout.bv_len ) {
427 normalized->bv_val = ch_realloc( normalized->bv_val,
428 normalized->bv_len + uidout.bv_len + sizeof("#") );
430 /* insert the separator */
431 normalized->bv_val[normalized->bv_len++] = '#';
434 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
435 uidout.bv_val, uidout.bv_len );
436 normalized->bv_len += uidout.bv_len;
439 normalized->bv_val[normalized->bv_len] = '\0';
449 * Handling boolean syntax and matching is quite rigid.
450 * A more flexible approach would be to allow a variety
451 * of strings to be normalized and prettied into TRUE
459 /* very unforgiving validation, requires no normalization
460 * before simplistic matching
463 if( in->bv_len == 4 ) {
464 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
467 } else if( in->bv_len == 5 ) {
468 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
473 return LDAP_INVALID_SYNTAX;
482 struct berval *value,
483 void *assertedValue )
485 /* simplistic matching allowed by rigid validation */
486 struct berval *asserted = (struct berval *) assertedValue;
487 *matchp = value->bv_len != asserted->bv_len;
491 /*-------------------------------------------------------------------
492 LDAP/X.500 string syntax / matching rules have a few oddities. This
493 comment attempts to detail how slapd(8) treats them.
496 StringSyntax X.500 LDAP Matching
497 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
498 PrintableString subset subset i/e + ignore insignificant spaces
499 NumericString subset subset ignore all spaces
500 IA5String ASCII ASCII i/e + ignore insignificant spaces
501 TeletexString T.61 T.61 i/e + ignore insignificant spaces
503 TelephoneNumber subset subset i + ignore all spaces and "-"
505 See draft-ietf-ldapbis-strpro for details (once published).
509 In X.500(93), a directory string can be either a PrintableString,
510 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
511 In later versions, more CHOICEs were added. In all cases the string
514 In LDPAv3, a directory string is a UTF-8 encoded UCS string.
516 For matching, there are both case ignore and exact rules. Both
517 also require that "insignificant" spaces be ignored.
518 spaces before the first non-space are ignored;
519 spaces after the last non-space are ignored;
520 spaces after a space are ignored.
521 Note: by these rules (and as clarified in X.520), a string of only
522 spaces is to be treated as if held one space, not empty (which
523 would be a syntax error).
526 In ASN.1, numeric string is just a string of digits and spaces
527 and could be empty. However, in X.500, all attribute values of
528 numeric string carry a non-empty constraint. For example:
530 internationalISDNNumber ATTRIBUTE ::= {
531 WITH SYNTAX InternationalISDNNumber
532 EQUALITY MATCHING RULE numericStringMatch
533 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
534 ID id-at-internationalISDNNumber }
535 InternationalISDNNumber ::=
536 NumericString (SIZE(1..ub-international-isdn-number))
538 Unforunately, some assertion values are don't carry the same
539 constraint (but its unclear how such an assertion could ever
540 be true). In LDAP, there is one syntax (numericString) not two
541 (numericString with constraint, numericString without constraint).
542 This should be treated as numericString with non-empty constraint.
543 Note that while someone may have no ISDN number, there are no ISDN
544 numbers which are zero length.
546 In matching, spaces are ignored.
549 In ASN.1, Printable string is just a string of printable characters
550 and can be empty. In X.500, semantics much like NumericString (see
551 serialNumber for a like example) excepting uses insignificant space
552 handling instead of ignore all spaces.
555 Basically same as PrintableString. There are no examples in X.500,
556 but same logic applies. So we require them to be non-empty as
559 -------------------------------------------------------------------*/
568 unsigned char *u = in->bv_val;
570 if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
572 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
573 /* get the length indicated by the first byte */
574 len = LDAP_UTF8_CHARLEN2( u, len );
576 /* very basic checks */
579 if( (u[5] & 0xC0) != 0x80 ) {
580 return LDAP_INVALID_SYNTAX;
583 if( (u[4] & 0xC0) != 0x80 ) {
584 return LDAP_INVALID_SYNTAX;
587 if( (u[3] & 0xC0) != 0x80 ) {
588 return LDAP_INVALID_SYNTAX;
591 if( (u[2] & 0xC0 )!= 0x80 ) {
592 return LDAP_INVALID_SYNTAX;
595 if( (u[1] & 0xC0) != 0x80 ) {
596 return LDAP_INVALID_SYNTAX;
599 /* CHARLEN already validated it */
602 return LDAP_INVALID_SYNTAX;
605 /* make sure len corresponds with the offset
606 to the next character */
607 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
610 if( count != 0 ) return LDAP_INVALID_SYNTAX;
619 struct berval *normalized )
624 /* validator should have refused an empty string */
625 assert( val->bv_len );
629 /* Ignore initial whitespace */
630 /* All space is ASCII. All ASCII is 1 byte */
631 for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
633 normalized->bv_len = val->bv_len - (p - val->bv_val);
635 if( !normalized->bv_len ) {
636 ber_mem2bv( " ", 1, 1, normalized );
640 ber_mem2bv( p, normalized->bv_len, 1, normalized );
641 e = normalized->bv_val + normalized->bv_len;
643 assert( normalized->bv_val );
645 p = q = normalized->bv_val;
650 if ( ASCII_SPACE( *p ) ) {
655 /* Ignore the extra whitespace */
656 while ( ASCII_SPACE( *p ) ) {
660 len = LDAP_UTF8_COPY(q,p);
666 assert( normalized->bv_val <= p );
667 assert( q+len <= p );
669 /* cannot start with a space */
670 assert( !ASCII_SPACE( normalized->bv_val[0] ) );
673 * If the string ended in space, backup the pointer one
674 * position. One is enough because the above loop collapsed
675 * all whitespace to a single space.
683 /* cannot end with a space */
684 assert( !ASCII_SPACE( *q ) );
691 normalized->bv_len = q - normalized->bv_val;
696 /* Returns Unicode canonically normalized copy of a substring assertion
697 * Skipping attribute description */
698 static SubstringsAssertion *
699 UTF8SubstringsassertionNormalize(
700 SubstringsAssertion *sa,
703 SubstringsAssertion *nsa;
706 nsa = (SubstringsAssertion *)ch_calloc( 1, sizeof(SubstringsAssertion) );
711 if( sa->sa_initial.bv_val != NULL ) {
712 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
713 if( nsa->sa_initial.bv_val == NULL ) {
718 if( sa->sa_any != NULL ) {
719 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
722 nsa->sa_any = (struct berval *)
723 ch_malloc( (i + 1) * sizeof(struct berval) );
725 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
726 UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
728 if( nsa->sa_any[i].bv_val == NULL ) {
732 nsa->sa_any[i].bv_val = NULL;
735 if( sa->sa_final.bv_val != NULL ) {
736 UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
737 if( nsa->sa_final.bv_val == NULL ) {
745 if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
746 if ( nsa->sa_any ) ber_bvarray_free( nsa->sa_any );
747 if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
752 #ifndef SLAPD_APPROX_OLDSINGLESTRING
754 #if defined(SLAPD_APPROX_INITIALS)
755 #define SLAPD_APPROX_DELIMITER "._ "
756 #define SLAPD_APPROX_WORDLEN 2
758 #define SLAPD_APPROX_DELIMITER " "
759 #define SLAPD_APPROX_WORDLEN 1
768 struct berval *value,
769 void *assertedValue )
771 struct berval *nval, *assertv;
772 char *val, **values, **words, *c;
773 int i, count, len, nextchunk=0, nextavail=0;
775 /* Yes, this is necessary */
776 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
782 /* Yes, this is necessary */
783 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
784 NULL, LDAP_UTF8_APPROX );
785 if( assertv == NULL ) {
791 /* Isolate how many words there are */
792 for ( c = nval->bv_val, count = 1; *c; c++ ) {
793 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
794 if ( c == NULL ) break;
799 /* Get a phonetic copy of each word */
800 words = (char **)ch_malloc( count * sizeof(char *) );
801 values = (char **)ch_malloc( count * sizeof(char *) );
802 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
804 values[i] = phonetic(c);
807 /* Work through the asserted value's words, to see if at least some
808 of the words are there, in the same order. */
810 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
811 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
816 #if defined(SLAPD_APPROX_INITIALS)
817 else if( len == 1 ) {
818 /* Single letter words need to at least match one word's initial */
819 for( i=nextavail; i<count; i++ )
820 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
827 /* Isolate the next word in the asserted value and phonetic it */
828 assertv->bv_val[nextchunk+len] = '\0';
829 val = phonetic( assertv->bv_val + nextchunk );
831 /* See if this phonetic chunk is in the remaining words of *value */
832 for( i=nextavail; i<count; i++ ){
833 if( !strcmp( val, values[i] ) ){
841 /* This chunk in the asserted value was NOT within the *value. */
847 /* Go on to the next word in the asserted value */
851 /* If some of the words were seen, call it a match */
852 if( nextavail > 0 ) {
860 ber_bvfree( assertv );
861 for( i=0; i<count; i++ ) {
862 ch_free( values[i] );
877 struct berval *prefix,
882 int i,j, len, wordcount, keycount=0;
883 struct berval *newkeys;
886 for( j=0; values[j].bv_val != NULL; j++ ) {
887 struct berval val = { 0, NULL };
888 /* Yes, this is necessary */
889 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
890 assert( val.bv_val != NULL );
892 /* Isolate how many words there are. There will be a key for each */
893 for( wordcount = 0, c = val.bv_val; *c; c++) {
894 len = strcspn(c, SLAPD_APPROX_DELIMITER);
895 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
897 if (*c == '\0') break;
901 /* Allocate/increase storage to account for new keys */
902 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
903 * sizeof(struct berval) );
904 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
905 if( keys ) ch_free( keys );
908 /* Get a phonetic copy of each word */
909 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
911 if( len < SLAPD_APPROX_WORDLEN ) continue;
912 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
917 ber_memfree( val.bv_val );
919 keys[keycount].bv_val = NULL;
931 struct berval *prefix,
940 /* Yes, this is necessary */
941 val = UTF8bvnormalize( ((struct berval *)assertValue),
942 NULL, LDAP_UTF8_APPROX );
943 if( val == NULL || val->bv_val == NULL ) {
944 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
945 keys[0].bv_val = NULL;
951 /* Isolate how many words there are. There will be a key for each */
952 for( count = 0,c = val->bv_val; *c; c++) {
953 len = strcspn(c, SLAPD_APPROX_DELIMITER);
954 if( len >= SLAPD_APPROX_WORDLEN ) count++;
956 if (*c == '\0') break;
960 /* Allocate storage for new keys */
961 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
963 /* Get a phonetic copy of each word */
964 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
966 if( len < SLAPD_APPROX_WORDLEN ) continue;
967 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
973 keys[count].bv_val = NULL;
981 /* No other form of Approximate Matching is defined */
989 struct berval *value,
990 void *assertedValue )
992 char *vapprox, *avapprox;
995 /* Yes, this is necessary */
996 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1002 /* Yes, this is necessary */
1003 t = UTF8normalize( ((struct berval *)assertedValue),
1008 return LDAP_SUCCESS;
1011 vapprox = phonetic( strip8bitChars( s ) );
1012 avapprox = phonetic( strip8bitChars( t ) );
1017 *matchp = strcmp( vapprox, avapprox );
1020 ch_free( avapprox );
1022 return LDAP_SUCCESS;
1031 struct berval *prefix,
1039 for( i=0; values[i].bv_val != NULL; i++ ) {
1040 /* empty - just count them */
1043 /* we should have at least one value at this point */
1046 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1048 /* Copy each value and run it through phonetic() */
1049 for( i=0; values[i].bv_val != NULL; i++ ) {
1050 /* Yes, this is necessary */
1051 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1053 /* strip 8-bit chars and run through phonetic() */
1054 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1057 keys[i].bv_val = NULL;
1060 return LDAP_SUCCESS;
1070 struct berval *prefix,
1077 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1079 /* Yes, this is necessary */
1080 s = UTF8normalize( ((struct berval *)assertValue),
1085 /* strip 8-bit chars and run through phonetic() */
1086 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1092 return LDAP_SUCCESS;
1103 struct berval *value,
1104 void *assertedValue )
1106 *matchp = UTF8bvnormcmp( value,
1107 (struct berval *) assertedValue,
1108 LDAP_UTF8_NOCASEFOLD );
1109 return LDAP_SUCCESS;
1113 caseExactIgnoreSubstringsMatch(
1118 struct berval *value,
1119 void *assertedValue )
1122 SubstringsAssertion *sub = NULL;
1123 struct berval left = { 0, NULL };
1129 casefold = ( mr != caseExactSubstringsMatchingRule )
1130 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1132 if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1138 sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
1144 /* Add up asserted input length */
1145 if( sub->sa_initial.bv_val ) {
1146 inlen += sub->sa_initial.bv_len;
1149 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1150 inlen += sub->sa_any[i].bv_len;
1153 if( sub->sa_final.bv_val ) {
1154 inlen += sub->sa_final.bv_len;
1157 if( sub->sa_initial.bv_val ) {
1158 if( inlen > left.bv_len ) {
1163 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1164 sub->sa_initial.bv_len );
1170 left.bv_val += sub->sa_initial.bv_len;
1171 left.bv_len -= sub->sa_initial.bv_len;
1172 inlen -= sub->sa_initial.bv_len;
1175 if( sub->sa_final.bv_val ) {
1176 if( inlen > left.bv_len ) {
1181 match = memcmp( sub->sa_final.bv_val,
1182 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1183 sub->sa_final.bv_len );
1189 left.bv_len -= sub->sa_final.bv_len;
1190 inlen -= sub->sa_final.bv_len;
1194 for(i=0; sub->sa_any[i].bv_val; i++) {
1199 if( inlen > left.bv_len ) {
1200 /* not enough length */
1205 if( sub->sa_any[i].bv_len == 0 ) {
1209 p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1215 idx = p - left.bv_val;
1217 if( idx >= left.bv_len ) {
1218 /* this shouldn't happen */
1220 if ( sub->sa_final.bv_val )
1221 ch_free( sub->sa_final.bv_val );
1223 ber_bvarray_free( sub->sa_any );
1224 if ( sub->sa_initial.bv_val )
1225 ch_free( sub->sa_initial.bv_val );
1233 if( sub->sa_any[i].bv_len > left.bv_len ) {
1234 /* not enough left */
1239 match = memcmp( left.bv_val,
1240 sub->sa_any[i].bv_val,
1241 sub->sa_any[i].bv_len );
1249 left.bv_val += sub->sa_any[i].bv_len;
1250 left.bv_len -= sub->sa_any[i].bv_len;
1251 inlen -= sub->sa_any[i].bv_len;
1258 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1259 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1260 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1264 return LDAP_SUCCESS;
1267 /* Index generation function */
1268 static int caseExactIgnoreIndexer(
1273 struct berval *prefix,
1281 HASH_CONTEXT HASHcontext;
1282 unsigned char HASHdigest[HASH_BYTES];
1283 struct berval digest;
1284 digest.bv_val = HASHdigest;
1285 digest.bv_len = sizeof(HASHdigest);
1287 for( i=0; values[i].bv_val != NULL; i++ ) {
1288 /* empty - just count them */
1291 /* we should have at least one value at this point */
1294 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1296 slen = syntax->ssyn_oidlen;
1297 mlen = mr->smr_oidlen;
1299 casefold = ( mr != caseExactMatchingRule )
1300 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1302 for( i=0; values[i].bv_val != NULL; i++ ) {
1303 struct berval value;
1304 UTF8bvnormalize( &values[i], &value, casefold );
1306 HASH_Init( &HASHcontext );
1307 if( prefix != NULL && prefix->bv_len > 0 ) {
1308 HASH_Update( &HASHcontext,
1309 prefix->bv_val, prefix->bv_len );
1311 HASH_Update( &HASHcontext,
1312 syntax->ssyn_oid, slen );
1313 HASH_Update( &HASHcontext,
1314 mr->smr_oid, mlen );
1315 HASH_Update( &HASHcontext,
1316 value.bv_val, value.bv_len );
1317 HASH_Final( HASHdigest, &HASHcontext );
1319 free( value.bv_val );
1321 ber_dupbv( &keys[i], &digest );
1324 keys[i].bv_val = NULL;
1326 return LDAP_SUCCESS;
1329 /* Index generation function */
1330 static int caseExactIgnoreFilter(
1335 struct berval *prefix,
1342 HASH_CONTEXT HASHcontext;
1343 unsigned char HASHdigest[HASH_BYTES];
1344 struct berval value = { 0, NULL };
1345 struct berval digest;
1347 digest.bv_val = HASHdigest;
1348 digest.bv_len = sizeof(HASHdigest);
1350 slen = syntax->ssyn_oidlen;
1351 mlen = mr->smr_oidlen;
1353 casefold = ( mr != caseExactMatchingRule )
1354 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1356 UTF8bvnormalize( (struct berval *) assertValue, &value, casefold );
1357 /* This usually happens if filter contains bad UTF8 */
1358 if( value.bv_val == NULL ) {
1359 keys = ch_malloc( sizeof( struct berval ) );
1360 keys[0].bv_val = NULL;
1361 return LDAP_SUCCESS;
1364 keys = ch_malloc( sizeof( struct berval ) * 2 );
1366 HASH_Init( &HASHcontext );
1367 if( prefix != NULL && prefix->bv_len > 0 ) {
1368 HASH_Update( &HASHcontext,
1369 prefix->bv_val, prefix->bv_len );
1371 HASH_Update( &HASHcontext,
1372 syntax->ssyn_oid, slen );
1373 HASH_Update( &HASHcontext,
1374 mr->smr_oid, mlen );
1375 HASH_Update( &HASHcontext,
1376 value.bv_val, value.bv_len );
1377 HASH_Final( HASHdigest, &HASHcontext );
1379 ber_dupbv( keys, &digest );
1380 keys[1].bv_val = NULL;
1382 free( value.bv_val );
1385 return LDAP_SUCCESS;
1388 /* Substrings Index generation function */
1389 static int caseExactIgnoreSubstringsIndexer(
1394 struct berval *prefix,
1404 HASH_CONTEXT HASHcontext;
1405 unsigned char HASHdigest[HASH_BYTES];
1406 struct berval digest;
1407 digest.bv_val = HASHdigest;
1408 digest.bv_len = sizeof(HASHdigest);
1412 for( i=0; values[i].bv_val != NULL; i++ ) {
1413 /* empty - just count them */
1416 /* we should have at least one value at this point */
1419 casefold = ( mr != caseExactSubstringsMatchingRule )
1420 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1422 nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1423 for( i=0; values[i].bv_val != NULL; i++ ) {
1424 UTF8bvnormalize( &values[i], &nvalues[i], casefold );
1426 nvalues[i].bv_val = NULL;
1429 for( i=0; values[i].bv_val != NULL; i++ ) {
1430 /* count number of indices to generate */
1431 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1435 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1436 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1437 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1438 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1440 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1444 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1445 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1446 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1450 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1451 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1452 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1453 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1455 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1461 /* no keys to generate */
1463 ber_bvarray_free( nvalues );
1464 return LDAP_SUCCESS;
1467 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1469 slen = syntax->ssyn_oidlen;
1470 mlen = mr->smr_oidlen;
1473 for( i=0; values[i].bv_val != NULL; i++ ) {
1476 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1478 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1479 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1481 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1482 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1484 for( j=0; j<max; j++ ) {
1485 HASH_Init( &HASHcontext );
1486 if( prefix != NULL && prefix->bv_len > 0 ) {
1487 HASH_Update( &HASHcontext,
1488 prefix->bv_val, prefix->bv_len );
1491 HASH_Update( &HASHcontext,
1492 &pre, sizeof( pre ) );
1493 HASH_Update( &HASHcontext,
1494 syntax->ssyn_oid, slen );
1495 HASH_Update( &HASHcontext,
1496 mr->smr_oid, mlen );
1497 HASH_Update( &HASHcontext,
1498 &values[i].bv_val[j],
1499 SLAP_INDEX_SUBSTR_MAXLEN );
1500 HASH_Final( HASHdigest, &HASHcontext );
1502 ber_dupbv( &keys[nkeys++], &digest );
1506 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1507 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1509 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1512 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1513 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1514 HASH_Init( &HASHcontext );
1515 if( prefix != NULL && prefix->bv_len > 0 ) {
1516 HASH_Update( &HASHcontext,
1517 prefix->bv_val, prefix->bv_len );
1519 HASH_Update( &HASHcontext,
1520 &pre, sizeof( pre ) );
1521 HASH_Update( &HASHcontext,
1522 syntax->ssyn_oid, slen );
1523 HASH_Update( &HASHcontext,
1524 mr->smr_oid, mlen );
1525 HASH_Update( &HASHcontext,
1526 values[i].bv_val, j );
1527 HASH_Final( HASHdigest, &HASHcontext );
1529 ber_dupbv( &keys[nkeys++], &digest );
1532 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1533 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1534 HASH_Init( &HASHcontext );
1535 if( prefix != NULL && prefix->bv_len > 0 ) {
1536 HASH_Update( &HASHcontext,
1537 prefix->bv_val, prefix->bv_len );
1539 HASH_Update( &HASHcontext,
1540 &pre, sizeof( pre ) );
1541 HASH_Update( &HASHcontext,
1542 syntax->ssyn_oid, slen );
1543 HASH_Update( &HASHcontext,
1544 mr->smr_oid, mlen );
1545 HASH_Update( &HASHcontext,
1546 &values[i].bv_val[values[i].bv_len-j], j );
1547 HASH_Final( HASHdigest, &HASHcontext );
1549 ber_dupbv( &keys[nkeys++], &digest );
1557 keys[nkeys].bv_val = NULL;
1564 ber_bvarray_free( nvalues );
1566 return LDAP_SUCCESS;
1569 static int caseExactIgnoreSubstringsFilter(
1574 struct berval *prefix,
1578 SubstringsAssertion *sa;
1581 ber_len_t nkeys = 0;
1582 size_t slen, mlen, klen;
1584 HASH_CONTEXT HASHcontext;
1585 unsigned char HASHdigest[HASH_BYTES];
1586 struct berval *value;
1587 struct berval digest;
1589 casefold = ( mr != caseExactSubstringsMatchingRule )
1590 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1592 sa = UTF8SubstringsassertionNormalize( assertValue, casefold );
1595 return LDAP_SUCCESS;
1598 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1599 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1604 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1606 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1607 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1608 /* don't bother accounting for stepping */
1609 nkeys += sa->sa_any[i].bv_len -
1610 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1615 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1616 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1622 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1623 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1624 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1627 return LDAP_SUCCESS;
1630 digest.bv_val = HASHdigest;
1631 digest.bv_len = sizeof(HASHdigest);
1633 slen = syntax->ssyn_oidlen;
1634 mlen = mr->smr_oidlen;
1636 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1639 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1640 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1642 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1643 value = &sa->sa_initial;
1645 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1646 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1648 HASH_Init( &HASHcontext );
1649 if( prefix != NULL && prefix->bv_len > 0 ) {
1650 HASH_Update( &HASHcontext,
1651 prefix->bv_val, prefix->bv_len );
1653 HASH_Update( &HASHcontext,
1654 &pre, sizeof( pre ) );
1655 HASH_Update( &HASHcontext,
1656 syntax->ssyn_oid, slen );
1657 HASH_Update( &HASHcontext,
1658 mr->smr_oid, mlen );
1659 HASH_Update( &HASHcontext,
1660 value->bv_val, klen );
1661 HASH_Final( HASHdigest, &HASHcontext );
1663 ber_dupbv( &keys[nkeys++], &digest );
1666 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1668 pre = SLAP_INDEX_SUBSTR_PREFIX;
1669 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1671 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1672 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1676 value = &sa->sa_any[i];
1679 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1680 j += SLAP_INDEX_SUBSTR_STEP )
1682 HASH_Init( &HASHcontext );
1683 if( prefix != NULL && prefix->bv_len > 0 ) {
1684 HASH_Update( &HASHcontext,
1685 prefix->bv_val, prefix->bv_len );
1687 HASH_Update( &HASHcontext,
1688 &pre, sizeof( pre ) );
1689 HASH_Update( &HASHcontext,
1690 syntax->ssyn_oid, slen );
1691 HASH_Update( &HASHcontext,
1692 mr->smr_oid, mlen );
1693 HASH_Update( &HASHcontext,
1694 &value->bv_val[j], klen );
1695 HASH_Final( HASHdigest, &HASHcontext );
1697 ber_dupbv( &keys[nkeys++], &digest );
1703 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1704 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1706 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1707 value = &sa->sa_final;
1709 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1710 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1712 HASH_Init( &HASHcontext );
1713 if( prefix != NULL && prefix->bv_len > 0 ) {
1714 HASH_Update( &HASHcontext,
1715 prefix->bv_val, prefix->bv_len );
1717 HASH_Update( &HASHcontext,
1718 &pre, sizeof( pre ) );
1719 HASH_Update( &HASHcontext,
1720 syntax->ssyn_oid, slen );
1721 HASH_Update( &HASHcontext,
1722 mr->smr_oid, mlen );
1723 HASH_Update( &HASHcontext,
1724 &value->bv_val[value->bv_len-klen], klen );
1725 HASH_Final( HASHdigest, &HASHcontext );
1727 ber_dupbv( &keys[nkeys++], &digest );
1731 keys[nkeys].bv_val = NULL;
1737 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1738 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1739 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1742 return LDAP_SUCCESS;
1751 struct berval *value,
1752 void *assertedValue )
1754 *matchp = UTF8bvnormcmp( value,
1755 (struct berval *) assertedValue,
1756 LDAP_UTF8_CASEFOLD );
1757 return LDAP_SUCCESS;
1760 /* Remove all spaces and '-' characters */
1762 telephoneNumberNormalize(
1765 struct berval *normalized )
1769 /* validator should have refused an empty string */
1770 assert( val->bv_len );
1772 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1774 for( p = val->bv_val; *p; p++ ) {
1775 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1781 normalized->bv_len = q - normalized->bv_val;
1783 if( normalized->bv_len == 0 ) {
1784 free( normalized->bv_val );
1785 return LDAP_INVALID_SYNTAX;
1788 return LDAP_SUCCESS;
1794 struct berval *val )
1798 if( val->bv_len == 0 ) {
1799 /* disallow empty strings */
1800 return LDAP_INVALID_SYNTAX;
1803 if( OID_LEADCHAR(val->bv_val[0]) ) {
1805 for(i=1; i < val->bv_len; i++) {
1806 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1807 if( dot++ ) return 1;
1808 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1811 return LDAP_INVALID_SYNTAX;
1815 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1817 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1818 for(i=1; i < val->bv_len; i++) {
1819 if( !DESC_CHAR(val->bv_val[i] ) ) {
1820 return LDAP_INVALID_SYNTAX;
1824 return LDAP_SUCCESS;
1827 return LDAP_INVALID_SYNTAX;
1836 struct berval *value,
1837 void *assertedValue )
1840 int vsign = 1, avsign = 1; /* default sign = '+' */
1841 struct berval *asserted;
1842 ber_len_t vlen, avlen;
1845 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1847 vlen = value->bv_len;
1848 if( mr == integerFirstComponentMatchingRule ) {
1849 char *tmp = memchr( v, '$', vlen );
1852 while( vlen && ASCII_SPACE( v[vlen-1] ))
1855 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) /* ANSI 2.2.1 */
1861 /* Do the same with the *assertedValue number */
1862 asserted = (struct berval *) assertedValue;
1863 av = asserted->bv_val;
1864 avlen = asserted->bv_len;
1865 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1871 match = vsign - avsign;
1873 match = (vlen != avlen
1874 ? ( vlen < avlen ? -1 : 1 )
1875 : memcmp( v, av, vlen ));
1881 return LDAP_SUCCESS;
1887 struct berval *val )
1891 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1893 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1894 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1895 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1896 return LDAP_INVALID_SYNTAX;
1899 for( i=1; i < val->bv_len; i++ ) {
1900 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1903 return LDAP_SUCCESS;
1910 struct berval *normalized )
1920 /* Ignore leading spaces */
1921 while ( len && ( *p == ' ' )) {
1928 negative = ( *p == '-' );
1929 if(( *p == '-' ) || ( *p == '+' )) {
1935 /* Ignore leading zeros */
1936 while ( len && ( *p == '0' )) {
1941 /* If there are no non-zero digits left, the number is zero, otherwise
1942 allocate space for the number and copy it into the buffer */
1944 normalized->bv_val = ch_strdup("0");
1945 normalized->bv_len = 1;
1948 normalized->bv_len = len+negative;
1949 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1951 normalized->bv_val[0] = '-';
1953 AC_MEMCPY( normalized->bv_val + negative, p, len );
1954 normalized->bv_val[len+negative] = '\0';
1957 return LDAP_SUCCESS;
1960 /* Index generation function */
1961 static int integerIndexer(
1966 struct berval *prefix,
1973 HASH_CONTEXT HASHcontext;
1974 unsigned char HASHdigest[HASH_BYTES];
1975 struct berval digest;
1976 digest.bv_val = HASHdigest;
1977 digest.bv_len = sizeof(HASHdigest);
1979 for( i=0; values[i].bv_val != NULL; i++ ) {
1980 /* empty - just count them */
1983 /* we should have at least one value at this point */
1986 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1988 slen = syntax->ssyn_oidlen;
1989 mlen = mr->smr_oidlen;
1991 for( i=0; values[i].bv_val != NULL; i++ ) {
1993 integerNormalize( syntax, &values[i], &norm );
1995 HASH_Init( &HASHcontext );
1996 if( prefix != NULL && prefix->bv_len > 0 ) {
1997 HASH_Update( &HASHcontext,
1998 prefix->bv_val, prefix->bv_len );
2000 HASH_Update( &HASHcontext,
2001 syntax->ssyn_oid, slen );
2002 HASH_Update( &HASHcontext,
2003 mr->smr_oid, mlen );
2004 HASH_Update( &HASHcontext,
2005 norm.bv_val, norm.bv_len );
2006 HASH_Final( HASHdigest, &HASHcontext );
2008 ber_dupbv( &keys[i], &digest );
2009 ch_free( norm.bv_val );
2012 keys[i].bv_val = NULL;
2014 return LDAP_SUCCESS;
2017 /* Index generation function */
2018 static int integerFilter(
2023 struct berval *prefix,
2029 HASH_CONTEXT HASHcontext;
2030 unsigned char HASHdigest[HASH_BYTES];
2032 struct berval digest;
2033 digest.bv_val = HASHdigest;
2034 digest.bv_len = sizeof(HASHdigest);
2036 slen = syntax->ssyn_oidlen;
2037 mlen = mr->smr_oidlen;
2039 integerNormalize( syntax, assertValue, &norm );
2041 keys = ch_malloc( sizeof( struct berval ) * 2 );
2043 HASH_Init( &HASHcontext );
2044 if( prefix != NULL && prefix->bv_len > 0 ) {
2045 HASH_Update( &HASHcontext,
2046 prefix->bv_val, prefix->bv_len );
2048 HASH_Update( &HASHcontext,
2049 syntax->ssyn_oid, slen );
2050 HASH_Update( &HASHcontext,
2051 mr->smr_oid, mlen );
2052 HASH_Update( &HASHcontext,
2053 norm.bv_val, norm.bv_len );
2054 HASH_Final( HASHdigest, &HASHcontext );
2056 ber_dupbv( &keys[0], &digest );
2057 keys[1].bv_val = NULL;
2058 ch_free( norm.bv_val );
2061 return LDAP_SUCCESS;
2066 countryStringValidate(
2068 struct berval *val )
2070 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2072 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2073 return LDAP_INVALID_SYNTAX;
2075 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2076 return LDAP_INVALID_SYNTAX;
2079 return LDAP_SUCCESS;
2083 printableStringValidate(
2085 struct berval *val )
2089 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2091 for(i=0; i < val->bv_len; i++) {
2092 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2093 return LDAP_INVALID_SYNTAX;
2097 return LDAP_SUCCESS;
2101 printablesStringValidate(
2103 struct berval *val )
2107 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2109 for(i=0,len=0; i < val->bv_len; i++) {
2110 int c = val->bv_val[i];
2114 return LDAP_INVALID_SYNTAX;
2118 } else if ( SLAP_PRINTABLE(c) ) {
2121 return LDAP_INVALID_SYNTAX;
2125 if( len == 0 ) LDAP_INVALID_SYNTAX;
2127 return LDAP_SUCCESS;
2133 struct berval *val )
2137 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2139 for(i=0; i < val->bv_len; i++) {
2140 if( !LDAP_ASCII(val->bv_val[i]) ) {
2141 return LDAP_INVALID_SYNTAX;
2145 return LDAP_SUCCESS;
2152 struct berval *normalized )
2156 assert( val->bv_len );
2160 /* Ignore initial whitespace */
2161 while ( ASCII_SPACE( *p ) ) {
2165 normalized->bv_val = ch_strdup( p );
2166 p = q = normalized->bv_val;
2169 if ( ASCII_SPACE( *p ) ) {
2172 /* Ignore the extra whitespace */
2173 while ( ASCII_SPACE( *p ) ) {
2181 assert( normalized->bv_val <= p );
2185 * If the string ended in space, backup the pointer one
2186 * position. One is enough because the above loop collapsed
2187 * all whitespace to a single space.
2190 if ( ASCII_SPACE( q[-1] ) ) {
2194 /* null terminate */
2197 normalized->bv_len = q - normalized->bv_val;
2199 if( normalized->bv_len == 0 ) {
2200 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
2201 normalized->bv_val[0] = ' ';
2202 normalized->bv_val[1] = '\0';
2203 normalized->bv_len = 1;
2206 return LDAP_SUCCESS;
2215 struct berval *value,
2216 void *assertedValue )
2218 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2221 match = strncmp( value->bv_val,
2222 ((struct berval *) assertedValue)->bv_val,
2227 return LDAP_SUCCESS;
2231 caseExactIA5SubstringsMatch(
2236 struct berval *value,
2237 void *assertedValue )
2240 SubstringsAssertion *sub = assertedValue;
2241 struct berval left = *value;
2245 /* Add up asserted input length */
2246 if( sub->sa_initial.bv_val ) {
2247 inlen += sub->sa_initial.bv_len;
2250 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2251 inlen += sub->sa_any[i].bv_len;
2254 if( sub->sa_final.bv_val ) {
2255 inlen += sub->sa_final.bv_len;
2258 if( sub->sa_initial.bv_val ) {
2259 if( inlen > left.bv_len ) {
2264 match = strncmp( sub->sa_initial.bv_val, left.bv_val,
2265 sub->sa_initial.bv_len );
2271 left.bv_val += sub->sa_initial.bv_len;
2272 left.bv_len -= sub->sa_initial.bv_len;
2273 inlen -= sub->sa_initial.bv_len;
2276 if( sub->sa_final.bv_val ) {
2277 if( inlen > left.bv_len ) {
2282 match = strncmp( sub->sa_final.bv_val,
2283 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2284 sub->sa_final.bv_len );
2290 left.bv_len -= sub->sa_final.bv_len;
2291 inlen -= sub->sa_final.bv_len;
2295 for(i=0; sub->sa_any[i].bv_val; i++) {
2300 if( inlen > left.bv_len ) {
2301 /* not enough length */
2306 if( sub->sa_any[i].bv_len == 0 ) {
2310 p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
2317 idx = p - left.bv_val;
2319 if( idx >= left.bv_len ) {
2320 /* this shouldn't happen */
2327 if( sub->sa_any[i].bv_len > left.bv_len ) {
2328 /* not enough left */
2333 match = strncmp( left.bv_val,
2334 sub->sa_any[i].bv_val,
2335 sub->sa_any[i].bv_len );
2343 left.bv_val += sub->sa_any[i].bv_len;
2344 left.bv_len -= sub->sa_any[i].bv_len;
2345 inlen -= sub->sa_any[i].bv_len;
2351 return LDAP_SUCCESS;
2354 /* Index generation function */
2355 static int caseExactIA5Indexer(
2360 struct berval *prefix,
2367 HASH_CONTEXT HASHcontext;
2368 unsigned char HASHdigest[HASH_BYTES];
2369 struct berval digest;
2370 digest.bv_val = HASHdigest;
2371 digest.bv_len = sizeof(HASHdigest);
2373 for( i=0; values[i].bv_val != NULL; i++ ) {
2374 /* empty - just count them */
2377 /* we should have at least one value at this point */
2380 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2382 slen = syntax->ssyn_oidlen;
2383 mlen = mr->smr_oidlen;
2385 for( i=0; values[i].bv_val != NULL; i++ ) {
2386 struct berval *value = &values[i];
2388 HASH_Init( &HASHcontext );
2389 if( prefix != NULL && prefix->bv_len > 0 ) {
2390 HASH_Update( &HASHcontext,
2391 prefix->bv_val, prefix->bv_len );
2393 HASH_Update( &HASHcontext,
2394 syntax->ssyn_oid, slen );
2395 HASH_Update( &HASHcontext,
2396 mr->smr_oid, mlen );
2397 HASH_Update( &HASHcontext,
2398 value->bv_val, value->bv_len );
2399 HASH_Final( HASHdigest, &HASHcontext );
2401 ber_dupbv( &keys[i], &digest );
2404 keys[i].bv_val = NULL;
2406 return LDAP_SUCCESS;
2409 /* Index generation function */
2410 static int caseExactIA5Filter(
2415 struct berval *prefix,
2421 HASH_CONTEXT HASHcontext;
2422 unsigned char HASHdigest[HASH_BYTES];
2423 struct berval *value;
2424 struct berval digest;
2425 digest.bv_val = HASHdigest;
2426 digest.bv_len = sizeof(HASHdigest);
2428 slen = syntax->ssyn_oidlen;
2429 mlen = mr->smr_oidlen;
2431 value = (struct berval *) assertValue;
2433 keys = ch_malloc( sizeof( struct berval ) * 2 );
2435 HASH_Init( &HASHcontext );
2436 if( prefix != NULL && prefix->bv_len > 0 ) {
2437 HASH_Update( &HASHcontext,
2438 prefix->bv_val, prefix->bv_len );
2440 HASH_Update( &HASHcontext,
2441 syntax->ssyn_oid, slen );
2442 HASH_Update( &HASHcontext,
2443 mr->smr_oid, mlen );
2444 HASH_Update( &HASHcontext,
2445 value->bv_val, value->bv_len );
2446 HASH_Final( HASHdigest, &HASHcontext );
2448 ber_dupbv( &keys[0], &digest );
2449 keys[1].bv_val = NULL;
2452 return LDAP_SUCCESS;
2455 /* Substrings Index generation function */
2456 static int caseExactIA5SubstringsIndexer(
2461 struct berval *prefix,
2468 HASH_CONTEXT HASHcontext;
2469 unsigned char HASHdigest[HASH_BYTES];
2470 struct berval digest;
2471 digest.bv_val = HASHdigest;
2472 digest.bv_len = sizeof(HASHdigest);
2474 /* we should have at least one value at this point */
2475 assert( values != NULL && values[0].bv_val != NULL );
2478 for( i=0; values[i].bv_val != NULL; i++ ) {
2479 /* count number of indices to generate */
2480 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2484 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2485 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2486 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2487 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2489 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2493 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2494 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2495 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2499 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2500 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2501 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2502 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2504 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2510 /* no keys to generate */
2512 return LDAP_SUCCESS;
2515 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2517 slen = syntax->ssyn_oidlen;
2518 mlen = mr->smr_oidlen;
2521 for( i=0; values[i].bv_val != NULL; i++ ) {
2523 struct berval *value;
2526 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2528 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2529 ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2531 char pre = SLAP_INDEX_SUBSTR_PREFIX;
2532 max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2534 for( j=0; j<max; j++ ) {
2535 HASH_Init( &HASHcontext );
2536 if( prefix != NULL && prefix->bv_len > 0 ) {
2537 HASH_Update( &HASHcontext,
2538 prefix->bv_val, prefix->bv_len );
2541 HASH_Update( &HASHcontext,
2542 &pre, sizeof( pre ) );
2543 HASH_Update( &HASHcontext,
2544 syntax->ssyn_oid, slen );
2545 HASH_Update( &HASHcontext,
2546 mr->smr_oid, mlen );
2547 HASH_Update( &HASHcontext,
2549 SLAP_INDEX_SUBSTR_MAXLEN );
2550 HASH_Final( HASHdigest, &HASHcontext );
2552 ber_dupbv( &keys[nkeys++], &digest );
2556 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2557 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2559 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2562 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2563 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2564 HASH_Init( &HASHcontext );
2565 if( prefix != NULL && prefix->bv_len > 0 ) {
2566 HASH_Update( &HASHcontext,
2567 prefix->bv_val, prefix->bv_len );
2569 HASH_Update( &HASHcontext,
2570 &pre, sizeof( pre ) );
2571 HASH_Update( &HASHcontext,
2572 syntax->ssyn_oid, slen );
2573 HASH_Update( &HASHcontext,
2574 mr->smr_oid, mlen );
2575 HASH_Update( &HASHcontext,
2577 HASH_Final( HASHdigest, &HASHcontext );
2579 ber_dupbv( &keys[nkeys++], &digest );
2582 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2583 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2584 HASH_Init( &HASHcontext );
2585 if( prefix != NULL && prefix->bv_len > 0 ) {
2586 HASH_Update( &HASHcontext,
2587 prefix->bv_val, prefix->bv_len );
2589 HASH_Update( &HASHcontext,
2590 &pre, sizeof( pre ) );
2591 HASH_Update( &HASHcontext,
2592 syntax->ssyn_oid, slen );
2593 HASH_Update( &HASHcontext,
2594 mr->smr_oid, mlen );
2595 HASH_Update( &HASHcontext,
2596 &value->bv_val[value->bv_len-j], j );
2597 HASH_Final( HASHdigest, &HASHcontext );
2599 ber_dupbv( &keys[nkeys++], &digest );
2606 keys[nkeys].bv_val = NULL;
2613 return LDAP_SUCCESS;
2616 static int caseExactIA5SubstringsFilter(
2621 struct berval *prefix,
2625 SubstringsAssertion *sa = assertValue;
2627 ber_len_t nkeys = 0;
2628 size_t slen, mlen, klen;
2630 HASH_CONTEXT HASHcontext;
2631 unsigned char HASHdigest[HASH_BYTES];
2632 struct berval *value;
2633 struct berval digest;
2635 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2636 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2641 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2643 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2644 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2645 /* don't bother accounting for stepping */
2646 nkeys += sa->sa_any[i].bv_len -
2647 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2652 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2653 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2660 return LDAP_SUCCESS;
2663 digest.bv_val = HASHdigest;
2664 digest.bv_len = sizeof(HASHdigest);
2666 slen = syntax->ssyn_oidlen;
2667 mlen = mr->smr_oidlen;
2669 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2672 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2673 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2675 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2676 value = &sa->sa_initial;
2678 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2679 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2681 HASH_Init( &HASHcontext );
2682 if( prefix != NULL && prefix->bv_len > 0 ) {
2683 HASH_Update( &HASHcontext,
2684 prefix->bv_val, prefix->bv_len );
2686 HASH_Update( &HASHcontext,
2687 &pre, sizeof( pre ) );
2688 HASH_Update( &HASHcontext,
2689 syntax->ssyn_oid, slen );
2690 HASH_Update( &HASHcontext,
2691 mr->smr_oid, mlen );
2692 HASH_Update( &HASHcontext,
2693 value->bv_val, klen );
2694 HASH_Final( HASHdigest, &HASHcontext );
2696 ber_dupbv( &keys[nkeys++], &digest );
2699 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2701 pre = SLAP_INDEX_SUBSTR_PREFIX;
2702 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2704 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2705 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2709 value = &sa->sa_any[i];
2712 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2713 j += SLAP_INDEX_SUBSTR_STEP )
2715 HASH_Init( &HASHcontext );
2716 if( prefix != NULL && prefix->bv_len > 0 ) {
2717 HASH_Update( &HASHcontext,
2718 prefix->bv_val, prefix->bv_len );
2720 HASH_Update( &HASHcontext,
2721 &pre, sizeof( pre ) );
2722 HASH_Update( &HASHcontext,
2723 syntax->ssyn_oid, slen );
2724 HASH_Update( &HASHcontext,
2725 mr->smr_oid, mlen );
2726 HASH_Update( &HASHcontext,
2727 &value->bv_val[j], klen );
2728 HASH_Final( HASHdigest, &HASHcontext );
2730 ber_dupbv( &keys[nkeys++], &digest );
2735 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2736 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2738 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2739 value = &sa->sa_final;
2741 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2742 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2744 HASH_Init( &HASHcontext );
2745 if( prefix != NULL && prefix->bv_len > 0 ) {
2746 HASH_Update( &HASHcontext,
2747 prefix->bv_val, prefix->bv_len );
2749 HASH_Update( &HASHcontext,
2750 &pre, sizeof( pre ) );
2751 HASH_Update( &HASHcontext,
2752 syntax->ssyn_oid, slen );
2753 HASH_Update( &HASHcontext,
2754 mr->smr_oid, mlen );
2755 HASH_Update( &HASHcontext,
2756 &value->bv_val[value->bv_len-klen], klen );
2757 HASH_Final( HASHdigest, &HASHcontext );
2759 ber_dupbv( &keys[nkeys++], &digest );
2763 keys[nkeys].bv_val = NULL;
2770 return LDAP_SUCCESS;
2779 struct berval *value,
2780 void *assertedValue )
2782 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2784 if( match == 0 && value->bv_len ) {
2785 match = strncasecmp( value->bv_val,
2786 ((struct berval *) assertedValue)->bv_val,
2791 return LDAP_SUCCESS;
2795 caseIgnoreIA5SubstringsMatch(
2800 struct berval *value,
2801 void *assertedValue )
2804 SubstringsAssertion *sub = assertedValue;
2805 struct berval left = *value;
2809 /* Add up asserted input length */
2810 if( sub->sa_initial.bv_val ) {
2811 inlen += sub->sa_initial.bv_len;
2814 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2815 inlen += sub->sa_any[i].bv_len;
2818 if( sub->sa_final.bv_val ) {
2819 inlen += sub->sa_final.bv_len;
2822 if( sub->sa_initial.bv_val ) {
2823 if( inlen > left.bv_len ) {
2828 match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
2829 sub->sa_initial.bv_len );
2835 left.bv_val += sub->sa_initial.bv_len;
2836 left.bv_len -= sub->sa_initial.bv_len;
2837 inlen -= sub->sa_initial.bv_len;
2840 if( sub->sa_final.bv_val ) {
2841 if( inlen > left.bv_len ) {
2846 match = strncasecmp( sub->sa_final.bv_val,
2847 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2848 sub->sa_final.bv_len );
2854 left.bv_len -= sub->sa_final.bv_len;
2855 inlen -= sub->sa_final.bv_len;
2859 for(i=0; sub->sa_any[i].bv_val; i++) {
2864 if( inlen > left.bv_len ) {
2865 /* not enough length */
2870 if( sub->sa_any[i].bv_len == 0 ) {
2874 p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
2881 assert( idx < left.bv_len );
2882 if( idx >= left.bv_len ) {
2883 /* this shouldn't happen */
2890 if( sub->sa_any[i].bv_len > left.bv_len ) {
2891 /* not enough left */
2896 match = strncasecmp( left.bv_val,
2897 sub->sa_any[i].bv_val,
2898 sub->sa_any[i].bv_len );
2907 left.bv_val += sub->sa_any[i].bv_len;
2908 left.bv_len -= sub->sa_any[i].bv_len;
2909 inlen -= sub->sa_any[i].bv_len;
2915 return LDAP_SUCCESS;
2918 /* Index generation function */
2919 static int caseIgnoreIA5Indexer(
2924 struct berval *prefix,
2929 int rc = LDAP_SUCCESS;
2932 HASH_CONTEXT HASHcontext;
2933 unsigned char HASHdigest[HASH_BYTES];
2934 struct berval digest;
2935 digest.bv_val = HASHdigest;
2936 digest.bv_len = sizeof(HASHdigest);
2938 /* we should have at least one value at this point */
2939 assert( values != NULL && values[0].bv_val != NULL );
2941 for( i=0; values[i].bv_val != NULL; i++ ) {
2942 /* just count them */
2945 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2947 slen = syntax->ssyn_oidlen;
2948 mlen = mr->smr_oidlen;
2950 for( i=0; values[i].bv_val != NULL; i++ ) {
2951 struct berval value;
2953 if( mr->smr_normalize ) {
2954 rc = (mr->smr_normalize)( use, syntax, mr, &values[i], &value );
2955 if( rc != LDAP_SUCCESS ) {
2958 } else if ( mr->smr_syntax->ssyn_normalize ) {
2959 rc = (mr->smr_syntax->ssyn_normalize)( syntax, &values[i], &value );
2960 if( rc != LDAP_SUCCESS ) {
2964 ber_dupbv( &value, &values[i] );
2967 ldap_pvt_str2lower( value.bv_val );
2969 HASH_Init( &HASHcontext );
2970 if( prefix != NULL && prefix->bv_len > 0 ) {
2971 HASH_Update( &HASHcontext,
2972 prefix->bv_val, prefix->bv_len );
2974 HASH_Update( &HASHcontext,
2975 syntax->ssyn_oid, slen );
2976 HASH_Update( &HASHcontext,
2977 mr->smr_oid, mlen );
2978 HASH_Update( &HASHcontext,
2979 value.bv_val, value.bv_len );
2980 HASH_Final( HASHdigest, &HASHcontext );
2982 free( value.bv_val );
2984 ber_dupbv( &keys[i], &digest );
2987 keys[i].bv_val = NULL;
2988 if( rc != LDAP_SUCCESS ) {
2989 ber_bvarray_free( keys );
2996 /* Index generation function */
2997 static int caseIgnoreIA5Filter(
3002 struct berval *prefix,
3008 HASH_CONTEXT HASHcontext;
3009 unsigned char HASHdigest[HASH_BYTES];
3010 struct berval value;
3011 struct berval digest;
3012 digest.bv_val = HASHdigest;
3013 digest.bv_len = sizeof(HASHdigest);
3015 slen = syntax->ssyn_oidlen;
3016 mlen = mr->smr_oidlen;
3018 ber_dupbv( &value, (struct berval *) assertValue );
3019 ldap_pvt_str2lower( value.bv_val );
3021 keys = ch_malloc( sizeof( struct berval ) * 2 );
3023 HASH_Init( &HASHcontext );
3024 if( prefix != NULL && prefix->bv_len > 0 ) {
3025 HASH_Update( &HASHcontext,
3026 prefix->bv_val, prefix->bv_len );
3028 HASH_Update( &HASHcontext,
3029 syntax->ssyn_oid, slen );
3030 HASH_Update( &HASHcontext,
3031 mr->smr_oid, mlen );
3032 HASH_Update( &HASHcontext,
3033 value.bv_val, value.bv_len );
3034 HASH_Final( HASHdigest, &HASHcontext );
3036 ber_dupbv( &keys[0], &digest );
3037 keys[1].bv_val = NULL;
3039 free( value.bv_val );
3043 return LDAP_SUCCESS;
3046 /* Substrings Index generation function */
3047 static int caseIgnoreIA5SubstringsIndexer(
3052 struct berval *prefix,
3059 HASH_CONTEXT HASHcontext;
3060 unsigned char HASHdigest[HASH_BYTES];
3061 struct berval digest;
3062 digest.bv_val = HASHdigest;
3063 digest.bv_len = sizeof(HASHdigest);
3065 /* we should have at least one value at this point */
3066 assert( values != NULL && values[0].bv_val != NULL );
3069 for( i=0; values[i].bv_val != NULL; i++ ) {
3070 /* count number of indices to generate */
3071 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3075 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3076 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3077 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3078 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3080 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3084 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3085 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3086 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3090 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3091 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3092 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3093 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3095 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3101 /* no keys to generate */
3103 return LDAP_SUCCESS;
3106 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3108 slen = syntax->ssyn_oidlen;
3109 mlen = mr->smr_oidlen;
3112 for( i=0; values[i].bv_val != NULL; i++ ) {
3114 struct berval value;
3116 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3118 ber_dupbv( &value, &values[i] );
3119 ldap_pvt_str2lower( value.bv_val );
3121 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3122 ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3124 char pre = SLAP_INDEX_SUBSTR_PREFIX;
3125 max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3127 for( j=0; j<max; j++ ) {
3128 HASH_Init( &HASHcontext );
3129 if( prefix != NULL && prefix->bv_len > 0 ) {
3130 HASH_Update( &HASHcontext,
3131 prefix->bv_val, prefix->bv_len );
3134 HASH_Update( &HASHcontext,
3135 &pre, sizeof( pre ) );
3136 HASH_Update( &HASHcontext,
3137 syntax->ssyn_oid, slen );
3138 HASH_Update( &HASHcontext,
3139 mr->smr_oid, mlen );
3140 HASH_Update( &HASHcontext,
3142 SLAP_INDEX_SUBSTR_MAXLEN );
3143 HASH_Final( HASHdigest, &HASHcontext );
3145 ber_dupbv( &keys[nkeys++], &digest );
3149 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3150 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3152 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3155 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3156 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3157 HASH_Init( &HASHcontext );
3158 if( prefix != NULL && prefix->bv_len > 0 ) {
3159 HASH_Update( &HASHcontext,
3160 prefix->bv_val, prefix->bv_len );
3162 HASH_Update( &HASHcontext,
3163 &pre, sizeof( pre ) );
3164 HASH_Update( &HASHcontext,
3165 syntax->ssyn_oid, slen );
3166 HASH_Update( &HASHcontext,
3167 mr->smr_oid, mlen );
3168 HASH_Update( &HASHcontext,
3170 HASH_Final( HASHdigest, &HASHcontext );
3172 ber_dupbv( &keys[nkeys++], &digest );
3175 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3176 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3177 HASH_Init( &HASHcontext );
3178 if( prefix != NULL && prefix->bv_len > 0 ) {
3179 HASH_Update( &HASHcontext,
3180 prefix->bv_val, prefix->bv_len );
3182 HASH_Update( &HASHcontext,
3183 &pre, sizeof( pre ) );
3184 HASH_Update( &HASHcontext,
3185 syntax->ssyn_oid, slen );
3186 HASH_Update( &HASHcontext,
3187 mr->smr_oid, mlen );
3188 HASH_Update( &HASHcontext,
3189 &value.bv_val[value.bv_len-j], j );
3190 HASH_Final( HASHdigest, &HASHcontext );
3192 ber_dupbv( &keys[nkeys++], &digest );
3197 free( value.bv_val );
3201 keys[nkeys].bv_val = NULL;
3208 return LDAP_SUCCESS;
3211 static int caseIgnoreIA5SubstringsFilter(
3216 struct berval *prefix,
3220 SubstringsAssertion *sa = assertValue;
3222 ber_len_t nkeys = 0;
3223 size_t slen, mlen, klen;
3225 HASH_CONTEXT HASHcontext;
3226 unsigned char HASHdigest[HASH_BYTES];
3227 struct berval value;
3228 struct berval digest;
3230 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3231 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3236 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3238 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3239 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3240 /* don't bother accounting for stepping */
3241 nkeys += sa->sa_any[i].bv_len -
3242 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3247 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3248 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3255 return LDAP_SUCCESS;
3258 digest.bv_val = HASHdigest;
3259 digest.bv_len = sizeof(HASHdigest);
3261 slen = syntax->ssyn_oidlen;
3262 mlen = mr->smr_oidlen;
3264 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3267 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3268 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3270 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3271 ber_dupbv( &value, &sa->sa_initial );
3272 ldap_pvt_str2lower( value.bv_val );
3274 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3275 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3277 HASH_Init( &HASHcontext );
3278 if( prefix != NULL && prefix->bv_len > 0 ) {
3279 HASH_Update( &HASHcontext,
3280 prefix->bv_val, prefix->bv_len );
3282 HASH_Update( &HASHcontext,
3283 &pre, sizeof( pre ) );
3284 HASH_Update( &HASHcontext,
3285 syntax->ssyn_oid, slen );
3286 HASH_Update( &HASHcontext,
3287 mr->smr_oid, mlen );
3288 HASH_Update( &HASHcontext,
3289 value.bv_val, klen );
3290 HASH_Final( HASHdigest, &HASHcontext );
3292 free( value.bv_val );
3293 ber_dupbv( &keys[nkeys++], &digest );
3296 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3298 pre = SLAP_INDEX_SUBSTR_PREFIX;
3299 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3301 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3302 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3306 ber_dupbv( &value, &sa->sa_any[i] );
3307 ldap_pvt_str2lower( value.bv_val );
3310 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3311 j += SLAP_INDEX_SUBSTR_STEP )
3313 HASH_Init( &HASHcontext );
3314 if( prefix != NULL && prefix->bv_len > 0 ) {
3315 HASH_Update( &HASHcontext,
3316 prefix->bv_val, prefix->bv_len );
3318 HASH_Update( &HASHcontext,
3319 &pre, sizeof( pre ) );
3320 HASH_Update( &HASHcontext,
3321 syntax->ssyn_oid, slen );
3322 HASH_Update( &HASHcontext,
3323 mr->smr_oid, mlen );
3324 HASH_Update( &HASHcontext,
3325 &value.bv_val[j], klen );
3326 HASH_Final( HASHdigest, &HASHcontext );
3328 ber_dupbv( &keys[nkeys++], &digest );
3331 free( value.bv_val );
3335 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3336 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3338 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3339 ber_dupbv( &value, &sa->sa_final );
3340 ldap_pvt_str2lower( value.bv_val );
3342 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3343 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3345 HASH_Init( &HASHcontext );
3346 if( prefix != NULL && prefix->bv_len > 0 ) {
3347 HASH_Update( &HASHcontext,
3348 prefix->bv_val, prefix->bv_len );
3350 HASH_Update( &HASHcontext,
3351 &pre, sizeof( pre ) );
3352 HASH_Update( &HASHcontext,
3353 syntax->ssyn_oid, slen );
3354 HASH_Update( &HASHcontext,
3355 mr->smr_oid, mlen );
3356 HASH_Update( &HASHcontext,
3357 &value.bv_val[value.bv_len-klen], klen );
3358 HASH_Final( HASHdigest, &HASHcontext );
3360 free( value.bv_val );
3361 ber_dupbv( &keys[nkeys++], &digest );
3365 keys[nkeys].bv_val = NULL;
3372 return LDAP_SUCCESS;
3376 numericStringValidate(
3382 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
3384 for(i=0; i < in->bv_len; i++) {
3385 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3386 return LDAP_INVALID_SYNTAX;
3390 return LDAP_SUCCESS;
3394 numericStringNormalize(
3397 struct berval *normalized )
3399 /* removal all spaces */
3402 assert( val->bv_len );
3404 normalized->bv_val = ch_malloc( val->bv_len + 1 );
3407 q = normalized->bv_val;
3410 if ( ASCII_SPACE( *p ) ) {
3411 /* Ignore whitespace */
3418 /* we should have copied no more then is in val */
3419 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3421 /* null terminate */
3424 normalized->bv_len = q - normalized->bv_val;
3426 if( normalized->bv_len == 0 ) {
3427 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
3428 normalized->bv_val[0] = ' ';
3429 normalized->bv_val[1] = '\0';
3430 normalized->bv_len = 1;
3433 return LDAP_SUCCESS;
3437 objectIdentifierFirstComponentMatch(
3442 struct berval *value,
3443 void *assertedValue )
3445 int rc = LDAP_SUCCESS;
3447 struct berval *asserted = (struct berval *) assertedValue;
3451 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3452 return LDAP_INVALID_SYNTAX;
3455 /* trim leading white space */
3456 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3460 /* grab next word */
3461 oid.bv_val = &value->bv_val[i];
3462 oid.bv_len = value->bv_len - i;
3463 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
3468 /* insert attributeTypes, objectclass check here */
3469 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3470 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3473 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3474 MatchingRule *asserted_mr = mr_bvfind( asserted );
3475 MatchingRule *stored_mr = mr_bvfind( &oid );
3477 if( asserted_mr == NULL ) {
3478 rc = SLAPD_COMPARE_UNDEFINED;
3480 match = asserted_mr != stored_mr;
3483 } else if ( !strcmp( syntax->ssyn_oid,
3484 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3486 AttributeType *asserted_at = at_bvfind( asserted );
3487 AttributeType *stored_at = at_bvfind( &oid );
3489 if( asserted_at == NULL ) {
3490 rc = SLAPD_COMPARE_UNDEFINED;
3492 match = asserted_at != stored_at;
3495 } else if ( !strcmp( syntax->ssyn_oid,
3496 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3498 ObjectClass *asserted_oc = oc_bvfind( asserted );
3499 ObjectClass *stored_oc = oc_bvfind( &oid );
3501 if( asserted_oc == NULL ) {
3502 rc = SLAPD_COMPARE_UNDEFINED;
3504 match = asserted_oc != stored_oc;
3510 LDAP_LOG( CONFIG, ENTRY,
3511 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
3512 match, value->bv_val, asserted->bv_val );
3514 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3515 "%d\n\t\"%s\"\n\t\"%s\"\n",
3516 match, value->bv_val, asserted->bv_val );
3520 if( rc == LDAP_SUCCESS ) *matchp = match;
3530 struct berval *value,
3531 void *assertedValue )
3533 long lValue, lAssertedValue;
3535 /* safe to assume integers are NUL terminated? */
3536 lValue = strtoul(value->bv_val, NULL, 10);
3537 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3538 return LDAP_CONSTRAINT_VIOLATION;
3540 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3541 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3542 return LDAP_CONSTRAINT_VIOLATION;
3544 *matchp = (lValue & lAssertedValue);
3545 return LDAP_SUCCESS;
3554 struct berval *value,
3555 void *assertedValue )
3557 long lValue, lAssertedValue;
3559 /* safe to assume integers are NUL terminated? */
3560 lValue = strtoul(value->bv_val, NULL, 10);
3561 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
3562 return LDAP_CONSTRAINT_VIOLATION;
3564 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3565 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
3566 return LDAP_CONSTRAINT_VIOLATION;
3568 *matchp = (lValue | lAssertedValue);
3569 return LDAP_SUCCESS;
3573 #include <openssl/x509.h>
3574 #include <openssl/err.h>
3575 char digit[] = "0123456789";
3578 * Next function returns a string representation of a ASN1_INTEGER.
3579 * It works for unlimited lengths.
3582 static struct berval *
3583 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3588 /* We work backwards, make it fill from the end of buf */
3589 p = buf + sizeof(buf) - 1;
3592 if ( a == NULL || a->length == 0 ) {
3600 /* We want to preserve the original */
3601 copy = ch_malloc(n*sizeof(unsigned int));
3602 for (i = 0; i<n; i++) {
3603 copy[i] = a->data[i];
3607 * base indicates the index of the most significant
3608 * byte that might be nonzero. When it goes off the
3609 * end, we now there is nothing left to do.
3615 for (i = base; i<n; i++ ) {
3616 copy[i] += carry*256;
3617 carry = copy[i] % 10;
3622 * Way too large, we need to leave
3623 * room for sign if negative
3628 *--p = digit[carry];
3629 if (copy[base] == 0)
3635 if ( a->type == V_ASN1_NEG_INTEGER ) {
3639 return ber_str2bv( p, 0, 1, bv );
3643 * Given a certificate in DER format, extract the corresponding
3644 * assertion value for certificateExactMatch
3647 certificateExactConvert(
3649 struct berval * out )
3652 unsigned char *p = in->bv_val;
3653 struct berval serial;
3654 struct berval issuer_dn;
3656 xcert = d2i_X509(NULL, &p, in->bv_len);
3659 LDAP_LOG( CONFIG, ENTRY,
3660 "certificateExactConvert: error parsing cert: %s\n",
3661 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3663 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3664 "error parsing cert: %s\n",
3665 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3667 return LDAP_INVALID_SYNTAX;
3670 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3672 return LDAP_INVALID_SYNTAX;
3674 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn ) != LDAP_SUCCESS ) {
3676 ber_memfree(serial.bv_val);
3677 return LDAP_INVALID_SYNTAX;
3682 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3683 out->bv_val = ch_malloc(out->bv_len);
3685 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3687 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3689 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3690 p += issuer_dn.bv_len;
3694 LDAP_LOG( CONFIG, ARGS,
3695 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
3697 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3699 out->bv_val, NULL, NULL );
3702 ber_memfree(serial.bv_val);
3703 ber_memfree(issuer_dn.bv_val);
3705 return LDAP_SUCCESS;
3709 serial_and_issuer_parse(
3710 struct berval *assertion,
3711 struct berval *serial,
3712 struct berval *issuer_dn
3720 begin = assertion->bv_val;
3721 end = assertion->bv_val+assertion->bv_len-1;
3722 for (p=begin; p<=end && *p != '$'; p++)
3725 return LDAP_INVALID_SYNTAX;
3727 /* p now points at the $ sign, now use begin and end to delimit the
3729 while (ASCII_SPACE(*begin))
3732 while (ASCII_SPACE(*end))
3735 bv.bv_len = end-begin+1;
3737 ber_dupbv(serial, &bv);
3739 /* now extract the issuer, remember p was at the dollar sign */
3742 end = assertion->bv_val+assertion->bv_len-1;
3743 while (ASCII_SPACE(*begin))
3745 /* should we trim spaces at the end too? is it safe always? */
3747 bv.bv_len = end-begin+1;
3749 dnNormalize2( NULL, &bv, issuer_dn );
3752 return LDAP_SUCCESS;
3756 certificateExactMatch(
3761 struct berval *value,
3762 void *assertedValue )
3765 unsigned char *p = value->bv_val;
3766 struct berval serial;
3767 struct berval issuer_dn;
3768 struct berval asserted_serial;
3769 struct berval asserted_issuer_dn;
3772 xcert = d2i_X509(NULL, &p, value->bv_len);
3775 LDAP_LOG( CONFIG, ENTRY,
3776 "certificateExactMatch: error parsing cert: %s\n",
3777 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3779 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3780 "error parsing cert: %s\n",
3781 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3783 return LDAP_INVALID_SYNTAX;
3786 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3787 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
3791 serial_and_issuer_parse(assertedValue,
3793 &asserted_issuer_dn);
3798 slap_schema.si_syn_integer,
3799 slap_schema.si_mr_integerMatch,
3802 if ( ret == LDAP_SUCCESS ) {
3803 if ( *matchp == 0 ) {
3804 /* We need to normalize everything for dnMatch */
3808 slap_schema.si_syn_distinguishedName,
3809 slap_schema.si_mr_distinguishedNameMatch,
3811 &asserted_issuer_dn);
3816 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
3817 "%d\n\t\"%s $ %s\"\n",
3818 *matchp, serial.bv_val, issuer_dn.bv_val );
3819 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
3820 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3823 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3824 "%d\n\t\"%s $ %s\"\n",
3825 *matchp, serial.bv_val, issuer_dn.bv_val );
3826 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3827 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3831 ber_memfree(serial.bv_val);
3832 ber_memfree(issuer_dn.bv_val);
3833 ber_memfree(asserted_serial.bv_val);
3834 ber_memfree(asserted_issuer_dn.bv_val);
3840 * Index generation function
3841 * We just index the serials, in most scenarios the issuer DN is one of
3842 * a very small set of values.
3844 static int certificateExactIndexer(
3849 struct berval *prefix,
3857 struct berval serial;
3859 /* we should have at least one value at this point */
3860 assert( values != NULL && values[0].bv_val != NULL );
3862 for( i=0; values[i].bv_val != NULL; i++ ) {
3863 /* empty -- just count them */
3866 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3868 for( i=0; values[i].bv_val != NULL; i++ ) {
3869 p = values[i].bv_val;
3870 xcert = d2i_X509(NULL, &p, values[i].bv_len);
3873 LDAP_LOG( CONFIG, ENTRY,
3874 "certificateExactIndexer: error parsing cert: %s\n",
3875 ERR_error_string(ERR_get_error(),NULL), 0, 0);
3877 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3878 "error parsing cert: %s\n",
3879 ERR_error_string(ERR_get_error(),NULL),
3882 /* Do we leak keys on error? */
3883 return LDAP_INVALID_SYNTAX;
3886 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3888 integerNormalize( slap_schema.si_syn_integer,
3891 ber_memfree(serial.bv_val);
3893 LDAP_LOG( CONFIG, ENTRY,
3894 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
3896 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3903 keys[i].bv_val = NULL;
3905 return LDAP_SUCCESS;
3908 /* Index generation function */
3909 /* We think this is always called with a value in matching rule syntax */
3910 static int certificateExactFilter(
3915 struct berval *prefix,
3920 struct berval asserted_serial;
3922 serial_and_issuer_parse(assertValue,
3926 keys = ch_malloc( sizeof( struct berval ) * 2 );
3927 integerNormalize( syntax, &asserted_serial, &keys[0] );
3928 keys[1].bv_val = NULL;
3931 ber_memfree(asserted_serial.bv_val);
3932 return LDAP_SUCCESS;
3937 check_time_syntax (struct berval *val,
3941 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3942 static int mdays[2][12] = {
3943 /* non-leap years */
3944 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
3946 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
3949 int part, c, tzoffset, leapyear = 0 ;
3951 if( val->bv_len == 0 ) {
3952 return LDAP_INVALID_SYNTAX;
3955 p = (char *)val->bv_val;
3956 e = p + val->bv_len;
3958 /* Ignore initial whitespace */
3959 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
3963 if (e - p < 13 - (2 * start)) {
3964 return LDAP_INVALID_SYNTAX;
3967 for (part = 0; part < 9; part++) {
3971 for (part = start; part < 7; part++) {
3973 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
3980 return LDAP_INVALID_SYNTAX;
3982 if (c < 0 || c > 9) {
3983 return LDAP_INVALID_SYNTAX;
3989 return LDAP_INVALID_SYNTAX;
3991 if (c < 0 || c > 9) {
3992 return LDAP_INVALID_SYNTAX;
3997 if (part == 2 || part == 3) {
4000 if (parts[part] < 0) {
4001 return LDAP_INVALID_SYNTAX;
4003 if (parts[part] > ceiling[part]) {
4004 return LDAP_INVALID_SYNTAX;
4008 /* leapyear check for the Gregorian calendar (year>1581) */
4009 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
4010 ((parts[0] % 4 == 0) && (parts[1] == 0)))
4015 if (parts[3] > mdays[leapyear][parts[2]]) {
4016 return LDAP_INVALID_SYNTAX;
4021 tzoffset = 0; /* UTC */
4022 } else if (c != '+' && c != '-') {
4023 return LDAP_INVALID_SYNTAX;
4027 } else /* c == '+' */ {
4032 return LDAP_INVALID_SYNTAX;
4035 for (part = 7; part < 9; part++) {
4037 if (c < 0 || c > 9) {
4038 return LDAP_INVALID_SYNTAX;
4043 if (c < 0 || c > 9) {
4044 return LDAP_INVALID_SYNTAX;
4048 if (parts[part] < 0 || parts[part] > ceiling[part]) {
4049 return LDAP_INVALID_SYNTAX;
4054 /* Ignore trailing whitespace */
4055 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4059 return LDAP_INVALID_SYNTAX;
4062 switch ( tzoffset ) {
4063 case -1: /* negativ offset to UTC, ie west of Greenwich */
4064 parts[4] += parts[7];
4065 parts[5] += parts[8];
4066 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4070 c = mdays[leapyear][parts[2]];
4072 if (parts[part] > c) {
4073 parts[part] -= c + 1;
4078 case 1: /* positive offset to UTC, ie east of Greenwich */
4079 parts[4] -= parts[7];
4080 parts[5] -= parts[8];
4081 for (part = 6; --part > 0; ) {
4085 /* first arg to % needs to be non negativ */
4086 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4088 if (parts[part] < 0) {
4089 parts[part] += c + 1;
4094 case 0: /* already UTC */
4098 return LDAP_SUCCESS;
4101 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4106 struct berval *normalized )
4110 rc = check_time_syntax(val, 1, parts);
4111 if (rc != LDAP_SUCCESS) {
4115 normalized->bv_val = ch_malloc( 14 );
4116 if ( normalized->bv_val == NULL ) {
4117 return LBER_ERROR_MEMORY;
4120 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4121 parts[1], parts[2] + 1, parts[3] + 1,
4122 parts[4], parts[5], parts[6] );
4123 normalized->bv_len = 13;
4125 return LDAP_SUCCESS;
4129 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4137 return check_time_syntax(in, 1, parts);
4142 generalizedTimeValidate(
4148 return check_time_syntax(in, 0, parts);
4152 generalizedTimeNormalize(
4155 struct berval *normalized )
4159 rc = check_time_syntax(val, 0, parts);
4160 if (rc != LDAP_SUCCESS) {
4164 normalized->bv_val = ch_malloc( 16 );
4165 if ( normalized->bv_val == NULL ) {
4166 return LBER_ERROR_MEMORY;
4169 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4170 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4171 parts[4], parts[5], parts[6] );
4172 normalized->bv_len = 15;
4174 return LDAP_SUCCESS;
4178 nisNetgroupTripleValidate(
4180 struct berval *val )
4185 if ( val->bv_len == 0 ) {
4186 return LDAP_INVALID_SYNTAX;
4189 p = (char *)val->bv_val;
4190 e = p + val->bv_len;
4192 if ( *p != '(' /*')'*/ ) {
4193 return LDAP_INVALID_SYNTAX;
4196 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4200 return LDAP_INVALID_SYNTAX;
4203 } else if ( !AD_CHAR( *p ) ) {
4204 return LDAP_INVALID_SYNTAX;
4208 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4209 return LDAP_INVALID_SYNTAX;
4215 return LDAP_INVALID_SYNTAX;
4218 return LDAP_SUCCESS;
4222 bootParameterValidate(
4224 struct berval *val )
4228 if ( val->bv_len == 0 ) {
4229 return LDAP_INVALID_SYNTAX;
4232 p = (char *)val->bv_val;
4233 e = p + val->bv_len;
4236 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4237 if ( !AD_CHAR( *p ) ) {
4238 return LDAP_INVALID_SYNTAX;
4243 return LDAP_INVALID_SYNTAX;
4247 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4248 if ( !AD_CHAR( *p ) ) {
4249 return LDAP_INVALID_SYNTAX;
4254 return LDAP_INVALID_SYNTAX;
4258 for ( p++; p < e; p++ ) {
4259 if ( !SLAP_PRINTABLE( *p ) ) {
4260 return LDAP_INVALID_SYNTAX;
4264 return LDAP_SUCCESS;
4267 static struct syntax_defs_rec {
4269 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4270 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4272 slap_syntax_validate_func *sd_validate;
4273 slap_syntax_transform_func *sd_normalize;
4274 slap_syntax_transform_func *sd_pretty;
4275 #ifdef SLAPD_BINARY_CONVERSION
4276 slap_syntax_transform_func *sd_ber2str;
4277 slap_syntax_transform_func *sd_str2ber;
4280 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4281 X_BINARY X_NOT_H_R ")",
4282 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4283 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4284 0, NULL, NULL, NULL},
4285 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4286 0, NULL, NULL, NULL},
4287 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4289 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4290 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4292 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4293 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4294 0, bitStringValidate, bitStringNormalize, NULL },
4295 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4296 0, booleanValidate, NULL, NULL},
4297 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4298 X_BINARY X_NOT_H_R ")",
4299 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4300 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4301 X_BINARY X_NOT_H_R ")",
4302 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4303 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4304 X_BINARY X_NOT_H_R ")",
4305 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4306 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4307 0, countryStringValidate, IA5StringNormalize, NULL},
4308 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4309 0, dnValidate, dnNormalize2, dnPretty2},
4310 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4311 0, NULL, NULL, NULL},
4312 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4313 0, NULL, NULL, NULL},
4314 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4315 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4316 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4317 0, NULL, NULL, NULL},
4318 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4319 0, NULL, NULL, NULL},
4320 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4321 0, NULL, NULL, NULL},
4322 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4323 0, NULL, NULL, NULL},
4324 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4325 0, NULL, NULL, NULL},
4326 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4327 0, printablesStringValidate, telephoneNumberNormalize, NULL},
4328 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4329 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4330 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4331 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
4332 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4333 0, NULL, NULL, NULL},
4334 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4335 0, IA5StringValidate, IA5StringNormalize, NULL},
4336 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4337 0, integerValidate, integerNormalize, NULL},
4338 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4339 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4340 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4341 0, NULL, NULL, NULL},
4342 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4343 0, NULL, NULL, NULL},
4344 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4345 0, NULL, NULL, NULL},
4346 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4347 0, NULL, NULL, NULL},
4348 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4349 0, NULL, NULL, NULL},
4350 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4351 0, nameUIDValidate, nameUIDNormalize, NULL},
4352 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4353 0, NULL, NULL, NULL},
4354 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4355 0, numericStringValidate, numericStringNormalize, NULL},
4356 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4357 0, NULL, NULL, NULL},
4358 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4359 0, oidValidate, NULL, NULL},
4360 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4361 0, IA5StringValidate, IA5StringNormalize, NULL},
4362 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4363 0, blobValidate, NULL, NULL},
4364 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4365 0, UTF8StringValidate, UTF8StringNormalize, NULL},
4366 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4367 0, NULL, NULL, NULL},
4368 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4369 0, NULL, NULL, NULL},
4370 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4371 0, printableStringValidate, IA5StringNormalize, NULL},
4372 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4373 X_BINARY X_NOT_H_R ")",
4374 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4375 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4376 X_BINARY X_NOT_H_R ")",
4377 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4378 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4379 0, printableStringValidate, telephoneNumberNormalize, NULL},
4380 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4381 0, NULL, NULL, NULL},
4382 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4383 0, printablesStringValidate, IA5StringNormalize, NULL},
4384 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4385 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4386 0, utcTimeValidate, utcTimeNormalize, NULL},
4388 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4389 0, NULL, NULL, NULL},
4390 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4391 0, NULL, NULL, NULL},
4392 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4393 0, NULL, NULL, NULL},
4394 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4395 0, NULL, NULL, NULL},
4396 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4397 0, NULL, NULL, NULL},
4399 /* RFC 2307 NIS Syntaxes */
4400 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4401 0, nisNetgroupTripleValidate, NULL, NULL},
4402 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4403 0, bootParameterValidate, NULL, NULL},
4407 /* These OIDs are not published yet, but will be in the next
4408 * I-D for PKIX LDAPv3 schema as have been advanced by David
4409 * Chadwick in private mail.
4411 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4412 0, NULL, NULL, NULL},
4415 /* OpenLDAP Experimental Syntaxes */
4416 #ifdef SLAPD_ACI_ENABLED
4417 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4419 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4423 #ifdef SLAPD_AUTHPASSWD
4424 /* needs updating */
4425 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4426 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4429 /* OpenLDAP Void Syntax */
4430 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4431 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4432 {NULL, 0, NULL, NULL, NULL}
4436 * Other matching rules in X.520 that we do not use (yet):
4438 * 2.5.13.9 numericStringOrderingMatch
4439 * 2.5.13.18 octetStringOrderingMatch
4440 * 2.5.13.19 octetStringSubstringsMatch
4441 * 2.5.13.25 uTCTimeMatch
4442 * 2.5.13.26 uTCTimeOrderingMatch
4443 * 2.5.13.31 directoryStringFirstComponentMatch
4444 * 2.5.13.32 wordMatch
4445 * 2.5.13.33 keywordMatch
4446 * 2.5.13.35 certificateMatch
4447 * 2.5.13.36 certificatePairExactMatch
4448 * 2.5.13.37 certificatePairMatch
4449 * 2.5.13.38 certificateListExactMatch
4450 * 2.5.13.39 certificateListMatch
4451 * 2.5.13.40 algorithmIdentifierMatch
4452 * 2.5.13.41 storedPrefixMatch
4453 * 2.5.13.42 attributeCertificateMatch
4454 * 2.5.13.43 readerAndKeyIDMatch
4455 * 2.5.13.44 attributeIntegrityMatch
4457 static struct mrule_defs_rec {
4459 slap_mask_t mrd_usage;
4460 slap_mr_convert_func * mrd_convert;
4461 slap_mr_normalize_func * mrd_normalize;
4462 slap_mr_match_func * mrd_match;
4463 slap_mr_indexer_func * mrd_indexer;
4464 slap_mr_filter_func * mrd_filter;
4466 char * mrd_associated;
4469 * EQUALITY matching rules must be listed after associated APPROX
4470 * matching rules. So, we list all APPROX matching rules first.
4472 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4473 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4474 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4476 directoryStringApproxMatch,
4477 directoryStringApproxIndexer,
4478 directoryStringApproxFilter,
4481 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4482 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4483 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
4485 IA5StringApproxMatch,
4486 IA5StringApproxIndexer,
4487 IA5StringApproxFilter,
4491 * Other matching rules
4494 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4495 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4496 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4498 objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4501 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4502 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4503 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4505 dnMatch, dnIndexer, dnFilter,
4508 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4509 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4510 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4512 caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4513 directoryStringApproxMatchOID },
4515 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4516 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4519 caseIgnoreOrderingMatch, NULL, NULL,
4522 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4523 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4524 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4526 caseExactIgnoreSubstringsMatch,
4527 caseExactIgnoreSubstringsIndexer,
4528 caseExactIgnoreSubstringsFilter,
4531 {"( 2.5.13.5 NAME 'caseExactMatch' "
4532 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4533 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4535 caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
4536 directoryStringApproxMatchOID },
4538 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4539 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4542 caseExactOrderingMatch, NULL, NULL,
4545 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4546 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4547 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4549 caseExactIgnoreSubstringsMatch,
4550 caseExactIgnoreSubstringsIndexer,
4551 caseExactIgnoreSubstringsFilter,
4554 {"( 2.5.13.8 NAME 'numericStringMatch' "
4555 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4556 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4559 caseIgnoreIA5Indexer,
4560 caseIgnoreIA5Filter,
4563 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4564 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4565 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4567 caseIgnoreIA5SubstringsMatch,
4568 caseIgnoreIA5SubstringsIndexer,
4569 caseIgnoreIA5SubstringsFilter,
4572 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4573 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4574 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4576 caseIgnoreListMatch, NULL, NULL,
4579 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4580 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4581 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4583 caseIgnoreListSubstringsMatch, NULL, NULL,
4586 {"( 2.5.13.13 NAME 'booleanMatch' "
4587 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4588 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4590 booleanMatch, NULL, NULL,
4593 {"( 2.5.13.14 NAME 'integerMatch' "
4594 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4595 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4597 integerMatch, integerIndexer, integerFilter,
4600 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4601 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4604 integerOrderingMatch, NULL, NULL,
4607 {"( 2.5.13.16 NAME 'bitStringMatch' "
4608 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4609 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4611 bitStringMatch, bitStringIndexer, bitStringFilter,
4614 {"( 2.5.13.17 NAME 'octetStringMatch' "
4615 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4616 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4618 octetStringMatch, octetStringIndexer, octetStringFilter,
4621 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4622 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4623 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4625 telephoneNumberMatch,
4626 telephoneNumberIndexer,
4627 telephoneNumberFilter,
4630 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4631 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4632 SLAP_MR_SUBSTR | SLAP_MR_EXT,
4634 telephoneNumberSubstringsMatch,
4635 telephoneNumberSubstringsIndexer,
4636 telephoneNumberSubstringsFilter,
4639 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4640 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4641 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4646 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4647 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4648 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4650 uniqueMemberMatch, NULL, NULL,
4653 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4654 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4655 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4657 protocolInformationMatch, NULL, NULL,
4660 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4661 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4662 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4664 generalizedTimeMatch, NULL, NULL,
4667 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4668 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4671 generalizedTimeOrderingMatch, NULL, NULL,
4674 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4675 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4676 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4678 integerFirstComponentMatch, NULL, NULL,
4681 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4682 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4683 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4685 objectIdentifierFirstComponentMatch, NULL, NULL,
4689 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4690 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4691 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4692 certificateExactConvert, NULL,
4693 certificateExactMatch,
4694 certificateExactIndexer, certificateExactFilter,
4698 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4699 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4700 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4702 caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
4703 IA5StringApproxMatchOID },
4705 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4706 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4707 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4709 caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4710 IA5StringApproxMatchOID },
4712 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4713 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4716 caseIgnoreIA5SubstringsMatch,
4717 caseIgnoreIA5SubstringsIndexer,
4718 caseIgnoreIA5SubstringsFilter,
4721 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4722 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4725 caseExactIA5SubstringsMatch,
4726 caseExactIA5SubstringsIndexer,
4727 caseExactIA5SubstringsFilter,
4730 #ifdef SLAPD_AUTHPASSWD
4731 /* needs updating */
4732 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4733 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4736 authPasswordMatch, NULL, NULL,
4740 #ifdef SLAPD_ACI_ENABLED
4741 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4742 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4745 OpenLDAPaciMatch, NULL, NULL,
4749 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4750 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4753 integerBitAndMatch, NULL, NULL,
4756 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4757 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4760 integerBitOrMatch, NULL, NULL,
4763 {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
4767 slap_schema_init( void )
4772 /* we should only be called once (from main) */
4773 assert( schema_init_done == 0 );
4775 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4776 res = register_syntax( syntax_defs[i].sd_desc,
4777 syntax_defs[i].sd_flags,
4778 syntax_defs[i].sd_validate,
4779 syntax_defs[i].sd_normalize,
4780 syntax_defs[i].sd_pretty
4781 #ifdef SLAPD_BINARY_CONVERSION
4783 syntax_defs[i].sd_ber2str,
4784 syntax_defs[i].sd_str2ber
4789 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4790 syntax_defs[i].sd_desc );
4795 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4796 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
4798 "slap_schema_init: Ingoring unusable matching rule %s\n",
4799 mrule_defs[i].mrd_desc );
4803 res = register_matching_rule(
4804 mrule_defs[i].mrd_desc,
4805 mrule_defs[i].mrd_usage,
4806 mrule_defs[i].mrd_convert,
4807 mrule_defs[i].mrd_normalize,
4808 mrule_defs[i].mrd_match,
4809 mrule_defs[i].mrd_indexer,
4810 mrule_defs[i].mrd_filter,
4811 mrule_defs[i].mrd_associated );
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;