1 /* schema_init.c - init builtin schema */
4 * Copyright 1998-2003 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)
32 #define SLAP_MR_DN_FOLD (0) /* TO BE DELETED */
35 /* validatation routines */
36 #define berValidate blobValidate
38 /* (new) normalization routines */
39 #define caseExactNormalize NULL
40 #define caseExactIA5Normalize NULL
41 #define caseIgnoreNormalize NULL
42 #define caseIgnoreIA5Normalize NULL
43 #define distinguishedNameNormalize NULL
44 #define integerNormalize NULL
45 #define integerFirstComponentNormalize NULL
46 #define numericStringNormalize NULL
47 #define objectIdentifierNormalize NULL
48 #define objectIdentifierFirstComponentNormalize NULL
49 #define generalizedTimeNormalize NULL
50 #define uniqueMemberNormalize NULL
51 #define bitStringNormalize NULL
52 #define telephoneNumberNormalize NULL
54 /* approx matching rules */
56 #define directoryStringApproxMatchOID NULL
57 #define IA5StringApproxMatchOID NULL
59 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
60 #define directoryStringApproxMatch approxMatch
61 #define directoryStringApproxIndexer approxIndexer
62 #define directoryStringApproxFilter approxFilter
63 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
64 #define IA5StringApproxMatch approxMatch
65 #define IA5StringApproxIndexer approxIndexer
66 #define IA5StringApproxFilter approxFilter
69 /* matching routines */
70 #define bitStringMatch octetStringMatch
71 #define bitStringIndexer octetStringIndexer
72 #define bitStringFilter octetStringFilter
74 #define numericStringMatch caseIgnoreIA5Match
75 #define numericStringIndexer NULL
76 #define numericStringFilter NULL
77 #define numericStringSubstringsIndexer NULL
78 #define numericStringSubstringsFilter NULL
80 #define objectIdentifierMatch octetStringMatch
81 #define objectIdentifierIndexer caseIgnoreIA5Indexer
82 #define objectIdentifierFilter caseIgnoreIA5Filter
84 #define generalizedTimeMatch caseIgnoreIA5Match
85 #define generalizedTimeOrderingMatch caseIgnoreIA5Match
87 #define uniqueMemberMatch dnMatch
88 #define numericStringSubstringsMatch NULL
90 #define caseExactIndexer caseExactIgnoreIndexer
91 #define caseExactFilter caseExactIgnoreFilter
92 #define caseExactOrderingMatch caseExactMatch
93 #define caseExactSubstringsMatch caseExactIgnoreSubstringsMatch
94 #define caseExactSubstringsIndexer caseExactIgnoreSubstringsIndexer
95 #define caseExactSubstringsFilter caseExactIgnoreSubstringsFilter
96 #define caseIgnoreIndexer caseExactIgnoreIndexer
97 #define caseIgnoreFilter caseExactIgnoreFilter
98 #define caseIgnoreOrderingMatch caseIgnoreMatch
99 #define caseIgnoreSubstringsMatch caseExactIgnoreSubstringsMatch
100 #define caseIgnoreSubstringsIndexer caseExactIgnoreSubstringsIndexer
101 #define caseIgnoreSubstringsFilter caseExactIgnoreSubstringsFilter
103 #define integerOrderingMatch integerMatch
104 #define integerFirstComponentMatch integerMatch
106 #define distinguishedNameMatch dnMatch
107 #define distinguishedNameIndexer caseExactIgnoreIndexer
108 #define distinguishedNameFilter caseExactIgnoreFilter
110 #define telephoneNumberMatch caseIgnoreIA5Match
111 #define telephoneNumberSubstringsMatch caseIgnoreIA5SubstringsMatch
112 #define telephoneNumberIndexer caseIgnoreIA5Indexer
113 #define telephoneNumberFilter caseIgnoreIA5Filter
114 #define telephoneNumberSubstringsIndexer caseIgnoreIA5SubstringsIndexer
115 #define telephoneNumberSubstringsFilter caseIgnoreIA5SubstringsFilter
118 static char *bvcasechr( struct berval *bv, unsigned char c, ber_len_t *len )
121 char lower = TOLOWER( c );
122 char upper = TOUPPER( c );
124 if( c == 0 ) return NULL;
126 for( i=0; i < bv->bv_len; i++ ) {
127 if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
129 return &bv->bv_val[i];
142 struct berval *value,
143 void *assertedValue )
145 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
148 match = memcmp( value->bv_val,
149 ((struct berval *) assertedValue)->bv_val,
158 octetStringOrderingMatch(
163 struct berval *value,
164 void *assertedValue )
166 ber_len_t v_len = value->bv_len;
167 ber_len_t av_len = ((struct berval *) assertedValue)->bv_len;
169 int match = memcmp( value->bv_val,
170 ((struct berval *) assertedValue)->bv_val,
171 (v_len < av_len ? v_len : av_len) );
173 if( match == 0 ) match = v_len - av_len;
179 /* Index generation function */
180 int octetStringIndexer(
185 struct berval *prefix,
192 HASH_CONTEXT HASHcontext;
193 unsigned char HASHdigest[HASH_BYTES];
194 struct berval digest;
195 digest.bv_val = HASHdigest;
196 digest.bv_len = sizeof(HASHdigest);
198 for( i=0; values[i].bv_val != NULL; i++ ) {
199 /* just count them */
202 /* we should have at least one value at this point */
205 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
207 slen = syntax->ssyn_oidlen;
208 mlen = mr->smr_oidlen;
210 for( i=0; values[i].bv_val != NULL; i++ ) {
211 HASH_Init( &HASHcontext );
212 if( prefix != NULL && prefix->bv_len > 0 ) {
213 HASH_Update( &HASHcontext,
214 prefix->bv_val, prefix->bv_len );
216 HASH_Update( &HASHcontext,
217 syntax->ssyn_oid, slen );
218 HASH_Update( &HASHcontext,
220 HASH_Update( &HASHcontext,
221 values[i].bv_val, values[i].bv_len );
222 HASH_Final( HASHdigest, &HASHcontext );
224 ber_dupbv( &keys[i], &digest );
227 keys[i].bv_val = NULL;
235 /* Index generation function */
236 int octetStringFilter(
241 struct berval *prefix,
242 void * assertedValue,
247 HASH_CONTEXT HASHcontext;
248 unsigned char HASHdigest[HASH_BYTES];
249 struct berval *value = (struct berval *) assertedValue;
250 struct berval digest;
251 digest.bv_val = HASHdigest;
252 digest.bv_len = sizeof(HASHdigest);
254 slen = syntax->ssyn_oidlen;
255 mlen = mr->smr_oidlen;
257 keys = ch_malloc( sizeof( struct berval ) * 2 );
259 HASH_Init( &HASHcontext );
260 if( prefix != NULL && prefix->bv_len > 0 ) {
261 HASH_Update( &HASHcontext,
262 prefix->bv_val, prefix->bv_len );
264 HASH_Update( &HASHcontext,
265 syntax->ssyn_oid, slen );
266 HASH_Update( &HASHcontext,
268 HASH_Update( &HASHcontext,
269 value->bv_val, value->bv_len );
270 HASH_Final( HASHdigest, &HASHcontext );
272 ber_dupbv( keys, &digest );
273 keys[1].bv_val = NULL;
286 /* no value allowed */
287 return LDAP_INVALID_SYNTAX;
295 /* any value allowed */
306 /* very unforgiving validation, requires no normalization
307 * before simplistic matching
309 if( in->bv_len < 3 ) {
310 return LDAP_INVALID_SYNTAX;
314 * rfc 2252 section 6.3 Bit String
315 * bitstring = "'" *binary-digit "'"
316 * binary-digit = "0" / "1"
317 * example: '0101111101'B
320 if( in->bv_val[0] != '\'' ||
321 in->bv_val[in->bv_len-2] != '\'' ||
322 in->bv_val[in->bv_len-1] != 'B' )
324 return LDAP_INVALID_SYNTAX;
327 for( i=in->bv_len-3; i>0; i-- ) {
328 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
329 return LDAP_INVALID_SYNTAX;
344 if( in->bv_len == 0 ) return LDAP_SUCCESS;
346 ber_dupbv( &dn, in );
347 if( !dn.bv_val ) return LDAP_OTHER;
349 if( dn.bv_val[dn.bv_len-1] == 'B'
350 && dn.bv_val[dn.bv_len-2] == '\'' )
352 /* assume presence of optional UID */
355 for(i=dn.bv_len-3; i>1; i--) {
356 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
360 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
361 ber_memfree( dn.bv_val );
362 return LDAP_INVALID_SYNTAX;
365 /* trim the UID to allow use of dnValidate */
366 dn.bv_val[i-1] = '\0';
370 rc = dnValidate( NULL, &dn );
372 ber_memfree( dn.bv_val );
380 struct berval *normalized )
385 ber_dupbv( &out, val );
386 if( out.bv_len != 0 ) {
387 struct berval uid = { 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 uid.bv_val = strrchr( out.bv_val, '#' );
395 if( uid.bv_val == NULL ) {
397 return LDAP_INVALID_SYNTAX;
400 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
401 out.bv_len -= uid.bv_len--;
403 /* temporarily trim the UID */
404 *(uid.bv_val++) = '\0';
407 rc = dnNormalize2( NULL, &out, normalized );
409 if( rc != LDAP_SUCCESS ) {
411 return LDAP_INVALID_SYNTAX;
415 normalized->bv_val = ch_realloc( normalized->bv_val,
416 normalized->bv_len + uid.bv_len + sizeof("#") );
418 /* insert the separator */
419 normalized->bv_val[normalized->bv_len++] = '#';
422 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
423 uid.bv_val, uid.bv_len );
424 normalized->bv_len += uid.bv_len;
427 normalized->bv_val[normalized->bv_len] = '\0';
437 * Handling boolean syntax and matching is quite rigid.
438 * A more flexible approach would be to allow a variety
439 * of strings to be normalized and prettied into TRUE
447 /* very unforgiving validation, requires no normalization
448 * before simplistic matching
451 if( in->bv_len == 4 ) {
452 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
455 } else if( in->bv_len == 5 ) {
456 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
461 return LDAP_INVALID_SYNTAX;
470 struct berval *value,
471 void *assertedValue )
473 /* simplistic matching allowed by rigid validation */
474 struct berval *asserted = (struct berval *) assertedValue;
475 *matchp = value->bv_len != asserted->bv_len;
479 /*-------------------------------------------------------------------
480 LDAP/X.500 string syntax / matching rules have a few oddities. This
481 comment attempts to detail how slapd(8) treats them.
484 StringSyntax X.500 LDAP Matching
485 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
486 PrintableString subset subset i/e + ignore insignificant spaces
487 NumericString subset subset ignore all spaces
488 IA5String ASCII ASCII i/e + ignore insignificant spaces
489 TeletexString T.61 T.61 i/e + ignore insignificant spaces
491 TelephoneNumber subset subset i + ignore all spaces and "-"
493 See draft-ietf-ldapbis-strpro for details (once published).
497 In X.500(93), a directory string can be either a PrintableString,
498 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
499 In later versions, more CHOICEs were added. In all cases the string
502 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
504 For matching, there are both case ignore and exact rules. Both
505 also require that "insignificant" spaces be ignored.
506 spaces before the first non-space are ignored;
507 spaces after the last non-space are ignored;
508 spaces after a space are ignored.
509 Note: by these rules (and as clarified in X.520), a string of only
510 spaces is to be treated as if held one space, not empty (which
511 would be a syntax error).
514 In ASN.1, numeric string is just a string of digits and spaces
515 and could be empty. However, in X.500, all attribute values of
516 numeric string carry a non-empty constraint. For example:
518 internationalISDNNumber ATTRIBUTE ::= {
519 WITH SYNTAX InternationalISDNNumber
520 EQUALITY MATCHING RULE numericStringMatch
521 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
522 ID id-at-internationalISDNNumber }
523 InternationalISDNNumber ::=
524 NumericString (SIZE(1..ub-international-isdn-number))
526 Unforunately, some assertion values are don't carry the same
527 constraint (but its unclear how such an assertion could ever
528 be true). In LDAP, there is one syntax (numericString) not two
529 (numericString with constraint, numericString without constraint).
530 This should be treated as numericString with non-empty constraint.
531 Note that while someone may have no ISDN number, there are no ISDN
532 numbers which are zero length.
534 In matching, spaces are ignored.
537 In ASN.1, Printable string is just a string of printable characters
538 and can be empty. In X.500, semantics much like NumericString (see
539 serialNumber for a like example) excepting uses insignificant space
540 handling instead of ignore all spaces.
543 Basically same as PrintableString. There are no examples in X.500,
544 but same logic applies. So we require them to be non-empty as
547 -------------------------------------------------------------------*/
556 unsigned char *u = in->bv_val;
558 if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
560 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
561 /* get the length indicated by the first byte */
562 len = LDAP_UTF8_CHARLEN2( u, len );
564 /* very basic checks */
567 if( (u[5] & 0xC0) != 0x80 ) {
568 return LDAP_INVALID_SYNTAX;
571 if( (u[4] & 0xC0) != 0x80 ) {
572 return LDAP_INVALID_SYNTAX;
575 if( (u[3] & 0xC0) != 0x80 ) {
576 return LDAP_INVALID_SYNTAX;
579 if( (u[2] & 0xC0 )!= 0x80 ) {
580 return LDAP_INVALID_SYNTAX;
583 if( (u[1] & 0xC0) != 0x80 ) {
584 return LDAP_INVALID_SYNTAX;
587 /* CHARLEN already validated it */
590 return LDAP_INVALID_SYNTAX;
593 /* make sure len corresponds with the offset
594 to the next character */
595 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
598 if( count != 0 ) return LDAP_INVALID_SYNTAX;
604 xUTF8StringNormalize(
607 struct berval *normalized )
612 /* validator should have refused an empty string */
613 assert( val->bv_len );
617 /* Ignore initial whitespace */
618 /* All space is ASCII. All ASCII is 1 byte */
619 for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
621 normalized->bv_len = val->bv_len - (p - val->bv_val);
623 if( !normalized->bv_len ) {
624 ber_mem2bv( " ", 1, 1, normalized );
628 ber_mem2bv( p, normalized->bv_len, 1, normalized );
629 e = normalized->bv_val + normalized->bv_len;
631 assert( normalized->bv_val );
633 p = q = normalized->bv_val;
638 if ( ASCII_SPACE( *p ) ) {
643 /* Ignore the extra whitespace */
644 while ( ASCII_SPACE( *p ) ) {
648 len = LDAP_UTF8_COPY(q,p);
654 assert( normalized->bv_val <= p );
655 assert( q+len <= p );
657 /* cannot start with a space */
658 assert( !ASCII_SPACE( normalized->bv_val[0] ) );
661 * If the string ended in space, backup the pointer one
662 * position. One is enough because the above loop collapsed
663 * all whitespace to a single space.
671 /* cannot end with a space */
672 assert( !ASCII_SPACE( *q ) );
679 normalized->bv_len = q - normalized->bv_val;
684 /* Returns Unicode canonically normalized copy of a substring assertion
685 * Skipping attribute description */
686 static SubstringsAssertion *
687 UTF8SubstringsAssertionNormalize(
688 SubstringsAssertion *sa,
691 SubstringsAssertion *nsa;
694 nsa = (SubstringsAssertion *)SLAP_CALLOC( 1, sizeof(SubstringsAssertion) );
699 if( sa->sa_initial.bv_val != NULL ) {
700 UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
701 if( nsa->sa_initial.bv_val == NULL ) {
706 if( sa->sa_any != NULL ) {
707 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
710 nsa->sa_any = (struct berval *)
711 SLAP_MALLOC( (i + 1) * sizeof(struct berval) );
712 if( nsa->sa_any == NULL ) {
716 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
717 UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
719 if( nsa->sa_any[i].bv_val == NULL ) {
723 nsa->sa_any[i].bv_val = NULL;
726 if( sa->sa_final.bv_val != NULL ) {
727 UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
728 if( nsa->sa_final.bv_val == NULL ) {
736 if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
737 if ( nsa->sa_any ) ber_bvarray_free( nsa->sa_any );
738 if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
743 #ifndef SLAPD_APPROX_OLDSINGLESTRING
745 #if defined(SLAPD_APPROX_INITIALS)
746 #define SLAPD_APPROX_DELIMITER "._ "
747 #define SLAPD_APPROX_WORDLEN 2
749 #define SLAPD_APPROX_DELIMITER " "
750 #define SLAPD_APPROX_WORDLEN 1
759 struct berval *value,
760 void *assertedValue )
762 struct berval *nval, *assertv;
763 char *val, **values, **words, *c;
764 int i, count, len, nextchunk=0, nextavail=0;
766 /* Yes, this is necessary */
767 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
773 /* Yes, this is necessary */
774 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
775 NULL, LDAP_UTF8_APPROX );
776 if( assertv == NULL ) {
782 /* Isolate how many words there are */
783 for ( c = nval->bv_val, count = 1; *c; c++ ) {
784 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
785 if ( c == NULL ) break;
790 /* Get a phonetic copy of each word */
791 words = (char **)ch_malloc( count * sizeof(char *) );
792 values = (char **)ch_malloc( count * sizeof(char *) );
793 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
795 values[i] = phonetic(c);
798 /* Work through the asserted value's words, to see if at least some
799 of the words are there, in the same order. */
801 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
802 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
807 #if defined(SLAPD_APPROX_INITIALS)
808 else if( len == 1 ) {
809 /* Single letter words need to at least match one word's initial */
810 for( i=nextavail; i<count; i++ )
811 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
818 /* Isolate the next word in the asserted value and phonetic it */
819 assertv->bv_val[nextchunk+len] = '\0';
820 val = phonetic( assertv->bv_val + nextchunk );
822 /* See if this phonetic chunk is in the remaining words of *value */
823 for( i=nextavail; i<count; i++ ){
824 if( !strcmp( val, values[i] ) ){
832 /* This chunk in the asserted value was NOT within the *value. */
838 /* Go on to the next word in the asserted value */
842 /* If some of the words were seen, call it a match */
843 if( nextavail > 0 ) {
851 ber_bvfree( assertv );
852 for( i=0; i<count; i++ ) {
853 ch_free( values[i] );
868 struct berval *prefix,
873 int i,j, len, wordcount, keycount=0;
874 struct berval *newkeys;
877 for( j=0; values[j].bv_val != NULL; j++ ) {
878 struct berval val = { 0, NULL };
879 /* Yes, this is necessary */
880 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
881 assert( val.bv_val != NULL );
883 /* Isolate how many words there are. There will be a key for each */
884 for( wordcount = 0, c = val.bv_val; *c; c++) {
885 len = strcspn(c, SLAPD_APPROX_DELIMITER);
886 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
888 if (*c == '\0') break;
892 /* Allocate/increase storage to account for new keys */
893 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
894 * sizeof(struct berval) );
895 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
896 if( keys ) ch_free( keys );
899 /* Get a phonetic copy of each word */
900 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
902 if( len < SLAPD_APPROX_WORDLEN ) continue;
903 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
908 ber_memfree( val.bv_val );
910 keys[keycount].bv_val = NULL;
922 struct berval *prefix,
923 void * assertedValue,
931 /* Yes, this is necessary */
932 val = UTF8bvnormalize( ((struct berval *)assertedValue),
933 NULL, LDAP_UTF8_APPROX );
934 if( val == NULL || val->bv_val == NULL ) {
935 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
936 keys[0].bv_val = NULL;
942 /* Isolate how many words there are. There will be a key for each */
943 for( count = 0,c = val->bv_val; *c; c++) {
944 len = strcspn(c, SLAPD_APPROX_DELIMITER);
945 if( len >= SLAPD_APPROX_WORDLEN ) count++;
947 if (*c == '\0') break;
951 /* Allocate storage for new keys */
952 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
954 /* Get a phonetic copy of each word */
955 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
957 if( len < SLAPD_APPROX_WORDLEN ) continue;
958 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
964 keys[count].bv_val = NULL;
972 /* No other form of Approximate Matching is defined */
980 struct berval *value,
981 void *assertedValue )
983 char *vapprox, *avapprox;
986 /* Yes, this is necessary */
987 s = UTF8normalize( value, UTF8_NOCASEFOLD );
993 /* Yes, this is necessary */
994 t = UTF8normalize( ((struct berval *)assertedValue),
1002 vapprox = phonetic( strip8bitChars( s ) );
1003 avapprox = phonetic( strip8bitChars( t ) );
1008 *matchp = strcmp( vapprox, avapprox );
1011 ch_free( avapprox );
1013 return LDAP_SUCCESS;
1022 struct berval *prefix,
1030 for( i=0; values[i].bv_val != NULL; i++ ) {
1031 /* empty - just count them */
1034 /* we should have at least one value at this point */
1037 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1039 /* Copy each value and run it through phonetic() */
1040 for( i=0; values[i].bv_val != NULL; i++ ) {
1041 /* Yes, this is necessary */
1042 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1044 /* strip 8-bit chars and run through phonetic() */
1045 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1048 keys[i].bv_val = NULL;
1051 return LDAP_SUCCESS;
1061 struct berval *prefix,
1062 void * assertedValue,
1068 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1070 /* Yes, this is necessary */
1071 s = UTF8normalize( ((struct berval *)assertedValue),
1076 /* strip 8-bit chars and run through phonetic() */
1077 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1083 return LDAP_SUCCESS;
1094 struct berval *value,
1095 void *assertedValue )
1097 *matchp = UTF8bvnormcmp( value,
1098 (struct berval *) assertedValue,
1099 LDAP_UTF8_NOCASEFOLD );
1100 return LDAP_SUCCESS;
1104 caseExactIgnoreSubstringsMatch(
1109 struct berval *value,
1110 void *assertedValue )
1113 SubstringsAssertion *sub = NULL;
1114 struct berval left = { 0, NULL };
1120 casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
1121 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1123 if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
1129 sub = UTF8SubstringsAssertionNormalize( assertedValue, casefold );
1135 /* Add up asserted input length */
1136 if( sub->sa_initial.bv_val ) {
1137 inlen += sub->sa_initial.bv_len;
1140 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
1141 inlen += sub->sa_any[i].bv_len;
1144 if( sub->sa_final.bv_val ) {
1145 inlen += sub->sa_final.bv_len;
1148 if( sub->sa_initial.bv_val ) {
1149 if( inlen > left.bv_len ) {
1154 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
1155 sub->sa_initial.bv_len );
1161 left.bv_val += sub->sa_initial.bv_len;
1162 left.bv_len -= sub->sa_initial.bv_len;
1163 inlen -= sub->sa_initial.bv_len;
1166 if( sub->sa_final.bv_val ) {
1167 if( inlen > left.bv_len ) {
1172 match = memcmp( sub->sa_final.bv_val,
1173 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
1174 sub->sa_final.bv_len );
1180 left.bv_len -= sub->sa_final.bv_len;
1181 inlen -= sub->sa_final.bv_len;
1185 for(i=0; sub->sa_any[i].bv_val; i++) {
1190 if( inlen > left.bv_len ) {
1191 /* not enough length */
1196 if( sub->sa_any[i].bv_len == 0 ) {
1200 p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
1206 idx = p - left.bv_val;
1208 if( idx >= left.bv_len ) {
1209 /* this shouldn't happen */
1211 if ( sub->sa_final.bv_val )
1212 ch_free( sub->sa_final.bv_val );
1214 ber_bvarray_free( sub->sa_any );
1215 if ( sub->sa_initial.bv_val )
1216 ch_free( sub->sa_initial.bv_val );
1224 if( sub->sa_any[i].bv_len > left.bv_len ) {
1225 /* not enough left */
1230 match = memcmp( left.bv_val,
1231 sub->sa_any[i].bv_val,
1232 sub->sa_any[i].bv_len );
1240 left.bv_val += sub->sa_any[i].bv_len;
1241 left.bv_len -= sub->sa_any[i].bv_len;
1242 inlen -= sub->sa_any[i].bv_len;
1249 if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
1250 if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
1251 if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
1255 return LDAP_SUCCESS;
1258 /* Index generation function */
1259 static int caseExactIgnoreIndexer(
1264 struct berval *prefix,
1269 unsigned casefold,wasspace;
1272 HASH_CONTEXT HASHcontext;
1273 unsigned char HASHdigest[HASH_BYTES];
1274 struct berval digest;
1275 digest.bv_val = HASHdigest;
1276 digest.bv_len = sizeof(HASHdigest);
1278 for( i=0; values[i].bv_val != NULL; i++ ) {
1279 /* empty - just count them */
1282 /* we should have at least one value at this point */
1285 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
1287 slen = syntax->ssyn_oidlen;
1288 mlen = mr->smr_oidlen;
1290 casefold = ( mr != slap_schema.si_mr_caseExactMatch )
1291 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1293 for( i=0; values[i].bv_val != NULL; i++ ) {
1294 struct berval value, nvalue;
1295 UTF8bvnormalize( &values[i], &value, casefold );
1297 /* collapse spaces (in place) */
1299 nvalue.bv_val = value.bv_val;
1302 for( j=0; j<value.bv_len; j++) {
1303 if ( ASCII_SPACE( value.bv_val[j] )) {
1304 if( wasspace++ == 0 ) {
1305 nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
1309 nvalue.bv_val[nvalue.bv_len++] = value.bv_val[j];
1313 if( nvalue.bv_len == 0 ) {
1314 nvalue.bv_val = " ";
1315 nvalue.bv_len = sizeof(" ")-1;
1317 if( wasspace ) --nvalue.bv_len;
1318 nvalue.bv_val[nvalue.bv_len] = '\0';
1321 HASH_Init( &HASHcontext );
1322 if( prefix != NULL && prefix->bv_len > 0 ) {
1323 HASH_Update( &HASHcontext,
1324 prefix->bv_val, prefix->bv_len );
1326 HASH_Update( &HASHcontext,
1327 syntax->ssyn_oid, slen );
1328 HASH_Update( &HASHcontext,
1329 mr->smr_oid, mlen );
1330 HASH_Update( &HASHcontext,
1331 nvalue.bv_val, nvalue.bv_len );
1332 HASH_Final( HASHdigest, &HASHcontext );
1334 free( value.bv_val );
1335 ber_dupbv( &keys[i], &digest );
1338 keys[i].bv_val = NULL;
1340 return LDAP_SUCCESS;
1343 /* Index generation function */
1344 static int caseExactIgnoreFilter(
1349 struct berval *prefix,
1350 void * assertedValue,
1356 HASH_CONTEXT HASHcontext;
1357 unsigned char HASHdigest[HASH_BYTES];
1358 struct berval value = { 0, NULL };
1359 struct berval digest;
1361 digest.bv_val = HASHdigest;
1362 digest.bv_len = sizeof(HASHdigest);
1364 slen = syntax->ssyn_oidlen;
1365 mlen = mr->smr_oidlen;
1367 casefold = ( mr != slap_schema.si_mr_caseExactMatch )
1368 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1370 UTF8bvnormalize( (struct berval *) assertedValue, &value, casefold );
1371 /* This usually happens if filter contains bad UTF8 */
1372 if( value.bv_val == NULL ) {
1373 keys = ch_malloc( sizeof( struct berval ) );
1374 keys[0].bv_val = NULL;
1375 return LDAP_SUCCESS;
1378 keys = ch_malloc( sizeof( struct berval ) * 2 );
1380 HASH_Init( &HASHcontext );
1381 if( prefix != NULL && prefix->bv_len > 0 ) {
1382 HASH_Update( &HASHcontext,
1383 prefix->bv_val, prefix->bv_len );
1385 HASH_Update( &HASHcontext,
1386 syntax->ssyn_oid, slen );
1387 HASH_Update( &HASHcontext,
1388 mr->smr_oid, mlen );
1389 HASH_Update( &HASHcontext,
1390 value.bv_val, value.bv_len );
1391 HASH_Final( HASHdigest, &HASHcontext );
1393 ber_dupbv( keys, &digest );
1394 keys[1].bv_val = NULL;
1396 free( value.bv_val );
1399 return LDAP_SUCCESS;
1402 /* Substrings Index generation function */
1403 static int caseExactIgnoreSubstringsIndexer(
1408 struct berval *prefix,
1412 unsigned casefold, wasspace;
1413 ber_len_t i, j, nkeys;
1416 BerVarray tvalues, nvalues;
1418 HASH_CONTEXT HASHcontext;
1419 unsigned char HASHdigest[HASH_BYTES];
1420 struct berval digest;
1421 digest.bv_val = HASHdigest;
1422 digest.bv_len = sizeof(HASHdigest);
1426 for( i=0; values[i].bv_val != NULL; i++ ) {
1427 /* empty - just count them */
1430 /* we should have at least one value at this point */
1433 casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
1434 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1436 tvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1437 nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
1439 for( i=0; values[i].bv_val != NULL; i++ ) {
1440 UTF8bvnormalize( &values[i], &tvalues[i], casefold );
1442 /* collapse spaces (in place) */
1443 nvalues[i].bv_len = 0;
1444 nvalues[i].bv_val = tvalues[i].bv_val;
1447 for( j=0; j<tvalues[i].bv_len; j++) {
1448 if ( ASCII_SPACE( tvalues[i].bv_val[j] )) {
1449 if( wasspace++ == 0 ) {
1450 nvalues[i].bv_val[nvalues[i].bv_len++] =
1451 tvalues[i].bv_val[j];
1455 nvalues[i].bv_val[nvalues[i].bv_len++] = tvalues[i].bv_val[j];
1459 if( nvalues[i].bv_len == 0 ) {
1460 nvalues[i].bv_val = " ";
1461 nvalues[i].bv_len = sizeof(" ")-1;
1463 if( wasspace ) --nvalues[i].bv_len;
1464 nvalues[i].bv_val[nvalues[i].bv_len] = '\0';
1468 tvalues[i].bv_val = NULL;
1469 nvalues[i].bv_val = NULL;
1472 for( i=0; values[i].bv_val != NULL; i++ ) {
1473 /* count number of indices to generate */
1474 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
1478 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1479 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1480 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1481 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1483 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1487 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
1488 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1489 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1493 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1494 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1495 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
1496 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
1498 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
1504 /* no keys to generate */
1506 ber_bvarray_free( tvalues );
1508 return LDAP_SUCCESS;
1511 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1513 slen = syntax->ssyn_oidlen;
1514 mlen = mr->smr_oidlen;
1517 for( i=0; values[i].bv_val != NULL; i++ ) {
1520 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
1522 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
1523 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
1525 char pre = SLAP_INDEX_SUBSTR_PREFIX;
1526 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
1528 for( j=0; j<max; j++ ) {
1529 HASH_Init( &HASHcontext );
1530 if( prefix != NULL && prefix->bv_len > 0 ) {
1531 HASH_Update( &HASHcontext,
1532 prefix->bv_val, prefix->bv_len );
1535 HASH_Update( &HASHcontext,
1536 &pre, sizeof( pre ) );
1537 HASH_Update( &HASHcontext,
1538 syntax->ssyn_oid, slen );
1539 HASH_Update( &HASHcontext,
1540 mr->smr_oid, mlen );
1541 HASH_Update( &HASHcontext,
1542 &values[i].bv_val[j],
1543 SLAP_INDEX_SUBSTR_MAXLEN );
1544 HASH_Final( HASHdigest, &HASHcontext );
1546 ber_dupbv( &keys[nkeys++], &digest );
1550 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
1551 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
1553 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
1556 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
1557 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1558 HASH_Init( &HASHcontext );
1559 if( prefix != NULL && prefix->bv_len > 0 ) {
1560 HASH_Update( &HASHcontext,
1561 prefix->bv_val, prefix->bv_len );
1563 HASH_Update( &HASHcontext,
1564 &pre, sizeof( pre ) );
1565 HASH_Update( &HASHcontext,
1566 syntax->ssyn_oid, slen );
1567 HASH_Update( &HASHcontext,
1568 mr->smr_oid, mlen );
1569 HASH_Update( &HASHcontext,
1570 values[i].bv_val, j );
1571 HASH_Final( HASHdigest, &HASHcontext );
1573 ber_dupbv( &keys[nkeys++], &digest );
1576 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
1577 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1578 HASH_Init( &HASHcontext );
1579 if( prefix != NULL && prefix->bv_len > 0 ) {
1580 HASH_Update( &HASHcontext,
1581 prefix->bv_val, prefix->bv_len );
1583 HASH_Update( &HASHcontext,
1584 &pre, sizeof( pre ) );
1585 HASH_Update( &HASHcontext,
1586 syntax->ssyn_oid, slen );
1587 HASH_Update( &HASHcontext,
1588 mr->smr_oid, mlen );
1589 HASH_Update( &HASHcontext,
1590 &values[i].bv_val[values[i].bv_len-j], j );
1591 HASH_Final( HASHdigest, &HASHcontext );
1593 ber_dupbv( &keys[nkeys++], &digest );
1601 keys[nkeys].bv_val = NULL;
1608 ber_bvarray_free( tvalues );
1611 return LDAP_SUCCESS;
1614 static int caseExactIgnoreSubstringsFilter(
1619 struct berval *prefix,
1620 void * assertedValue,
1623 SubstringsAssertion *sa;
1626 ber_len_t nkeys = 0;
1627 size_t slen, mlen, klen;
1629 HASH_CONTEXT HASHcontext;
1630 unsigned char HASHdigest[HASH_BYTES];
1631 struct berval *value;
1632 struct berval digest;
1634 casefold = ( mr != slap_schema.si_mr_caseExactSubstringsMatch )
1635 ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
1637 sa = UTF8SubstringsAssertionNormalize( assertedValue, casefold );
1640 return LDAP_SUCCESS;
1643 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1644 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1649 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1651 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1652 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
1653 /* don't bother accounting for stepping */
1654 nkeys += sa->sa_any[i].bv_len -
1655 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
1660 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1661 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1667 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1668 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1669 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1672 return LDAP_SUCCESS;
1675 digest.bv_val = HASHdigest;
1676 digest.bv_len = sizeof(HASHdigest);
1678 slen = syntax->ssyn_oidlen;
1679 mlen = mr->smr_oidlen;
1681 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
1684 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
1685 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1687 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
1688 value = &sa->sa_initial;
1690 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1691 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1693 HASH_Init( &HASHcontext );
1694 if( prefix != NULL && prefix->bv_len > 0 ) {
1695 HASH_Update( &HASHcontext,
1696 prefix->bv_val, prefix->bv_len );
1698 HASH_Update( &HASHcontext,
1699 &pre, sizeof( pre ) );
1700 HASH_Update( &HASHcontext,
1701 syntax->ssyn_oid, slen );
1702 HASH_Update( &HASHcontext,
1703 mr->smr_oid, mlen );
1704 HASH_Update( &HASHcontext,
1705 value->bv_val, klen );
1706 HASH_Final( HASHdigest, &HASHcontext );
1708 ber_dupbv( &keys[nkeys++], &digest );
1711 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
1713 pre = SLAP_INDEX_SUBSTR_PREFIX;
1714 klen = SLAP_INDEX_SUBSTR_MAXLEN;
1716 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
1717 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
1721 value = &sa->sa_any[i];
1724 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
1725 j += SLAP_INDEX_SUBSTR_STEP )
1727 HASH_Init( &HASHcontext );
1728 if( prefix != NULL && prefix->bv_len > 0 ) {
1729 HASH_Update( &HASHcontext,
1730 prefix->bv_val, prefix->bv_len );
1732 HASH_Update( &HASHcontext,
1733 &pre, sizeof( pre ) );
1734 HASH_Update( &HASHcontext,
1735 syntax->ssyn_oid, slen );
1736 HASH_Update( &HASHcontext,
1737 mr->smr_oid, mlen );
1738 HASH_Update( &HASHcontext,
1739 &value->bv_val[j], klen );
1740 HASH_Final( HASHdigest, &HASHcontext );
1742 ber_dupbv( &keys[nkeys++], &digest );
1748 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
1749 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
1751 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
1752 value = &sa->sa_final;
1754 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
1755 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
1757 HASH_Init( &HASHcontext );
1758 if( prefix != NULL && prefix->bv_len > 0 ) {
1759 HASH_Update( &HASHcontext,
1760 prefix->bv_val, prefix->bv_len );
1762 HASH_Update( &HASHcontext,
1763 &pre, sizeof( pre ) );
1764 HASH_Update( &HASHcontext,
1765 syntax->ssyn_oid, slen );
1766 HASH_Update( &HASHcontext,
1767 mr->smr_oid, mlen );
1768 HASH_Update( &HASHcontext,
1769 &value->bv_val[value->bv_len-klen], klen );
1770 HASH_Final( HASHdigest, &HASHcontext );
1772 ber_dupbv( &keys[nkeys++], &digest );
1776 keys[nkeys].bv_val = NULL;
1782 if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
1783 if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
1784 if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
1787 return LDAP_SUCCESS;
1796 struct berval *value,
1797 void *assertedValue )
1799 *matchp = UTF8bvnormcmp( value,
1800 (struct berval *) assertedValue,
1801 LDAP_UTF8_CASEFOLD );
1802 return LDAP_SUCCESS;
1805 /* Remove all spaces and '-' characters */
1807 xtelephoneNumberNormalize(
1810 struct berval *normalized )
1814 /* validator should have refused an empty string */
1815 assert( val->bv_len );
1817 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1819 for( p = val->bv_val; *p; p++ ) {
1820 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1826 normalized->bv_len = q - normalized->bv_val;
1828 if( normalized->bv_len == 0 ) {
1829 free( normalized->bv_val );
1830 return LDAP_INVALID_SYNTAX;
1833 return LDAP_SUCCESS;
1839 struct berval *val )
1843 if( val->bv_len == 0 ) {
1844 /* disallow empty strings */
1845 return LDAP_INVALID_SYNTAX;
1848 if( OID_LEADCHAR(val->bv_val[0]) ) {
1850 for(i=1; i < val->bv_len; i++) {
1851 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1852 if( dot++ ) return 1;
1853 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1856 return LDAP_INVALID_SYNTAX;
1860 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1862 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1863 for(i=1; i < val->bv_len; i++) {
1864 if( !DESC_CHAR(val->bv_val[i] ) ) {
1865 return LDAP_INVALID_SYNTAX;
1869 return LDAP_SUCCESS;
1872 return LDAP_INVALID_SYNTAX;
1881 struct berval *value,
1882 void *assertedValue )
1885 int vsign = 1, avsign = 1; /* default sign = '+' */
1886 struct berval *asserted;
1887 ber_len_t vlen, avlen;
1890 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1892 vlen = value->bv_len;
1893 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1894 char *tmp = memchr( v, '$', vlen );
1897 while( vlen && ASCII_SPACE( v[vlen-1] ))
1900 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) /* ANSI 2.2.1 */
1906 /* Do the same with the *assertedValue number */
1907 asserted = (struct berval *) assertedValue;
1908 av = asserted->bv_val;
1909 avlen = asserted->bv_len;
1910 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1916 match = vsign - avsign;
1918 match = (vlen != avlen
1919 ? ( vlen < avlen ? -1 : 1 )
1920 : memcmp( v, av, vlen ));
1926 return LDAP_SUCCESS;
1932 struct berval *val )
1936 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1938 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1939 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1940 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1941 return LDAP_INVALID_SYNTAX;
1944 for( i=1; i < val->bv_len; i++ ) {
1945 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1948 return LDAP_SUCCESS;
1955 struct berval *normalized )
1965 /* Ignore leading spaces */
1966 while ( len && ( *p == ' ' )) {
1973 negative = ( *p == '-' );
1974 if(( *p == '-' ) || ( *p == '+' )) {
1980 /* Ignore leading zeros */
1981 while ( len && ( *p == '0' )) {
1986 /* If there are no non-zero digits left, the number is zero, otherwise
1987 allocate space for the number and copy it into the buffer */
1989 normalized->bv_val = ch_strdup("0");
1990 normalized->bv_len = 1;
1993 normalized->bv_len = len+negative;
1994 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1996 normalized->bv_val[0] = '-';
1998 AC_MEMCPY( normalized->bv_val + negative, p, len );
1999 normalized->bv_val[len+negative] = '\0';
2002 return LDAP_SUCCESS;
2005 /* Index generation function */
2006 static int integerIndexer(
2011 struct berval *prefix,
2018 HASH_CONTEXT HASHcontext;
2019 unsigned char HASHdigest[HASH_BYTES];
2020 struct berval digest;
2021 digest.bv_val = HASHdigest;
2022 digest.bv_len = sizeof(HASHdigest);
2024 for( i=0; values[i].bv_val != NULL; i++ ) {
2025 /* empty - just count them */
2028 /* we should have at least one value at this point */
2031 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2033 slen = syntax->ssyn_oidlen;
2034 mlen = mr->smr_oidlen;
2036 for( i=0; values[i].bv_val != NULL; i++ ) {
2038 xintegerNormalize( syntax, &values[i], &norm );
2040 HASH_Init( &HASHcontext );
2041 if( prefix != NULL && prefix->bv_len > 0 ) {
2042 HASH_Update( &HASHcontext,
2043 prefix->bv_val, prefix->bv_len );
2045 HASH_Update( &HASHcontext,
2046 syntax->ssyn_oid, slen );
2047 HASH_Update( &HASHcontext,
2048 mr->smr_oid, mlen );
2049 HASH_Update( &HASHcontext,
2050 norm.bv_val, norm.bv_len );
2051 HASH_Final( HASHdigest, &HASHcontext );
2053 ber_dupbv( &keys[i], &digest );
2054 ch_free( norm.bv_val );
2057 keys[i].bv_val = NULL;
2059 return LDAP_SUCCESS;
2062 /* Index generation function */
2063 static int integerFilter(
2068 struct berval *prefix,
2069 void * assertedValue,
2074 HASH_CONTEXT HASHcontext;
2075 unsigned char HASHdigest[HASH_BYTES];
2077 struct berval digest;
2078 digest.bv_val = HASHdigest;
2079 digest.bv_len = sizeof(HASHdigest);
2081 slen = syntax->ssyn_oidlen;
2082 mlen = mr->smr_oidlen;
2084 xintegerNormalize( syntax, assertedValue, &norm );
2086 keys = ch_malloc( sizeof( struct berval ) * 2 );
2088 HASH_Init( &HASHcontext );
2089 if( prefix != NULL && prefix->bv_len > 0 ) {
2090 HASH_Update( &HASHcontext,
2091 prefix->bv_val, prefix->bv_len );
2093 HASH_Update( &HASHcontext,
2094 syntax->ssyn_oid, slen );
2095 HASH_Update( &HASHcontext,
2096 mr->smr_oid, mlen );
2097 HASH_Update( &HASHcontext,
2098 norm.bv_val, norm.bv_len );
2099 HASH_Final( HASHdigest, &HASHcontext );
2101 ber_dupbv( &keys[0], &digest );
2102 keys[1].bv_val = NULL;
2103 ch_free( norm.bv_val );
2106 return LDAP_SUCCESS;
2111 countryStringValidate(
2113 struct berval *val )
2115 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
2117 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
2118 return LDAP_INVALID_SYNTAX;
2120 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
2121 return LDAP_INVALID_SYNTAX;
2124 return LDAP_SUCCESS;
2128 printableStringValidate(
2130 struct berval *val )
2134 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2136 for(i=0; i < val->bv_len; i++) {
2137 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
2138 return LDAP_INVALID_SYNTAX;
2142 return LDAP_SUCCESS;
2146 printablesStringValidate(
2148 struct berval *val )
2152 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2154 for(i=0,len=0; i < val->bv_len; i++) {
2155 int c = val->bv_val[i];
2159 return LDAP_INVALID_SYNTAX;
2163 } else if ( SLAP_PRINTABLE(c) ) {
2166 return LDAP_INVALID_SYNTAX;
2171 return LDAP_INVALID_SYNTAX;
2174 return LDAP_SUCCESS;
2180 struct berval *val )
2184 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
2186 for(i=0; i < val->bv_len; i++) {
2187 if( !LDAP_ASCII(val->bv_val[i]) ) {
2188 return LDAP_INVALID_SYNTAX;
2192 return LDAP_SUCCESS;
2196 xIA5StringNormalize(
2199 struct berval *normalized )
2203 assert( val->bv_len );
2207 /* Ignore initial whitespace */
2208 while ( ASCII_SPACE( *p ) ) {
2212 normalized->bv_val = ch_strdup( p );
2213 p = q = normalized->bv_val;
2216 if ( ASCII_SPACE( *p ) ) {
2219 /* Ignore the extra whitespace */
2220 while ( ASCII_SPACE( *p ) ) {
2228 assert( normalized->bv_val <= p );
2232 * If the string ended in space, backup the pointer one
2233 * position. One is enough because the above loop collapsed
2234 * all whitespace to a single space.
2237 if ( ASCII_SPACE( q[-1] ) ) {
2241 /* null terminate */
2244 normalized->bv_len = q - normalized->bv_val;
2246 if( normalized->bv_len == 0 ) {
2247 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
2248 normalized->bv_val[0] = ' ';
2249 normalized->bv_val[1] = '\0';
2250 normalized->bv_len = 1;
2253 return LDAP_SUCCESS;
2262 struct berval *value,
2263 void *assertedValue )
2265 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2268 match = strncmp( value->bv_val,
2269 ((struct berval *) assertedValue)->bv_val,
2274 return LDAP_SUCCESS;
2278 caseExactIA5SubstringsMatch(
2283 struct berval *value,
2284 void *assertedValue )
2287 SubstringsAssertion *sub = assertedValue;
2288 struct berval left = *value;
2292 /* Add up asserted input length */
2293 if( sub->sa_initial.bv_val ) {
2294 inlen += sub->sa_initial.bv_len;
2297 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2298 inlen += sub->sa_any[i].bv_len;
2301 if( sub->sa_final.bv_val ) {
2302 inlen += sub->sa_final.bv_len;
2305 if( sub->sa_initial.bv_val ) {
2306 if( inlen > left.bv_len ) {
2311 match = strncmp( sub->sa_initial.bv_val, left.bv_val,
2312 sub->sa_initial.bv_len );
2318 left.bv_val += sub->sa_initial.bv_len;
2319 left.bv_len -= sub->sa_initial.bv_len;
2320 inlen -= sub->sa_initial.bv_len;
2323 if( sub->sa_final.bv_val ) {
2324 if( inlen > left.bv_len ) {
2329 match = strncmp( sub->sa_final.bv_val,
2330 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2331 sub->sa_final.bv_len );
2337 left.bv_len -= sub->sa_final.bv_len;
2338 inlen -= sub->sa_final.bv_len;
2342 for(i=0; sub->sa_any[i].bv_val; i++) {
2347 if( inlen > left.bv_len ) {
2348 /* not enough length */
2353 if( sub->sa_any[i].bv_len == 0 ) {
2357 p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
2364 idx = p - left.bv_val;
2366 if( idx >= left.bv_len ) {
2367 /* this shouldn't happen */
2374 if( sub->sa_any[i].bv_len > left.bv_len ) {
2375 /* not enough left */
2380 match = strncmp( left.bv_val,
2381 sub->sa_any[i].bv_val,
2382 sub->sa_any[i].bv_len );
2390 left.bv_val += sub->sa_any[i].bv_len;
2391 left.bv_len -= sub->sa_any[i].bv_len;
2392 inlen -= sub->sa_any[i].bv_len;
2398 return LDAP_SUCCESS;
2401 /* Index generation function */
2402 static int caseExactIA5Indexer(
2407 struct berval *prefix,
2414 HASH_CONTEXT HASHcontext;
2415 unsigned char HASHdigest[HASH_BYTES];
2416 struct berval digest;
2417 digest.bv_val = HASHdigest;
2418 digest.bv_len = sizeof(HASHdigest);
2420 for( i=0; values[i].bv_val != NULL; i++ ) {
2421 /* empty - just count them */
2424 /* we should have at least one value at this point */
2427 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2429 slen = syntax->ssyn_oidlen;
2430 mlen = mr->smr_oidlen;
2432 for( i=0; values[i].bv_val != NULL; i++ ) {
2433 struct berval *value = &values[i];
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[i], &digest );
2451 keys[i].bv_val = NULL;
2453 return LDAP_SUCCESS;
2456 /* Index generation function */
2457 static int caseExactIA5Filter(
2462 struct berval *prefix,
2463 void * assertedValue,
2468 HASH_CONTEXT HASHcontext;
2469 unsigned char HASHdigest[HASH_BYTES];
2470 struct berval *value;
2471 struct berval digest;
2472 digest.bv_val = HASHdigest;
2473 digest.bv_len = sizeof(HASHdigest);
2475 slen = syntax->ssyn_oidlen;
2476 mlen = mr->smr_oidlen;
2478 value = (struct berval *) assertedValue;
2480 keys = ch_malloc( sizeof( struct berval ) * 2 );
2482 HASH_Init( &HASHcontext );
2483 if( prefix != NULL && prefix->bv_len > 0 ) {
2484 HASH_Update( &HASHcontext,
2485 prefix->bv_val, prefix->bv_len );
2487 HASH_Update( &HASHcontext,
2488 syntax->ssyn_oid, slen );
2489 HASH_Update( &HASHcontext,
2490 mr->smr_oid, mlen );
2491 HASH_Update( &HASHcontext,
2492 value->bv_val, value->bv_len );
2493 HASH_Final( HASHdigest, &HASHcontext );
2495 ber_dupbv( &keys[0], &digest );
2496 keys[1].bv_val = NULL;
2499 return LDAP_SUCCESS;
2502 /* Substrings Index generation function */
2503 static int caseExactIA5SubstringsIndexer(
2508 struct berval *prefix,
2515 HASH_CONTEXT HASHcontext;
2516 unsigned char HASHdigest[HASH_BYTES];
2517 struct berval digest;
2518 digest.bv_val = HASHdigest;
2519 digest.bv_len = sizeof(HASHdigest);
2521 /* we should have at least one value at this point */
2522 assert( values != NULL && values[0].bv_val != NULL );
2525 for( i=0; values[i].bv_val != NULL; i++ ) {
2526 /* count number of indices to generate */
2527 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
2531 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2532 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2533 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2534 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2536 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2540 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
2541 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2542 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2546 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2547 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2548 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
2549 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
2551 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
2557 /* no keys to generate */
2559 return LDAP_SUCCESS;
2562 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2564 slen = syntax->ssyn_oidlen;
2565 mlen = mr->smr_oidlen;
2568 for( i=0; values[i].bv_val != NULL; i++ ) {
2570 struct berval *value;
2573 if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
2575 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
2576 ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
2578 char pre = SLAP_INDEX_SUBSTR_PREFIX;
2579 max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
2581 for( j=0; j<max; j++ ) {
2582 HASH_Init( &HASHcontext );
2583 if( prefix != NULL && prefix->bv_len > 0 ) {
2584 HASH_Update( &HASHcontext,
2585 prefix->bv_val, prefix->bv_len );
2588 HASH_Update( &HASHcontext,
2589 &pre, sizeof( pre ) );
2590 HASH_Update( &HASHcontext,
2591 syntax->ssyn_oid, slen );
2592 HASH_Update( &HASHcontext,
2593 mr->smr_oid, mlen );
2594 HASH_Update( &HASHcontext,
2596 SLAP_INDEX_SUBSTR_MAXLEN );
2597 HASH_Final( HASHdigest, &HASHcontext );
2599 ber_dupbv( &keys[nkeys++], &digest );
2603 max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2604 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2606 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
2609 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
2610 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2611 HASH_Init( &HASHcontext );
2612 if( prefix != NULL && prefix->bv_len > 0 ) {
2613 HASH_Update( &HASHcontext,
2614 prefix->bv_val, prefix->bv_len );
2616 HASH_Update( &HASHcontext,
2617 &pre, sizeof( pre ) );
2618 HASH_Update( &HASHcontext,
2619 syntax->ssyn_oid, slen );
2620 HASH_Update( &HASHcontext,
2621 mr->smr_oid, mlen );
2622 HASH_Update( &HASHcontext,
2624 HASH_Final( HASHdigest, &HASHcontext );
2626 ber_dupbv( &keys[nkeys++], &digest );
2629 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
2630 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2631 HASH_Init( &HASHcontext );
2632 if( prefix != NULL && prefix->bv_len > 0 ) {
2633 HASH_Update( &HASHcontext,
2634 prefix->bv_val, prefix->bv_len );
2636 HASH_Update( &HASHcontext,
2637 &pre, sizeof( pre ) );
2638 HASH_Update( &HASHcontext,
2639 syntax->ssyn_oid, slen );
2640 HASH_Update( &HASHcontext,
2641 mr->smr_oid, mlen );
2642 HASH_Update( &HASHcontext,
2643 &value->bv_val[value->bv_len-j], j );
2644 HASH_Final( HASHdigest, &HASHcontext );
2646 ber_dupbv( &keys[nkeys++], &digest );
2653 keys[nkeys].bv_val = NULL;
2660 return LDAP_SUCCESS;
2663 static int caseExactIA5SubstringsFilter(
2668 struct berval *prefix,
2669 void * assertedValue,
2672 SubstringsAssertion *sa = assertedValue;
2674 ber_len_t nkeys = 0;
2675 size_t slen, mlen, klen;
2677 HASH_CONTEXT HASHcontext;
2678 unsigned char HASHdigest[HASH_BYTES];
2679 struct berval *value;
2680 struct berval digest;
2682 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2683 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2688 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2690 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2691 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
2692 /* don't bother accounting for stepping */
2693 nkeys += sa->sa_any[i].bv_len -
2694 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
2699 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2700 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2707 return LDAP_SUCCESS;
2710 digest.bv_val = HASHdigest;
2711 digest.bv_len = sizeof(HASHdigest);
2713 slen = syntax->ssyn_oidlen;
2714 mlen = mr->smr_oidlen;
2716 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
2719 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
2720 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2722 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
2723 value = &sa->sa_initial;
2725 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2726 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2728 HASH_Init( &HASHcontext );
2729 if( prefix != NULL && prefix->bv_len > 0 ) {
2730 HASH_Update( &HASHcontext,
2731 prefix->bv_val, prefix->bv_len );
2733 HASH_Update( &HASHcontext,
2734 &pre, sizeof( pre ) );
2735 HASH_Update( &HASHcontext,
2736 syntax->ssyn_oid, slen );
2737 HASH_Update( &HASHcontext,
2738 mr->smr_oid, mlen );
2739 HASH_Update( &HASHcontext,
2740 value->bv_val, klen );
2741 HASH_Final( HASHdigest, &HASHcontext );
2743 ber_dupbv( &keys[nkeys++], &digest );
2746 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
2748 pre = SLAP_INDEX_SUBSTR_PREFIX;
2749 klen = SLAP_INDEX_SUBSTR_MAXLEN;
2751 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
2752 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
2756 value = &sa->sa_any[i];
2759 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
2760 j += SLAP_INDEX_SUBSTR_STEP )
2762 HASH_Init( &HASHcontext );
2763 if( prefix != NULL && prefix->bv_len > 0 ) {
2764 HASH_Update( &HASHcontext,
2765 prefix->bv_val, prefix->bv_len );
2767 HASH_Update( &HASHcontext,
2768 &pre, sizeof( pre ) );
2769 HASH_Update( &HASHcontext,
2770 syntax->ssyn_oid, slen );
2771 HASH_Update( &HASHcontext,
2772 mr->smr_oid, mlen );
2773 HASH_Update( &HASHcontext,
2774 &value->bv_val[j], klen );
2775 HASH_Final( HASHdigest, &HASHcontext );
2777 ber_dupbv( &keys[nkeys++], &digest );
2782 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
2783 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
2785 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
2786 value = &sa->sa_final;
2788 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
2789 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
2791 HASH_Init( &HASHcontext );
2792 if( prefix != NULL && prefix->bv_len > 0 ) {
2793 HASH_Update( &HASHcontext,
2794 prefix->bv_val, prefix->bv_len );
2796 HASH_Update( &HASHcontext,
2797 &pre, sizeof( pre ) );
2798 HASH_Update( &HASHcontext,
2799 syntax->ssyn_oid, slen );
2800 HASH_Update( &HASHcontext,
2801 mr->smr_oid, mlen );
2802 HASH_Update( &HASHcontext,
2803 &value->bv_val[value->bv_len-klen], klen );
2804 HASH_Final( HASHdigest, &HASHcontext );
2806 ber_dupbv( &keys[nkeys++], &digest );
2810 keys[nkeys].bv_val = NULL;
2817 return LDAP_SUCCESS;
2826 struct berval *value,
2827 void *assertedValue )
2829 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
2831 if( match == 0 && value->bv_len ) {
2832 match = strncasecmp( value->bv_val,
2833 ((struct berval *) assertedValue)->bv_val,
2838 return LDAP_SUCCESS;
2842 caseIgnoreIA5SubstringsMatch(
2847 struct berval *value,
2848 void *assertedValue )
2851 SubstringsAssertion *sub = assertedValue;
2852 struct berval left = *value;
2856 /* Add up asserted input length */
2857 if( sub->sa_initial.bv_val ) {
2858 inlen += sub->sa_initial.bv_len;
2861 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
2862 inlen += sub->sa_any[i].bv_len;
2865 if( sub->sa_final.bv_val ) {
2866 inlen += sub->sa_final.bv_len;
2869 if( sub->sa_initial.bv_val ) {
2870 if( inlen > left.bv_len ) {
2875 match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
2876 sub->sa_initial.bv_len );
2882 left.bv_val += sub->sa_initial.bv_len;
2883 left.bv_len -= sub->sa_initial.bv_len;
2884 inlen -= sub->sa_initial.bv_len;
2887 if( sub->sa_final.bv_val ) {
2888 if( inlen > left.bv_len ) {
2893 match = strncasecmp( sub->sa_final.bv_val,
2894 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
2895 sub->sa_final.bv_len );
2901 left.bv_len -= sub->sa_final.bv_len;
2902 inlen -= sub->sa_final.bv_len;
2906 for(i=0; sub->sa_any[i].bv_val; i++) {
2911 if( inlen > left.bv_len ) {
2912 /* not enough length */
2917 if( sub->sa_any[i].bv_len == 0 ) {
2921 p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
2928 assert( idx < left.bv_len );
2929 if( idx >= left.bv_len ) {
2930 /* this shouldn't happen */
2937 if( sub->sa_any[i].bv_len > left.bv_len ) {
2938 /* not enough left */
2943 match = strncasecmp( left.bv_val,
2944 sub->sa_any[i].bv_val,
2945 sub->sa_any[i].bv_len );
2954 left.bv_val += sub->sa_any[i].bv_len;
2955 left.bv_len -= sub->sa_any[i].bv_len;
2956 inlen -= sub->sa_any[i].bv_len;
2962 return LDAP_SUCCESS;
2965 /* Index generation function */
2966 static int caseIgnoreIA5Indexer(
2971 struct berval *prefix,
2976 int rc = LDAP_SUCCESS;
2979 HASH_CONTEXT HASHcontext;
2980 unsigned char HASHdigest[HASH_BYTES];
2981 struct berval digest;
2982 digest.bv_val = HASHdigest;
2983 digest.bv_len = sizeof(HASHdigest);
2985 /* we should have at least one value at this point */
2986 assert( values != NULL && values[0].bv_val != NULL );
2988 for( i=0; values[i].bv_val != NULL; i++ ) {
2989 /* just count them */
2992 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2994 slen = syntax->ssyn_oidlen;
2995 mlen = mr->smr_oidlen;
2997 for( i=0; values[i].bv_val != NULL; i++ ) {
2998 struct berval value;
3000 if( mr->smr_normalize ) {
3001 rc = (mr->smr_normalize)( use, syntax, mr, &values[i], &value );
3002 if( rc != LDAP_SUCCESS ) {
3005 #ifndef SLAP_NVALUES
3006 } else if ( mr->smr_syntax->ssyn_normalize ) {
3007 rc = (mr->smr_syntax->ssyn_normalize)( syntax, &values[i], &value );
3008 if( rc != LDAP_SUCCESS ) {
3013 ber_dupbv( &value, &values[i] );
3016 ldap_pvt_str2lower( value.bv_val );
3018 HASH_Init( &HASHcontext );
3019 if( prefix != NULL && prefix->bv_len > 0 ) {
3020 HASH_Update( &HASHcontext,
3021 prefix->bv_val, prefix->bv_len );
3023 HASH_Update( &HASHcontext,
3024 syntax->ssyn_oid, slen );
3025 HASH_Update( &HASHcontext,
3026 mr->smr_oid, mlen );
3027 HASH_Update( &HASHcontext,
3028 value.bv_val, value.bv_len );
3029 HASH_Final( HASHdigest, &HASHcontext );
3031 free( value.bv_val );
3033 ber_dupbv( &keys[i], &digest );
3036 keys[i].bv_val = NULL;
3037 if( rc != LDAP_SUCCESS ) {
3038 ber_bvarray_free( keys );
3045 /* Index generation function */
3046 static int caseIgnoreIA5Filter(
3051 struct berval *prefix,
3052 void * assertedValue,
3057 HASH_CONTEXT HASHcontext;
3058 unsigned char HASHdigest[HASH_BYTES];
3059 struct berval value;
3060 struct berval digest;
3061 digest.bv_val = HASHdigest;
3062 digest.bv_len = sizeof(HASHdigest);
3064 slen = syntax->ssyn_oidlen;
3065 mlen = mr->smr_oidlen;
3067 ber_dupbv( &value, (struct berval *) assertedValue );
3068 ldap_pvt_str2lower( value.bv_val );
3070 keys = ch_malloc( sizeof( struct berval ) * 2 );
3072 HASH_Init( &HASHcontext );
3073 if( prefix != NULL && prefix->bv_len > 0 ) {
3074 HASH_Update( &HASHcontext,
3075 prefix->bv_val, prefix->bv_len );
3077 HASH_Update( &HASHcontext,
3078 syntax->ssyn_oid, slen );
3079 HASH_Update( &HASHcontext,
3080 mr->smr_oid, mlen );
3081 HASH_Update( &HASHcontext,
3082 value.bv_val, value.bv_len );
3083 HASH_Final( HASHdigest, &HASHcontext );
3085 ber_dupbv( &keys[0], &digest );
3086 keys[1].bv_val = NULL;
3088 free( value.bv_val );
3092 return LDAP_SUCCESS;
3095 /* Substrings Index generation function */
3096 static int caseIgnoreIA5SubstringsIndexer(
3101 struct berval *prefix,
3108 HASH_CONTEXT HASHcontext;
3109 unsigned char HASHdigest[HASH_BYTES];
3110 struct berval digest;
3111 digest.bv_val = HASHdigest;
3112 digest.bv_len = sizeof(HASHdigest);
3114 /* we should have at least one value at this point */
3115 assert( values != NULL && values[0].bv_val != NULL );
3118 for( i=0; values[i].bv_val != NULL; i++ ) {
3119 /* count number of indices to generate */
3120 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
3124 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3125 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3126 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3127 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3129 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3133 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
3134 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3135 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3139 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3140 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3141 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
3142 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
3144 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
3150 /* no keys to generate */
3152 return LDAP_SUCCESS;
3155 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3157 slen = syntax->ssyn_oidlen;
3158 mlen = mr->smr_oidlen;
3161 for( i=0; values[i].bv_val != NULL; i++ ) {
3163 struct berval value;
3165 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
3167 ber_dupbv( &value, &values[i] );
3168 ldap_pvt_str2lower( value.bv_val );
3170 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
3171 ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
3173 char pre = SLAP_INDEX_SUBSTR_PREFIX;
3174 max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
3176 for( j=0; j<max; j++ ) {
3177 HASH_Init( &HASHcontext );
3178 if( prefix != NULL && prefix->bv_len > 0 ) {
3179 HASH_Update( &HASHcontext,
3180 prefix->bv_val, prefix->bv_len );
3183 HASH_Update( &HASHcontext,
3184 &pre, sizeof( pre ) );
3185 HASH_Update( &HASHcontext,
3186 syntax->ssyn_oid, slen );
3187 HASH_Update( &HASHcontext,
3188 mr->smr_oid, mlen );
3189 HASH_Update( &HASHcontext,
3191 SLAP_INDEX_SUBSTR_MAXLEN );
3192 HASH_Final( HASHdigest, &HASHcontext );
3194 ber_dupbv( &keys[nkeys++], &digest );
3198 max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3199 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3201 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
3204 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
3205 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3206 HASH_Init( &HASHcontext );
3207 if( prefix != NULL && prefix->bv_len > 0 ) {
3208 HASH_Update( &HASHcontext,
3209 prefix->bv_val, prefix->bv_len );
3211 HASH_Update( &HASHcontext,
3212 &pre, sizeof( pre ) );
3213 HASH_Update( &HASHcontext,
3214 syntax->ssyn_oid, slen );
3215 HASH_Update( &HASHcontext,
3216 mr->smr_oid, mlen );
3217 HASH_Update( &HASHcontext,
3219 HASH_Final( HASHdigest, &HASHcontext );
3221 ber_dupbv( &keys[nkeys++], &digest );
3224 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
3225 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3226 HASH_Init( &HASHcontext );
3227 if( prefix != NULL && prefix->bv_len > 0 ) {
3228 HASH_Update( &HASHcontext,
3229 prefix->bv_val, prefix->bv_len );
3231 HASH_Update( &HASHcontext,
3232 &pre, sizeof( pre ) );
3233 HASH_Update( &HASHcontext,
3234 syntax->ssyn_oid, slen );
3235 HASH_Update( &HASHcontext,
3236 mr->smr_oid, mlen );
3237 HASH_Update( &HASHcontext,
3238 &value.bv_val[value.bv_len-j], j );
3239 HASH_Final( HASHdigest, &HASHcontext );
3241 ber_dupbv( &keys[nkeys++], &digest );
3246 free( value.bv_val );
3250 keys[nkeys].bv_val = NULL;
3257 return LDAP_SUCCESS;
3260 static int caseIgnoreIA5SubstringsFilter(
3265 struct berval *prefix,
3266 void * assertedValue,
3269 SubstringsAssertion *sa = assertedValue;
3271 ber_len_t nkeys = 0;
3272 size_t slen, mlen, klen;
3274 HASH_CONTEXT HASHcontext;
3275 unsigned char HASHdigest[HASH_BYTES];
3276 struct berval value;
3277 struct berval digest;
3279 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3280 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3285 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3287 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3288 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
3289 /* don't bother accounting for stepping */
3290 nkeys += sa->sa_any[i].bv_len -
3291 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
3296 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3297 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3304 return LDAP_SUCCESS;
3307 digest.bv_val = HASHdigest;
3308 digest.bv_len = sizeof(HASHdigest);
3310 slen = syntax->ssyn_oidlen;
3311 mlen = mr->smr_oidlen;
3313 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
3316 if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
3317 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3319 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
3320 ber_dupbv( &value, &sa->sa_initial );
3321 ldap_pvt_str2lower( value.bv_val );
3323 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3324 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3326 HASH_Init( &HASHcontext );
3327 if( prefix != NULL && prefix->bv_len > 0 ) {
3328 HASH_Update( &HASHcontext,
3329 prefix->bv_val, prefix->bv_len );
3331 HASH_Update( &HASHcontext,
3332 &pre, sizeof( pre ) );
3333 HASH_Update( &HASHcontext,
3334 syntax->ssyn_oid, slen );
3335 HASH_Update( &HASHcontext,
3336 mr->smr_oid, mlen );
3337 HASH_Update( &HASHcontext,
3338 value.bv_val, klen );
3339 HASH_Final( HASHdigest, &HASHcontext );
3341 free( value.bv_val );
3342 ber_dupbv( &keys[nkeys++], &digest );
3345 if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
3347 pre = SLAP_INDEX_SUBSTR_PREFIX;
3348 klen = SLAP_INDEX_SUBSTR_MAXLEN;
3350 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
3351 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
3355 ber_dupbv( &value, &sa->sa_any[i] );
3356 ldap_pvt_str2lower( value.bv_val );
3359 j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
3360 j += SLAP_INDEX_SUBSTR_STEP )
3362 HASH_Init( &HASHcontext );
3363 if( prefix != NULL && prefix->bv_len > 0 ) {
3364 HASH_Update( &HASHcontext,
3365 prefix->bv_val, prefix->bv_len );
3367 HASH_Update( &HASHcontext,
3368 &pre, sizeof( pre ) );
3369 HASH_Update( &HASHcontext,
3370 syntax->ssyn_oid, slen );
3371 HASH_Update( &HASHcontext,
3372 mr->smr_oid, mlen );
3373 HASH_Update( &HASHcontext,
3374 &value.bv_val[j], klen );
3375 HASH_Final( HASHdigest, &HASHcontext );
3377 ber_dupbv( &keys[nkeys++], &digest );
3380 free( value.bv_val );
3384 if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
3385 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
3387 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
3388 ber_dupbv( &value, &sa->sa_final );
3389 ldap_pvt_str2lower( value.bv_val );
3391 klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
3392 ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
3394 HASH_Init( &HASHcontext );
3395 if( prefix != NULL && prefix->bv_len > 0 ) {
3396 HASH_Update( &HASHcontext,
3397 prefix->bv_val, prefix->bv_len );
3399 HASH_Update( &HASHcontext,
3400 &pre, sizeof( pre ) );
3401 HASH_Update( &HASHcontext,
3402 syntax->ssyn_oid, slen );
3403 HASH_Update( &HASHcontext,
3404 mr->smr_oid, mlen );
3405 HASH_Update( &HASHcontext,
3406 &value.bv_val[value.bv_len-klen], klen );
3407 HASH_Final( HASHdigest, &HASHcontext );
3409 free( value.bv_val );
3410 ber_dupbv( &keys[nkeys++], &digest );
3414 keys[nkeys].bv_val = NULL;
3421 return LDAP_SUCCESS;
3425 numericStringValidate(
3431 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
3433 for(i=0; i < in->bv_len; i++) {
3434 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
3435 return LDAP_INVALID_SYNTAX;
3439 return LDAP_SUCCESS;
3443 xnumericStringNormalize(
3446 struct berval *normalized )
3448 /* removal all spaces */
3451 assert( val->bv_len );
3453 normalized->bv_val = ch_malloc( val->bv_len + 1 );
3456 q = normalized->bv_val;
3459 if ( ASCII_SPACE( *p ) ) {
3460 /* Ignore whitespace */
3467 /* we should have copied no more then is in val */
3468 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
3470 /* null terminate */
3473 normalized->bv_len = q - normalized->bv_val;
3475 if( normalized->bv_len == 0 ) {
3476 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
3477 normalized->bv_val[0] = ' ';
3478 normalized->bv_val[1] = '\0';
3479 normalized->bv_len = 1;
3482 return LDAP_SUCCESS;
3486 objectIdentifierFirstComponentMatch(
3491 struct berval *value,
3492 void *assertedValue )
3494 int rc = LDAP_SUCCESS;
3496 struct berval *asserted = (struct berval *) assertedValue;
3500 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
3501 return LDAP_INVALID_SYNTAX;
3504 /* trim leading white space */
3505 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
3509 /* grab next word */
3510 oid.bv_val = &value->bv_val[i];
3511 j = value->bv_len - i;
3512 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
3517 /* insert attributeTypes, objectclass check here */
3518 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
3519 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
3522 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
3523 MatchingRule *asserted_mr = mr_bvfind( asserted );
3524 MatchingRule *stored_mr = mr_bvfind( &oid );
3526 if( asserted_mr == NULL ) {
3527 rc = SLAPD_COMPARE_UNDEFINED;
3529 match = asserted_mr != stored_mr;
3532 } else if ( !strcmp( syntax->ssyn_oid,
3533 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
3535 AttributeType *asserted_at = at_bvfind( asserted );
3536 AttributeType *stored_at = at_bvfind( &oid );
3538 if( asserted_at == NULL ) {
3539 rc = SLAPD_COMPARE_UNDEFINED;
3541 match = asserted_at != stored_at;
3544 } else if ( !strcmp( syntax->ssyn_oid,
3545 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
3547 ObjectClass *asserted_oc = oc_bvfind( asserted );
3548 ObjectClass *stored_oc = oc_bvfind( &oid );
3550 if( asserted_oc == NULL ) {
3551 rc = SLAPD_COMPARE_UNDEFINED;
3553 match = asserted_oc != stored_oc;
3559 LDAP_LOG( CONFIG, ENTRY,
3560 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
3561 match, value->bv_val, asserted->bv_val );
3563 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
3564 "%d\n\t\"%s\"\n\t\"%s\"\n",
3565 match, value->bv_val, asserted->bv_val );
3568 if( rc == LDAP_SUCCESS ) *matchp = match;
3578 struct berval *value,
3579 void *assertedValue )
3581 long lValue, lAssertedValue;
3583 /* safe to assume integers are NUL terminated? */
3584 lValue = strtol(value->bv_val, NULL, 10);
3585 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
3586 return LDAP_CONSTRAINT_VIOLATION;
3589 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3590 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
3591 && errno == ERANGE )
3593 return LDAP_CONSTRAINT_VIOLATION;
3596 *matchp = (lValue & lAssertedValue) ? 0 : 1;
3597 return LDAP_SUCCESS;
3606 struct berval *value,
3607 void *assertedValue )
3609 long lValue, lAssertedValue;
3611 /* safe to assume integers are NUL terminated? */
3612 lValue = strtol(value->bv_val, NULL, 10);
3613 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
3614 return LDAP_CONSTRAINT_VIOLATION;
3617 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
3618 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
3619 && errno == ERANGE )
3621 return LDAP_CONSTRAINT_VIOLATION;
3624 *matchp = (lValue | lAssertedValue) ? 0 : -1;
3625 return LDAP_SUCCESS;
3629 #include <openssl/x509.h>
3630 #include <openssl/err.h>
3633 * Next function returns a string representation of a ASN1_INTEGER.
3634 * It works for unlimited lengths.
3637 static struct berval *
3638 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
3642 static char digit[] = "0123456789";
3644 /* We work backwards, make it fill from the end of buf */
3645 p = buf + sizeof(buf) - 1;
3648 if ( a == NULL || a->length == 0 ) {
3656 /* We want to preserve the original */
3657 copy = ch_malloc(n*sizeof(unsigned int));
3658 for (i = 0; i<n; i++) {
3659 copy[i] = a->data[i];
3663 * base indicates the index of the most significant
3664 * byte that might be nonzero. When it goes off the
3665 * end, we now there is nothing left to do.
3671 for (i = base; i<n; i++ ) {
3672 copy[i] += carry*256;
3673 carry = copy[i] % 10;
3678 * Way too large, we need to leave
3679 * room for sign if negative
3684 *--p = digit[carry];
3686 if (copy[base] == 0) base++;
3691 if ( a->type == V_ASN1_NEG_INTEGER ) {
3695 return ber_str2bv( p, 0, 1, bv );
3699 * Given a certificate in DER format, extract the corresponding
3700 * assertion value for certificateExactMatch
3703 certificateExactConvert(
3705 struct berval * out )
3708 unsigned char *p = in->bv_val;
3709 struct berval serial;
3710 struct berval issuer_dn;
3712 xcert = d2i_X509(NULL, &p, in->bv_len);
3715 LDAP_LOG( CONFIG, ENTRY,
3716 "certificateExactConvert: error parsing cert: %s\n",
3717 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3719 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
3720 "error parsing cert: %s\n",
3721 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3723 return LDAP_INVALID_SYNTAX;
3726 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
3728 return LDAP_INVALID_SYNTAX;
3730 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
3734 ber_memfree(serial.bv_val);
3735 return LDAP_INVALID_SYNTAX;
3740 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
3741 out->bv_val = ch_malloc(out->bv_len);
3743 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
3745 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
3747 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
3748 p += issuer_dn.bv_len;
3752 LDAP_LOG( CONFIG, ARGS,
3753 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
3755 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
3757 out->bv_val, NULL, NULL );
3760 ber_memfree(serial.bv_val);
3761 ber_memfree(issuer_dn.bv_val);
3763 return LDAP_SUCCESS;
3767 serial_and_issuer_parse(
3768 struct berval *assertion,
3769 struct berval *serial,
3770 struct berval *issuer_dn
3778 begin = assertion->bv_val;
3779 end = assertion->bv_val+assertion->bv_len-1;
3780 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
3781 if ( p > end ) return LDAP_INVALID_SYNTAX;
3783 /* p now points at the $ sign, now use
3784 * begin and end to delimit the serial number
3786 while (ASCII_SPACE(*begin)) begin++;
3788 while (ASCII_SPACE(*end)) end--;
3790 if( end <= begin ) return LDAP_INVALID_SYNTAX;
3792 bv.bv_len = end-begin+1;
3794 ber_dupbv(serial, &bv);
3796 /* now extract the issuer, remember p was at the dollar sign */
3798 end = assertion->bv_val+assertion->bv_len-1;
3799 while (ASCII_SPACE(*begin)) begin++;
3800 /* should we trim spaces at the end too? is it safe always? no, no */
3802 if( end <= begin ) return LDAP_INVALID_SYNTAX;
3805 bv.bv_len = end-begin+1;
3808 dnNormalize2( NULL, &bv, issuer_dn );
3811 return LDAP_SUCCESS;
3815 certificateExactMatch(
3820 struct berval *value,
3821 void *assertedValue )
3824 unsigned char *p = value->bv_val;
3825 struct berval serial;
3826 struct berval issuer_dn;
3827 struct berval asserted_serial;
3828 struct berval asserted_issuer_dn;
3831 xcert = d2i_X509(NULL, &p, value->bv_len);
3834 LDAP_LOG( CONFIG, ENTRY,
3835 "certificateExactMatch: error parsing cert: %s\n",
3836 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
3838 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
3839 "error parsing cert: %s\n",
3840 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
3842 return LDAP_INVALID_SYNTAX;
3845 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3846 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
3850 serial_and_issuer_parse(assertedValue,
3851 &asserted_serial, &asserted_issuer_dn);
3856 slap_schema.si_syn_integer,
3857 slap_schema.si_mr_integerMatch,
3860 if ( ret == LDAP_SUCCESS ) {
3861 if ( *matchp == 0 ) {
3862 /* We need to normalize everything for dnMatch */
3866 slap_schema.si_syn_distinguishedName,
3867 slap_schema.si_mr_distinguishedNameMatch,
3869 &asserted_issuer_dn);
3874 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
3875 "%d\n\t\"%s $ %s\"\n",
3876 *matchp, serial.bv_val, issuer_dn.bv_val );
3877 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
3878 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3881 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
3882 "%d\n\t\"%s $ %s\"\n",
3883 *matchp, serial.bv_val, issuer_dn.bv_val );
3884 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
3885 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
3889 ber_memfree(serial.bv_val);
3890 ber_memfree(issuer_dn.bv_val);
3891 ber_memfree(asserted_serial.bv_val);
3892 ber_memfree(asserted_issuer_dn.bv_val);
3898 * Index generation function
3899 * We just index the serials, in most scenarios the issuer DN is one of
3900 * a very small set of values.
3902 static int certificateExactIndexer(
3907 struct berval *prefix,
3915 struct berval serial;
3917 /* we should have at least one value at this point */
3918 assert( values != NULL && values[0].bv_val != NULL );
3920 for( i=0; values[i].bv_val != NULL; i++ ) {
3921 /* empty -- just count them */
3924 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
3926 for( i=0; values[i].bv_val != NULL; i++ ) {
3927 p = values[i].bv_val;
3928 xcert = d2i_X509(NULL, &p, values[i].bv_len);
3931 LDAP_LOG( CONFIG, ENTRY,
3932 "certificateExactIndexer: error parsing cert: %s\n",
3933 ERR_error_string(ERR_get_error(),NULL), 0, 0);
3935 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3936 "error parsing cert: %s\n",
3937 ERR_error_string(ERR_get_error(),NULL),
3940 /* Do we leak keys on error? */
3941 return LDAP_INVALID_SYNTAX;
3944 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
3946 xintegerNormalize( slap_schema.si_syn_integer,
3947 &serial, &keys[i] );
3948 ber_memfree(serial.bv_val);
3950 LDAP_LOG( CONFIG, ENTRY,
3951 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
3953 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
3960 keys[i].bv_val = NULL;
3962 return LDAP_SUCCESS;
3965 /* Index generation function */
3966 /* We think this is always called with a value in matching rule syntax */
3967 static int certificateExactFilter(
3972 struct berval *prefix,
3973 void * assertedValue,
3977 struct berval asserted_serial;
3980 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
3981 if( ret != LDAP_SUCCESS ) return ret;
3983 keys = ch_malloc( sizeof( struct berval ) * 2 );
3984 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
3985 keys[1].bv_val = NULL;
3988 ber_memfree(asserted_serial.bv_val);
3989 return LDAP_SUCCESS;
3994 check_time_syntax (struct berval *val,
3998 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
3999 static int mdays[2][12] = {
4000 /* non-leap years */
4001 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
4003 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
4006 int part, c, tzoffset, leapyear = 0 ;
4008 if( val->bv_len == 0 ) {
4009 return LDAP_INVALID_SYNTAX;
4012 p = (char *)val->bv_val;
4013 e = p + val->bv_len;
4015 /* Ignore initial whitespace */
4016 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4020 if (e - p < 13 - (2 * start)) {
4021 return LDAP_INVALID_SYNTAX;
4024 for (part = 0; part < 9; part++) {
4028 for (part = start; part < 7; part++) {
4030 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
4037 return LDAP_INVALID_SYNTAX;
4039 if (c < 0 || c > 9) {
4040 return LDAP_INVALID_SYNTAX;
4046 return LDAP_INVALID_SYNTAX;
4048 if (c < 0 || c > 9) {
4049 return LDAP_INVALID_SYNTAX;
4054 if (part == 2 || part == 3) {
4057 if (parts[part] < 0) {
4058 return LDAP_INVALID_SYNTAX;
4060 if (parts[part] > ceiling[part]) {
4061 return LDAP_INVALID_SYNTAX;
4065 /* leapyear check for the Gregorian calendar (year>1581) */
4066 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
4067 ((parts[0] % 4 == 0) && (parts[1] == 0)))
4072 if (parts[3] > mdays[leapyear][parts[2]]) {
4073 return LDAP_INVALID_SYNTAX;
4078 tzoffset = 0; /* UTC */
4079 } else if (c != '+' && c != '-') {
4080 return LDAP_INVALID_SYNTAX;
4084 } else /* c == '+' */ {
4089 return LDAP_INVALID_SYNTAX;
4092 for (part = 7; part < 9; part++) {
4094 if (c < 0 || c > 9) {
4095 return LDAP_INVALID_SYNTAX;
4100 if (c < 0 || c > 9) {
4101 return LDAP_INVALID_SYNTAX;
4105 if (parts[part] < 0 || parts[part] > ceiling[part]) {
4106 return LDAP_INVALID_SYNTAX;
4111 /* Ignore trailing whitespace */
4112 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
4116 return LDAP_INVALID_SYNTAX;
4119 switch ( tzoffset ) {
4120 case -1: /* negativ offset to UTC, ie west of Greenwich */
4121 parts[4] += parts[7];
4122 parts[5] += parts[8];
4123 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
4127 c = mdays[leapyear][parts[2]];
4129 if (parts[part] > c) {
4130 parts[part] -= c + 1;
4135 case 1: /* positive offset to UTC, ie east of Greenwich */
4136 parts[4] -= parts[7];
4137 parts[5] -= parts[8];
4138 for (part = 6; --part > 0; ) {
4142 /* first arg to % needs to be non negativ */
4143 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
4145 if (parts[part] < 0) {
4146 parts[part] += c + 1;
4151 case 0: /* already UTC */
4155 return LDAP_SUCCESS;
4158 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4163 struct berval *normalized )
4167 rc = check_time_syntax(val, 1, parts);
4168 if (rc != LDAP_SUCCESS) {
4172 normalized->bv_val = ch_malloc( 14 );
4173 if ( normalized->bv_val == NULL ) {
4174 return LBER_ERROR_MEMORY;
4177 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
4178 parts[1], parts[2] + 1, parts[3] + 1,
4179 parts[4], parts[5], parts[6] );
4180 normalized->bv_len = 13;
4182 return LDAP_SUCCESS;
4186 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4194 return check_time_syntax(in, 1, parts);
4199 generalizedTimeValidate(
4205 return check_time_syntax(in, 0, parts);
4209 xgeneralizedTimeNormalize(
4212 struct berval *normalized )
4216 rc = check_time_syntax(val, 0, parts);
4217 if (rc != LDAP_SUCCESS) {
4221 normalized->bv_val = ch_malloc( 16 );
4222 if ( normalized->bv_val == NULL ) {
4223 return LBER_ERROR_MEMORY;
4226 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
4227 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
4228 parts[4], parts[5], parts[6] );
4229 normalized->bv_len = 15;
4231 return LDAP_SUCCESS;
4235 nisNetgroupTripleValidate(
4237 struct berval *val )
4242 if ( val->bv_len == 0 ) {
4243 return LDAP_INVALID_SYNTAX;
4246 p = (char *)val->bv_val;
4247 e = p + val->bv_len;
4249 if ( *p != '(' /*')'*/ ) {
4250 return LDAP_INVALID_SYNTAX;
4253 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
4257 return LDAP_INVALID_SYNTAX;
4260 } else if ( !AD_CHAR( *p ) ) {
4261 return LDAP_INVALID_SYNTAX;
4265 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
4266 return LDAP_INVALID_SYNTAX;
4272 return LDAP_INVALID_SYNTAX;
4275 return LDAP_SUCCESS;
4279 bootParameterValidate(
4281 struct berval *val )
4285 if ( val->bv_len == 0 ) {
4286 return LDAP_INVALID_SYNTAX;
4289 p = (char *)val->bv_val;
4290 e = p + val->bv_len;
4293 for (; ( p < e ) && ( *p != '=' ); p++ ) {
4294 if ( !AD_CHAR( *p ) ) {
4295 return LDAP_INVALID_SYNTAX;
4300 return LDAP_INVALID_SYNTAX;
4304 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
4305 if ( !AD_CHAR( *p ) ) {
4306 return LDAP_INVALID_SYNTAX;
4311 return LDAP_INVALID_SYNTAX;
4315 for ( p++; p < e; p++ ) {
4316 if ( !SLAP_PRINTABLE( *p ) ) {
4317 return LDAP_INVALID_SYNTAX;
4321 return LDAP_SUCCESS;
4324 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
4325 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
4327 static slap_syntax_defs_rec syntax_defs[] = {
4328 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
4329 X_BINARY X_NOT_H_R ")",
4330 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4331 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
4332 0, NULL, NULL, NULL},
4333 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
4334 0, NULL, NULL, NULL},
4335 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
4337 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4338 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
4340 SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4341 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
4342 0, bitStringValidate, NULL, NULL },
4343 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
4344 0, booleanValidate, NULL, NULL},
4345 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
4346 X_BINARY X_NOT_H_R ")",
4347 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4348 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
4349 X_BINARY X_NOT_H_R ")",
4350 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4351 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
4352 X_BINARY X_NOT_H_R ")",
4353 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4354 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
4355 0, countryStringValidate, xIA5StringNormalize, NULL},
4356 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
4357 0, dnValidate, dnNormalize2, dnPretty2},
4358 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
4359 0, NULL, NULL, NULL},
4360 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
4361 0, NULL, NULL, NULL},
4362 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
4363 0, UTF8StringValidate, xUTF8StringNormalize, NULL},
4364 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
4365 0, NULL, NULL, NULL},
4366 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
4367 0, NULL, NULL, NULL},
4368 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
4369 0, NULL, NULL, NULL},
4370 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
4371 0, NULL, NULL, NULL},
4372 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
4373 0, NULL, NULL, NULL},
4374 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
4375 0, printablesStringValidate, xtelephoneNumberNormalize, NULL},
4376 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
4377 SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
4378 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
4379 0, generalizedTimeValidate, xgeneralizedTimeNormalize, NULL},
4380 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
4381 0, NULL, NULL, NULL},
4382 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
4383 0, IA5StringValidate, xIA5StringNormalize, NULL},
4384 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
4385 0, integerValidate, xintegerNormalize, NULL},
4386 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
4387 SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
4388 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
4389 0, NULL, NULL, NULL},
4390 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
4391 0, NULL, NULL, NULL},
4392 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
4393 0, NULL, NULL, NULL},
4394 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
4395 0, NULL, NULL, NULL},
4396 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
4397 0, NULL, NULL, NULL},
4398 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
4399 0, nameUIDValidate, xnameUIDNormalize, NULL},
4400 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
4401 0, NULL, NULL, NULL},
4402 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
4403 0, numericStringValidate, xnumericStringNormalize, NULL},
4404 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
4405 0, NULL, NULL, NULL},
4406 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
4407 0, oidValidate, NULL, NULL},
4408 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
4409 0, IA5StringValidate, xIA5StringNormalize, NULL},
4410 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
4411 0, blobValidate, NULL, NULL},
4412 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
4413 0, UTF8StringValidate, xUTF8StringNormalize, NULL},
4414 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
4415 0, NULL, NULL, NULL},
4416 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
4417 0, NULL, NULL, NULL},
4418 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
4419 0, printableStringValidate, xIA5StringNormalize, NULL},
4420 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
4421 X_BINARY X_NOT_H_R ")",
4422 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
4423 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
4424 X_BINARY X_NOT_H_R ")",
4425 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
4426 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
4427 0, printableStringValidate, xtelephoneNumberNormalize, NULL},
4428 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
4429 0, NULL, NULL, NULL},
4430 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
4431 0, printablesStringValidate, xIA5StringNormalize, NULL},
4432 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
4433 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
4434 0, utcTimeValidate, xutcTimeNormalize, NULL},
4436 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
4437 0, NULL, NULL, NULL},
4438 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
4439 0, NULL, NULL, NULL},
4440 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
4441 0, NULL, NULL, NULL},
4442 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
4443 0, NULL, NULL, NULL},
4444 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
4445 0, NULL, NULL, NULL},
4447 /* RFC 2307 NIS Syntaxes */
4448 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
4449 0, nisNetgroupTripleValidate, NULL, NULL},
4450 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
4451 0, bootParameterValidate, NULL, NULL},
4455 /* These OIDs are not published yet, but will be in the next
4456 * I-D for PKIX LDAPv3 schema as have been advanced by David
4457 * Chadwick in private mail.
4459 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
4460 0, UTF8StringValidate, NULL, NULL},
4463 /* OpenLDAP Experimental Syntaxes */
4464 #ifdef SLAPD_ACI_ENABLED
4465 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
4467 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
4471 #ifdef SLAPD_AUTHPASSWD
4472 /* needs updating */
4473 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
4474 SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
4477 /* OpenLDAP Void Syntax */
4478 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
4479 SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
4480 {NULL, 0, NULL, NULL, NULL}
4484 char *certificateExactMatchSyntaxes[] = {
4485 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
4489 char *directoryStringSyntaxes[] = {
4490 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
4493 char *integerFirstComponentMatchSyntaxes[] = {
4494 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
4495 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
4498 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
4499 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
4500 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
4501 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
4502 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
4503 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
4504 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
4505 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
4506 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
4511 * Other matching rules in X.520 that we do not use (yet):
4513 * 2.5.13.9 numericStringOrderingMatch
4514 * 2.5.13.19 octetStringSubstringsMatch
4515 * 2.5.13.25 uTCTimeMatch
4516 * 2.5.13.26 uTCTimeOrderingMatch
4517 * 2.5.13.31 directoryStringFirstComponentMatch
4518 * 2.5.13.32 wordMatch
4519 * 2.5.13.33 keywordMatch
4520 * 2.5.13.35 certificateMatch
4521 * 2.5.13.36 certificatePairExactMatch
4522 * 2.5.13.37 certificatePairMatch
4523 * 2.5.13.38 certificateListExactMatch
4524 * 2.5.13.39 certificateListMatch
4525 * 2.5.13.40 algorithmIdentifierMatch
4526 * 2.5.13.41 storedPrefixMatch
4527 * 2.5.13.42 attributeCertificateMatch
4528 * 2.5.13.43 readerAndKeyIDMatch
4529 * 2.5.13.44 attributeIntegrityMatch
4531 static slap_mrule_defs_rec mrule_defs[] = {
4533 * EQUALITY matching rules must be listed after associated APPROX
4534 * matching rules. So, we list all APPROX matching rules first.
4536 #ifndef SLAP_NVALUES
4537 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
4538 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4539 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4540 NULL, NULL, directoryStringApproxMatch,
4541 directoryStringApproxIndexer, directoryStringApproxFilter,
4544 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
4545 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4546 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
4547 NULL, NULL, IA5StringApproxMatch,
4548 IA5StringApproxIndexer, IA5StringApproxFilter,
4553 * Other matching rules
4556 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
4557 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4558 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4560 objectIdentifierNormalize, objectIdentifierMatch,
4561 objectIdentifierIndexer, objectIdentifierFilter,
4564 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
4565 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
4566 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4568 distinguishedNameNormalize, distinguishedNameMatch,
4569 distinguishedNameIndexer, distinguishedNameFilter,
4572 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
4573 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4574 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
4575 directoryStringSyntaxes,
4577 caseIgnoreNormalize, caseIgnoreMatch,
4578 caseIgnoreIndexer, caseIgnoreFilter,
4579 directoryStringApproxMatchOID },
4581 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
4582 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4583 SLAP_MR_ORDERING, directoryStringSyntaxes,
4584 NULL, caseIgnoreNormalize, caseIgnoreOrderingMatch,
4587 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
4588 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4589 SLAP_MR_SUBSTR, NULL,
4591 caseExactIgnoreSubstringsMatch,
4592 caseExactIgnoreSubstringsIndexer, caseExactIgnoreSubstringsFilter,
4595 {"( 2.5.13.5 NAME 'caseExactMatch' "
4596 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4597 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
4599 caseExactNormalize, caseExactMatch,
4600 caseExactIndexer, caseExactFilter,
4601 directoryStringApproxMatchOID },
4603 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
4604 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
4605 SLAP_MR_ORDERING, directoryStringSyntaxes,
4606 NULL, caseExactNormalize, caseExactOrderingMatch,
4609 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
4610 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4611 SLAP_MR_SUBSTR, directoryStringSyntaxes,
4613 NULL, caseExactSubstringsMatch,
4614 caseExactSubstringsIndexer, caseExactSubstringsFilter,
4617 {"( 2.5.13.8 NAME 'numericStringMatch' "
4618 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
4619 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4621 numericStringNormalize, numericStringMatch,
4622 numericStringIndexer, numericStringFilter,
4625 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
4626 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4627 SLAP_MR_SUBSTR, NULL,
4629 NULL, numericStringSubstringsMatch,
4630 numericStringSubstringsIndexer, numericStringSubstringsFilter,
4633 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
4634 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
4635 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4636 NULL, NULL, NULL, NULL, NULL, NULL},
4638 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
4639 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4640 SLAP_MR_SUBSTR, NULL,
4641 NULL, NULL, NULL, NULL, NULL, NULL},
4643 {"( 2.5.13.13 NAME 'booleanMatch' "
4644 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
4645 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4646 NULL, NULL, booleanMatch, NULL, NULL, NULL},
4648 {"( 2.5.13.14 NAME 'integerMatch' "
4649 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4650 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4652 integerNormalize, integerMatch,
4653 integerIndexer, integerFilter,
4656 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
4657 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4658 SLAP_MR_ORDERING, NULL, NULL,
4659 integerNormalize, integerOrderingMatch,
4660 integerIndexer, integerFilter,
4663 {"( 2.5.13.16 NAME 'bitStringMatch' "
4664 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
4665 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4667 bitStringNormalize, bitStringMatch,
4668 bitStringIndexer, bitStringFilter,
4671 {"( 2.5.13.17 NAME 'octetStringMatch' "
4672 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4673 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4675 octetStringMatch, octetStringIndexer, octetStringFilter,
4678 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
4679 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4680 SLAP_MR_ORDERING, NULL,
4682 octetStringOrderingMatch, NULL, NULL,
4685 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
4686 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
4687 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4689 telephoneNumberNormalize, telephoneNumberMatch,
4690 telephoneNumberIndexer, telephoneNumberFilter,
4693 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
4694 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
4695 SLAP_MR_SUBSTR, NULL,
4696 NULL, NULL, telephoneNumberSubstringsMatch,
4697 telephoneNumberSubstringsIndexer, telephoneNumberSubstringsFilter,
4700 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
4701 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
4702 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4707 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
4708 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
4709 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4711 uniqueMemberNormalize, uniqueMemberMatch,
4715 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
4716 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
4717 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4718 NULL, NULL, NULL, NULL, NULL, NULL},
4720 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
4721 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4722 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4724 generalizedTimeNormalize, generalizedTimeMatch,
4728 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
4729 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
4730 SLAP_MR_ORDERING, NULL,
4732 generalizedTimeOrderingMatch, generalizedTimeOrderingMatch,
4736 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
4737 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4738 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
4740 integerFirstComponentNormalize, integerMatch,
4744 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
4745 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
4746 SLAP_MR_EQUALITY | SLAP_MR_EXT,
4747 objectIdentifierFirstComponentMatchSyntaxes,
4749 objectIdentifierFirstComponentNormalize, objectIdentifierMatch,
4755 {"( 2.5.13.34 NAME 'certificateExactMatch' "
4756 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
4757 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
4758 certificateExactConvert, NULL,
4759 certificateExactMatch,
4760 certificateExactIndexer, certificateExactFilter,
4765 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
4766 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4767 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
4769 caseExactIA5Normalize, caseExactIA5Match,
4770 caseExactIA5Indexer, caseExactIA5Filter,
4771 IA5StringApproxMatchOID },
4773 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
4774 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4775 SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD, NULL,
4777 NULL, caseIgnoreIA5Match,
4778 caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
4779 IA5StringApproxMatchOID },
4781 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
4782 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4783 SLAP_MR_SUBSTR, NULL,
4785 NULL, caseIgnoreIA5SubstringsMatch,
4786 caseIgnoreIA5SubstringsIndexer, caseIgnoreIA5SubstringsFilter,
4789 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
4790 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
4791 SLAP_MR_SUBSTR, NULL,
4793 NULL, caseExactIA5SubstringsMatch,
4794 caseExactIA5SubstringsIndexer, caseExactIA5SubstringsFilter,
4797 #ifdef SLAPD_AUTHPASSWD
4798 /* needs updating */
4799 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
4800 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
4801 SLAP_MR_EQUALITY, NULL,
4803 authPasswordMatch, NULL, NULL,
4807 #ifdef SLAPD_ACI_ENABLED
4808 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
4809 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
4810 SLAP_MR_EQUALITY, NULL,
4812 OpenLDAPaciMatch, NULL, NULL,
4816 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
4817 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4820 NULL, integerBitAndMatch, NULL, NULL,
4823 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
4824 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
4827 NULL, integerBitOrMatch, NULL, NULL,
4830 {NULL, SLAP_MR_NONE, NULL,
4831 NULL, NULL, NULL, NULL, NULL,
4836 slap_schema_init( void )
4841 /* we should only be called once (from main) */
4842 assert( schema_init_done == 0 );
4844 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
4845 res = register_syntax( &syntax_defs[i] );
4848 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
4849 syntax_defs[i].sd_desc );
4854 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
4855 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
4856 mrule_defs[i].mrd_compat_syntaxes == NULL )
4859 "slap_schema_init: Ignoring unusable matching rule %s\n",
4860 mrule_defs[i].mrd_desc );
4864 res = register_matching_rule( &mrule_defs[i] );
4868 "slap_schema_init: Error registering matching rule %s\n",
4869 mrule_defs[i].mrd_desc );
4874 res = slap_schema_load();
4875 schema_init_done = 1;
4880 schema_destroy( void )