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)
31 #define SLAP_NVALUES 1
33 #define SLAP_MR_ASSOCIATED(mr, with) \
34 ((mr) == (with) || (mr)->smr_associated == (with))
36 /* not yet implemented */
37 #define objectIdentifierNormalize NULL
38 #define integerOrderingMatch NULL
39 #define uniqueMemberMatch NULL
40 #define integerFirstComponentNormalize NULL
41 #define objectIdentifierFirstComponentNormalize NULL
43 /* approx matching rules */
45 #define directoryStringApproxMatchOID NULL
46 #define IA5StringApproxMatchOID NULL
48 #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
49 #define directoryStringApproxMatch approxMatch
50 #define directoryStringApproxIndexer approxIndexer
51 #define directoryStringApproxFilter approxFilter
52 #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
53 #define IA5StringApproxMatch approxMatch
54 #define IA5StringApproxIndexer approxIndexer
55 #define IA5StringApproxFilter approxFilter
63 /* no value allowed */
64 return LDAP_INVALID_SYNTAX;
72 /* any value allowed */
85 int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
88 match = memcmp( value->bv_val,
89 ((struct berval *) assertedValue)->bv_val,
98 octetStringOrderingMatch(
103 struct berval *value,
104 void *assertedValue )
106 ber_len_t v_len = value->bv_len;
107 ber_len_t av_len = ((struct berval *) assertedValue)->bv_len;
109 int match = memcmp( value->bv_val,
110 ((struct berval *) assertedValue)->bv_val,
111 (v_len < av_len ? v_len : av_len) );
113 if( match == 0 ) match = v_len - av_len;
119 /* Index generation function */
120 int octetStringIndexer(
125 struct berval *prefix,
132 HASH_CONTEXT HASHcontext;
133 unsigned char HASHdigest[HASH_BYTES];
134 struct berval digest;
135 digest.bv_val = HASHdigest;
136 digest.bv_len = sizeof(HASHdigest);
138 for( i=0; values[i].bv_val != NULL; i++ ) {
139 /* just count them */
142 /* we should have at least one value at this point */
145 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
147 slen = syntax->ssyn_oidlen;
148 mlen = mr->smr_oidlen;
150 for( i=0; values[i].bv_val != NULL; i++ ) {
151 HASH_Init( &HASHcontext );
152 if( prefix != NULL && prefix->bv_len > 0 ) {
153 HASH_Update( &HASHcontext,
154 prefix->bv_val, prefix->bv_len );
156 HASH_Update( &HASHcontext,
157 syntax->ssyn_oid, slen );
158 HASH_Update( &HASHcontext,
160 HASH_Update( &HASHcontext,
161 values[i].bv_val, values[i].bv_len );
162 HASH_Final( HASHdigest, &HASHcontext );
164 ber_dupbv( &keys[i], &digest );
167 keys[i].bv_val = NULL;
175 /* Index generation function */
176 int octetStringFilter(
181 struct berval *prefix,
182 void * assertedValue,
187 HASH_CONTEXT HASHcontext;
188 unsigned char HASHdigest[HASH_BYTES];
189 struct berval *value = (struct berval *) assertedValue;
190 struct berval digest;
191 digest.bv_val = HASHdigest;
192 digest.bv_len = sizeof(HASHdigest);
194 slen = syntax->ssyn_oidlen;
195 mlen = mr->smr_oidlen;
197 keys = ch_malloc( sizeof( struct berval ) * 2 );
199 HASH_Init( &HASHcontext );
200 if( prefix != NULL && prefix->bv_len > 0 ) {
201 HASH_Update( &HASHcontext,
202 prefix->bv_val, prefix->bv_len );
204 HASH_Update( &HASHcontext,
205 syntax->ssyn_oid, slen );
206 HASH_Update( &HASHcontext,
208 HASH_Update( &HASHcontext,
209 value->bv_val, value->bv_len );
210 HASH_Final( HASHdigest, &HASHcontext );
212 ber_dupbv( keys, &digest );
213 keys[1].bv_val = NULL;
222 octetStringSubstringsMatch (
227 struct berval *value,
228 void *assertedValue )
231 SubstringsAssertion *sub = assertedValue;
232 struct berval left = *value;
236 /* Add up asserted input length */
237 if( sub->sa_initial.bv_val ) {
238 inlen += sub->sa_initial.bv_len;
241 for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
242 inlen += sub->sa_any[i].bv_len;
245 if( sub->sa_final.bv_val ) {
246 inlen += sub->sa_final.bv_len;
249 if( sub->sa_initial.bv_val ) {
250 if( inlen > left.bv_len ) {
255 match = memcmp( sub->sa_initial.bv_val, left.bv_val,
256 sub->sa_initial.bv_len );
262 left.bv_val += sub->sa_initial.bv_len;
263 left.bv_len -= sub->sa_initial.bv_len;
264 inlen -= sub->sa_initial.bv_len;
267 if( sub->sa_final.bv_val ) {
268 if( inlen > left.bv_len ) {
273 match = memcmp( sub->sa_final.bv_val,
274 &left.bv_val[left.bv_len - sub->sa_final.bv_len],
275 sub->sa_final.bv_len );
281 left.bv_len -= sub->sa_final.bv_len;
282 inlen -= sub->sa_final.bv_len;
286 for(i=0; sub->sa_any[i].bv_val; i++) {
291 if( inlen > left.bv_len ) {
292 /* not enough length */
297 if( sub->sa_any[i].bv_len == 0 ) {
301 p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
308 idx = p - left.bv_val;
310 if( idx >= left.bv_len ) {
311 /* this shouldn't happen */
318 if( sub->sa_any[i].bv_len > left.bv_len ) {
319 /* not enough left */
324 match = memcmp( left.bv_val,
325 sub->sa_any[i].bv_val,
326 sub->sa_any[i].bv_len );
334 left.bv_val += sub->sa_any[i].bv_len;
335 left.bv_len -= sub->sa_any[i].bv_len;
336 inlen -= sub->sa_any[i].bv_len;
345 /* Substrings Index generation function */
347 octetStringSubstringsIndexer (
352 struct berval *prefix,
356 ber_len_t i, j, nkeys;
360 HASH_CONTEXT HASHcontext;
361 unsigned char HASHdigest[HASH_BYTES];
362 struct berval digest;
363 digest.bv_val = HASHdigest;
364 digest.bv_len = sizeof(HASHdigest);
368 for( i=0; values[i].bv_val != NULL; i++ ) {
369 /* count number of indices to generate */
370 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
374 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
375 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
376 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
377 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
379 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
383 if( flags & SLAP_INDEX_SUBSTR_ANY ) {
384 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
385 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
389 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
390 if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
391 nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
392 ( SLAP_INDEX_SUBSTR_MINLEN - 1);
394 nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
400 /* no keys to generate */
405 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
407 slen = syntax->ssyn_oidlen;
408 mlen = mr->smr_oidlen;
411 for( i=0; values[i].bv_val != NULL; i++ ) {
414 if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
416 if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
417 ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
419 char pre = SLAP_INDEX_SUBSTR_PREFIX;
420 max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
422 for( j=0; j<max; j++ ) {
423 HASH_Init( &HASHcontext );
424 if( prefix != NULL && prefix->bv_len > 0 ) {
425 HASH_Update( &HASHcontext,
426 prefix->bv_val, prefix->bv_len );
429 HASH_Update( &HASHcontext,
430 &pre, sizeof( pre ) );
431 HASH_Update( &HASHcontext,
432 syntax->ssyn_oid, slen );
433 HASH_Update( &HASHcontext,
435 HASH_Update( &HASHcontext,
436 &values[i].bv_val[j],
437 SLAP_INDEX_SUBSTR_MAXLEN );
438 HASH_Final( HASHdigest, &HASHcontext );
440 ber_dupbv( &keys[nkeys++], &digest );
444 max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
445 ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
447 for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
450 if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
451 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
452 HASH_Init( &HASHcontext );
453 if( prefix != NULL && prefix->bv_len > 0 ) {
454 HASH_Update( &HASHcontext,
455 prefix->bv_val, prefix->bv_len );
457 HASH_Update( &HASHcontext,
458 &pre, sizeof( pre ) );
459 HASH_Update( &HASHcontext,
460 syntax->ssyn_oid, slen );
461 HASH_Update( &HASHcontext,
463 HASH_Update( &HASHcontext,
464 values[i].bv_val, j );
465 HASH_Final( HASHdigest, &HASHcontext );
467 ber_dupbv( &keys[nkeys++], &digest );
470 if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
471 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
472 HASH_Init( &HASHcontext );
473 if( prefix != NULL && prefix->bv_len > 0 ) {
474 HASH_Update( &HASHcontext,
475 prefix->bv_val, prefix->bv_len );
477 HASH_Update( &HASHcontext,
478 &pre, sizeof( pre ) );
479 HASH_Update( &HASHcontext,
480 syntax->ssyn_oid, slen );
481 HASH_Update( &HASHcontext,
483 HASH_Update( &HASHcontext,
484 &values[i].bv_val[values[i].bv_len-j], j );
485 HASH_Final( HASHdigest, &HASHcontext );
487 ber_dupbv( &keys[nkeys++], &digest );
495 keys[nkeys].bv_val = NULL;
506 octetStringSubstringsFilter (
511 struct berval *prefix,
512 void * assertedValue,
515 SubstringsAssertion *sa;
519 size_t slen, mlen, klen;
521 HASH_CONTEXT HASHcontext;
522 unsigned char HASHdigest[HASH_BYTES];
523 struct berval *value;
524 struct berval digest;
526 sa = (SubstringsAssertion *) assertedValue;
528 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL
529 && sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
534 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
536 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
537 if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
538 /* don't bother accounting for stepping */
539 nkeys += sa->sa_any[i].bv_len -
540 ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
545 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
546 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
556 digest.bv_val = HASHdigest;
557 digest.bv_len = sizeof(HASHdigest);
559 slen = syntax->ssyn_oidlen;
560 mlen = mr->smr_oidlen;
562 keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
565 if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
566 sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
568 pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
569 value = &sa->sa_initial;
571 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
572 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
574 HASH_Init( &HASHcontext );
575 if( prefix != NULL && prefix->bv_len > 0 ) {
576 HASH_Update( &HASHcontext,
577 prefix->bv_val, prefix->bv_len );
579 HASH_Update( &HASHcontext,
580 &pre, sizeof( pre ) );
581 HASH_Update( &HASHcontext,
582 syntax->ssyn_oid, slen );
583 HASH_Update( &HASHcontext,
585 HASH_Update( &HASHcontext,
586 value->bv_val, klen );
587 HASH_Final( HASHdigest, &HASHcontext );
589 ber_dupbv( &keys[nkeys++], &digest );
592 if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
594 pre = SLAP_INDEX_SUBSTR_PREFIX;
595 klen = SLAP_INDEX_SUBSTR_MAXLEN;
597 for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
598 if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
602 value = &sa->sa_any[i];
605 j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
606 j += SLAP_INDEX_SUBSTR_STEP )
608 HASH_Init( &HASHcontext );
609 if( prefix != NULL && prefix->bv_len > 0 ) {
610 HASH_Update( &HASHcontext,
611 prefix->bv_val, prefix->bv_len );
613 HASH_Update( &HASHcontext,
614 &pre, sizeof( pre ) );
615 HASH_Update( &HASHcontext,
616 syntax->ssyn_oid, slen );
617 HASH_Update( &HASHcontext,
619 HASH_Update( &HASHcontext,
620 &value->bv_val[j], klen );
621 HASH_Final( HASHdigest, &HASHcontext );
623 ber_dupbv( &keys[nkeys++], &digest );
629 if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
630 sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
632 pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
633 value = &sa->sa_final;
635 klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
636 ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
638 HASH_Init( &HASHcontext );
639 if( prefix != NULL && prefix->bv_len > 0 ) {
640 HASH_Update( &HASHcontext,
641 prefix->bv_val, prefix->bv_len );
643 HASH_Update( &HASHcontext,
644 &pre, sizeof( pre ) );
645 HASH_Update( &HASHcontext,
646 syntax->ssyn_oid, slen );
647 HASH_Update( &HASHcontext,
649 HASH_Update( &HASHcontext,
650 &value->bv_val[value->bv_len-klen], klen );
651 HASH_Final( HASHdigest, &HASHcontext );
653 ber_dupbv( &keys[nkeys++], &digest );
657 keys[nkeys].bv_val = NULL;
674 /* very unforgiving validation, requires no normalization
675 * before simplistic matching
677 if( in->bv_len < 3 ) {
678 return LDAP_INVALID_SYNTAX;
682 * rfc 2252 section 6.3 Bit String
683 * bitstring = "'" *binary-digit "'"
684 * binary-digit = "0" / "1"
685 * example: '0101111101'B
688 if( in->bv_val[0] != '\'' ||
689 in->bv_val[in->bv_len-2] != '\'' ||
690 in->bv_val[in->bv_len-1] != 'B' )
692 return LDAP_INVALID_SYNTAX;
695 for( i=in->bv_len-3; i>0; i-- ) {
696 if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
697 return LDAP_INVALID_SYNTAX;
712 if( in->bv_len == 0 ) return LDAP_SUCCESS;
714 ber_dupbv( &dn, in );
715 if( !dn.bv_val ) return LDAP_OTHER;
717 if( dn.bv_val[dn.bv_len-1] == 'B'
718 && dn.bv_val[dn.bv_len-2] == '\'' )
720 /* assume presence of optional UID */
723 for(i=dn.bv_len-3; i>1; i--) {
724 if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
728 if( dn.bv_val[i] != '\'' || dn.bv_val[i-1] != '#' ) {
729 ber_memfree( dn.bv_val );
730 return LDAP_INVALID_SYNTAX;
733 /* trim the UID to allow use of dnValidate */
734 dn.bv_val[i-1] = '\0';
738 rc = dnValidate( NULL, &dn );
740 ber_memfree( dn.bv_val );
745 uniqueMemberNormalize(
750 struct berval *normalized )
755 ber_dupbv( &out, val );
756 if( out.bv_len != 0 ) {
757 struct berval uid = { 0, NULL };
759 if( out.bv_val[out.bv_len-1] == 'B'
760 && out.bv_val[out.bv_len-2] == '\'' )
762 /* assume presence of optional UID */
763 uid.bv_val = strrchr( out.bv_val, '#' );
765 if( uid.bv_val == NULL ) {
767 return LDAP_INVALID_SYNTAX;
770 uid.bv_len = out.bv_len - (uid.bv_val - out.bv_val);
771 out.bv_len -= uid.bv_len--;
773 /* temporarily trim the UID */
774 *(uid.bv_val++) = '\0';
777 rc = dnNormalize2( NULL, &out, normalized );
779 if( rc != LDAP_SUCCESS ) {
781 return LDAP_INVALID_SYNTAX;
785 normalized->bv_val = ch_realloc( normalized->bv_val,
786 normalized->bv_len + uid.bv_len + sizeof("#") );
788 /* insert the separator */
789 normalized->bv_val[normalized->bv_len++] = '#';
792 AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
793 uid.bv_val, uid.bv_len );
794 normalized->bv_len += uid.bv_len;
797 normalized->bv_val[normalized->bv_len] = '\0';
807 * Handling boolean syntax and matching is quite rigid.
808 * A more flexible approach would be to allow a variety
809 * of strings to be normalized and prettied into TRUE
817 /* very unforgiving validation, requires no normalization
818 * before simplistic matching
821 if( in->bv_len == 4 ) {
822 if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
825 } else if( in->bv_len == 5 ) {
826 if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
831 return LDAP_INVALID_SYNTAX;
840 struct berval *value,
841 void *assertedValue )
843 /* simplistic matching allowed by rigid validation */
844 struct berval *asserted = (struct berval *) assertedValue;
845 *matchp = value->bv_len != asserted->bv_len;
849 /*-------------------------------------------------------------------
850 LDAP/X.500 string syntax / matching rules have a few oddities. This
851 comment attempts to detail how slapd(8) treats them.
854 StringSyntax X.500 LDAP Matching/Comments
855 DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces
856 PrintableString subset subset i/e + ignore insignificant spaces
857 PrintableString subset subset i/e + ignore insignificant spaces
858 NumericString subset subset ignore all spaces
859 IA5String ASCII ASCII i/e + ignore insignificant spaces
860 TeletexString T.61 T.61 i/e + ignore insignificant spaces
862 TelephoneNumber subset subset i + ignore all spaces and "-"
864 See draft-ietf-ldapbis-strpro for details (once published).
868 In X.500(93), a directory string can be either a PrintableString,
869 a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)).
870 In later versions, more CHOICEs were added. In all cases the string
873 In LDAPv3, a directory string is a UTF-8 encoded UCS string.
874 A directory string cannot be zero length.
876 For matching, there are both case ignore and exact rules. Both
877 also require that "insignificant" spaces be ignored.
878 spaces before the first non-space are ignored;
879 spaces after the last non-space are ignored;
880 spaces after a space are ignored.
881 Note: by these rules (and as clarified in X.520), a string of only
882 spaces is to be treated as if held one space, not empty (which
883 would be a syntax error).
886 In ASN.1, numeric string is just a string of digits and spaces
887 and could be empty. However, in X.500, all attribute values of
888 numeric string carry a non-empty constraint. For example:
890 internationalISDNNumber ATTRIBUTE ::= {
891 WITH SYNTAX InternationalISDNNumber
892 EQUALITY MATCHING RULE numericStringMatch
893 SUBSTRINGS MATCHING RULE numericStringSubstringsMatch
894 ID id-at-internationalISDNNumber }
895 InternationalISDNNumber ::=
896 NumericString (SIZE(1..ub-international-isdn-number))
898 Unforunately, some assertion values are don't carry the same
899 constraint (but its unclear how such an assertion could ever
900 be true). In LDAP, there is one syntax (numericString) not two
901 (numericString with constraint, numericString without constraint).
902 This should be treated as numericString with non-empty constraint.
903 Note that while someone may have no ISDN number, there are no ISDN
904 numbers which are zero length.
906 In matching, spaces are ignored.
909 In ASN.1, Printable string is just a string of printable characters
910 and can be empty. In X.500, semantics much like NumericString (see
911 serialNumber for a like example) excepting uses insignificant space
912 handling instead of ignore all spaces.
915 Basically same as PrintableString. There are no examples in X.500,
916 but same logic applies. So we require them to be non-empty as
919 -------------------------------------------------------------------*/
928 unsigned char *u = in->bv_val;
930 if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) {
931 /* directory strings cannot be empty */
932 return LDAP_INVALID_SYNTAX;
935 for( count = in->bv_len; count > 0; count-=len, u+=len ) {
936 /* get the length indicated by the first byte */
937 len = LDAP_UTF8_CHARLEN2( u, len );
939 /* very basic checks */
942 if( (u[5] & 0xC0) != 0x80 ) {
943 return LDAP_INVALID_SYNTAX;
946 if( (u[4] & 0xC0) != 0x80 ) {
947 return LDAP_INVALID_SYNTAX;
950 if( (u[3] & 0xC0) != 0x80 ) {
951 return LDAP_INVALID_SYNTAX;
954 if( (u[2] & 0xC0 )!= 0x80 ) {
955 return LDAP_INVALID_SYNTAX;
958 if( (u[1] & 0xC0) != 0x80 ) {
959 return LDAP_INVALID_SYNTAX;
962 /* CHARLEN already validated it */
965 return LDAP_INVALID_SYNTAX;
968 /* make sure len corresponds with the offset
969 to the next character */
970 if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
974 return LDAP_INVALID_SYNTAX;
986 struct berval *normalized )
988 struct berval tmp, nvalue;
992 if( val->bv_val == NULL ) {
993 /* assume we're dealing with a syntax (e.g., UTF8String)
994 * which allows empty strings
996 normalized->bv_len = 0;
997 normalized->bv_val = NULL;
1001 flags = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactMatch )
1002 ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
1003 flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
1004 ? LDAP_UTF8_APPROX : 0;
1006 val = UTF8bvnormalize( val, &tmp, flags );
1011 /* collapse spaces (in place) */
1013 nvalue.bv_val = tmp.bv_val;
1015 wasspace=1; /* trim leading spaces */
1016 for( i=0; i<tmp.bv_len; i++) {
1017 if ( ASCII_SPACE( tmp.bv_val[i] )) {
1018 if( wasspace++ == 0 ) {
1019 /* trim repeated spaces */
1020 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1024 nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
1028 if( nvalue.bv_len ) {
1030 /* last character was a space, trim it */
1033 nvalue.bv_val[nvalue.bv_len] = '\0';
1036 /* string of all spaces is treated as one space */
1037 nvalue.bv_val[0] = ' ';
1038 nvalue.bv_val[1] = '\0';
1042 *normalized = nvalue;
1043 return LDAP_SUCCESS;
1046 #ifndef SLAP_NVALUES
1048 #ifndef SLAPD_APPROX_OLDSINGLESTRING
1049 #if defined(SLAPD_APPROX_INITIALS)
1050 #define SLAPD_APPROX_DELIMITER "._ "
1051 #define SLAPD_APPROX_WORDLEN 2
1053 #define SLAPD_APPROX_DELIMITER " "
1054 #define SLAPD_APPROX_WORDLEN 1
1063 struct berval *value,
1064 void *assertedValue )
1066 struct berval *nval, *assertv;
1067 char *val, **values, **words, *c;
1068 int i, count, len, nextchunk=0, nextavail=0;
1070 /* Yes, this is necessary */
1071 nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX );
1072 if( nval == NULL ) {
1074 return LDAP_SUCCESS;
1077 /* Yes, this is necessary */
1078 assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
1079 NULL, LDAP_UTF8_APPROX );
1080 if( assertv == NULL ) {
1083 return LDAP_SUCCESS;
1086 /* Isolate how many words there are */
1087 for ( c = nval->bv_val, count = 1; *c; c++ ) {
1088 c = strpbrk( c, SLAPD_APPROX_DELIMITER );
1089 if ( c == NULL ) break;
1094 /* Get a phonetic copy of each word */
1095 words = (char **)ch_malloc( count * sizeof(char *) );
1096 values = (char **)ch_malloc( count * sizeof(char *) );
1097 for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
1099 values[i] = phonetic(c);
1102 /* Work through the asserted value's words, to see if at least some
1103 of the words are there, in the same order. */
1105 while ( (ber_len_t) nextchunk < assertv->bv_len ) {
1106 len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
1111 #if defined(SLAPD_APPROX_INITIALS)
1112 else if( len == 1 ) {
1113 /* Single letter words need to at least match one word's initial */
1114 for( i=nextavail; i<count; i++ )
1115 if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
1122 /* Isolate the next word in the asserted value and phonetic it */
1123 assertv->bv_val[nextchunk+len] = '\0';
1124 val = phonetic( assertv->bv_val + nextchunk );
1126 /* See if this phonetic chunk is in the remaining words of *value */
1127 for( i=nextavail; i<count; i++ ){
1128 if( !strcmp( val, values[i] ) ){
1136 /* This chunk in the asserted value was NOT within the *value. */
1142 /* Go on to the next word in the asserted value */
1146 /* If some of the words were seen, call it a match */
1147 if( nextavail > 0 ) {
1154 /* Cleanup allocs */
1155 ber_bvfree( assertv );
1156 for( i=0; i<count; i++ ) {
1157 ch_free( values[i] );
1163 return LDAP_SUCCESS;
1172 struct berval *prefix,
1177 int i,j, len, wordcount, keycount=0;
1178 struct berval *newkeys;
1179 BerVarray keys=NULL;
1181 for( j=0; values[j].bv_val != NULL; j++ ) {
1182 struct berval val = { 0, NULL };
1183 /* Yes, this is necessary */
1184 UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX );
1185 assert( val.bv_val != NULL );
1187 /* Isolate how many words there are. There will be a key for each */
1188 for( wordcount = 0, c = val.bv_val; *c; c++) {
1189 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1190 if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
1192 if (*c == '\0') break;
1196 /* Allocate/increase storage to account for new keys */
1197 newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
1198 * sizeof(struct berval) );
1199 AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
1200 if( keys ) ch_free( keys );
1203 /* Get a phonetic copy of each word */
1204 for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
1206 if( len < SLAPD_APPROX_WORDLEN ) continue;
1207 ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
1212 ber_memfree( val.bv_val );
1214 keys[keycount].bv_val = NULL;
1217 return LDAP_SUCCESS;
1226 struct berval *prefix,
1227 void * assertedValue,
1235 /* Yes, this is necessary */
1236 val = UTF8bvnormalize( ((struct berval *)assertedValue),
1237 NULL, LDAP_UTF8_APPROX );
1238 if( val == NULL || val->bv_val == NULL ) {
1239 keys = (struct berval *)ch_malloc( sizeof(struct berval) );
1240 keys[0].bv_val = NULL;
1243 return LDAP_SUCCESS;
1246 /* Isolate how many words there are. There will be a key for each */
1247 for( count = 0,c = val->bv_val; *c; c++) {
1248 len = strcspn(c, SLAPD_APPROX_DELIMITER);
1249 if( len >= SLAPD_APPROX_WORDLEN ) count++;
1251 if (*c == '\0') break;
1255 /* Allocate storage for new keys */
1256 keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
1258 /* Get a phonetic copy of each word */
1259 for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
1261 if( len < SLAPD_APPROX_WORDLEN ) continue;
1262 ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
1268 keys[count].bv_val = NULL;
1271 return LDAP_SUCCESS;
1275 /* No other form of Approximate Matching is defined */
1283 struct berval *value,
1284 void *assertedValue )
1286 char *vapprox, *avapprox;
1289 /* Yes, this is necessary */
1290 s = UTF8normalize( value, UTF8_NOCASEFOLD );
1293 return LDAP_SUCCESS;
1296 /* Yes, this is necessary */
1297 t = UTF8normalize( ((struct berval *)assertedValue),
1302 return LDAP_SUCCESS;
1305 vapprox = phonetic( strip8bitChars( s ) );
1306 avapprox = phonetic( strip8bitChars( t ) );
1311 *matchp = strcmp( vapprox, avapprox );
1314 ch_free( avapprox );
1316 return LDAP_SUCCESS;
1325 struct berval *prefix,
1333 for( i=0; values[i].bv_val != NULL; i++ ) {
1334 /* empty - just count them */
1337 /* we should have at least one value at this point */
1340 keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
1342 /* Copy each value and run it through phonetic() */
1343 for( i=0; values[i].bv_val != NULL; i++ ) {
1344 /* Yes, this is necessary */
1345 s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
1347 /* strip 8-bit chars and run through phonetic() */
1348 ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
1351 keys[i].bv_val = NULL;
1354 return LDAP_SUCCESS;
1363 struct berval *prefix,
1364 void * assertedValue,
1370 keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
1372 /* Yes, this is necessary */
1373 s = UTF8normalize( ((struct berval *)assertedValue),
1378 /* strip 8-bit chars and run through phonetic() */
1379 keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
1385 return LDAP_SUCCESS;
1388 #endif /* !SLAP_NVALUES */
1390 /* Remove all spaces and '-' characters */
1392 telephoneNumberNormalize(
1397 struct berval *normalized )
1401 /* validator should have refused an empty string */
1402 assert( val->bv_len );
1404 q = normalized->bv_val = ch_malloc( val->bv_len + 1 );
1406 for( p = val->bv_val; *p; p++ ) {
1407 if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
1413 normalized->bv_len = q - normalized->bv_val;
1415 if( normalized->bv_len == 0 ) {
1416 free( normalized->bv_val );
1417 return LDAP_INVALID_SYNTAX;
1420 return LDAP_SUCCESS;
1426 struct berval *val )
1430 if( val->bv_len == 0 ) {
1431 /* disallow empty strings */
1432 return LDAP_INVALID_SYNTAX;
1435 if( OID_LEADCHAR(val->bv_val[0]) ) {
1437 for(i=1; i < val->bv_len; i++) {
1438 if( OID_SEPARATOR( val->bv_val[i] ) ) {
1439 if( dot++ ) return 1;
1440 } else if ( OID_CHAR( val->bv_val[i] ) ) {
1443 return LDAP_INVALID_SYNTAX;
1447 return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
1449 } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
1450 for(i=1; i < val->bv_len; i++) {
1451 if( !DESC_CHAR(val->bv_val[i] ) ) {
1452 return LDAP_INVALID_SYNTAX;
1456 return LDAP_SUCCESS;
1459 return LDAP_INVALID_SYNTAX;
1468 struct berval *value,
1469 void *assertedValue )
1472 int vsign = 1, avsign = 1; /* default sign = '+' */
1473 struct berval *asserted;
1474 ber_len_t vlen, avlen;
1477 /* Skip leading space/sign/zeroes, and get the sign of the *value number */
1479 vlen = value->bv_len;
1481 #ifndef SLAP_NVALUES
1482 if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
1483 char *tmp = memchr( v, '$', vlen );
1484 if( tmp ) vlen = tmp - v;
1485 while( vlen && ASCII_SPACE( v[vlen-1] )) vlen--;
1489 for( ; vlen && ( *v < '1' || '9' < *v ); v++, vlen-- ) { /* ANSI 2.2.1 */
1490 if( *v == '-' ) vsign = -1;
1493 if( vlen == 0 ) vsign = 0;
1495 /* Do the same with the *assertedValue number */
1496 asserted = (struct berval *) assertedValue;
1497 av = asserted->bv_val;
1498 avlen = asserted->bv_len;
1499 for( ; avlen && ( *av < '1' || '9' < *av ); av++, avlen-- )
1505 match = vsign - avsign;
1507 match = (vlen != avlen
1508 ? ( vlen < avlen ? -1 : 1 )
1509 : memcmp( v, av, vlen ));
1515 return LDAP_SUCCESS;
1521 struct berval *val )
1525 if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
1527 if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
1528 if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
1530 } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
1531 return LDAP_INVALID_SYNTAX;
1534 for( i=1; i < val->bv_len; i++ ) {
1535 if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
1538 return LDAP_SUCCESS;
1547 struct berval *normalized )
1557 /* Ignore leading spaces */
1558 while ( len && ( *p == ' ' )) {
1565 negative = ( *p == '-' );
1566 if(( *p == '-' ) || ( *p == '+' )) {
1572 /* Ignore leading zeros */
1573 while ( len && ( *p == '0' )) {
1578 /* If there are no non-zero digits left, the number is zero, otherwise
1579 allocate space for the number and copy it into the buffer */
1581 normalized->bv_val = ch_strdup("0");
1582 normalized->bv_len = 1;
1585 normalized->bv_len = len+negative;
1586 normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
1587 if( negative ) normalized->bv_val[0] = '-';
1588 AC_MEMCPY( normalized->bv_val + negative, p, len );
1589 normalized->bv_val[len+negative] = '\0';
1592 return LDAP_SUCCESS;
1596 countryStringValidate(
1598 struct berval *val )
1600 if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
1602 if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
1603 return LDAP_INVALID_SYNTAX;
1605 if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
1606 return LDAP_INVALID_SYNTAX;
1609 return LDAP_SUCCESS;
1613 printableStringValidate(
1615 struct berval *val )
1619 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1621 for(i=0; i < val->bv_len; i++) {
1622 if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
1623 return LDAP_INVALID_SYNTAX;
1627 return LDAP_SUCCESS;
1631 printablesStringValidate(
1633 struct berval *val )
1637 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1639 for(i=0,len=0; i < val->bv_len; i++) {
1640 int c = val->bv_val[i];
1644 return LDAP_INVALID_SYNTAX;
1648 } else if ( SLAP_PRINTABLE(c) ) {
1651 return LDAP_INVALID_SYNTAX;
1656 return LDAP_INVALID_SYNTAX;
1659 return LDAP_SUCCESS;
1665 struct berval *val )
1669 if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1671 for(i=0; i < val->bv_len; i++) {
1672 if( !LDAP_ASCII(val->bv_val[i]) ) {
1673 return LDAP_INVALID_SYNTAX;
1677 return LDAP_SUCCESS;
1686 struct berval *normalized )
1689 int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match);
1691 assert( val->bv_len );
1695 /* Ignore initial whitespace */
1696 while ( ASCII_SPACE( *p ) ) {
1700 normalized->bv_val = ch_strdup( p );
1701 p = q = normalized->bv_val;
1704 if ( ASCII_SPACE( *p ) ) {
1707 /* Ignore the extra whitespace */
1708 while ( ASCII_SPACE( *p ) ) {
1712 } else if ( casefold ) {
1713 /* Most IA5 rules require casefolding */
1714 *q++ = TOLOWER(*p++);
1721 assert( normalized->bv_val <= p );
1725 * If the string ended in space, backup the pointer one
1726 * position. One is enough because the above loop collapsed
1727 * all whitespace to a single space.
1730 if ( ASCII_SPACE( q[-1] ) ) {
1734 /* null terminate */
1737 normalized->bv_len = q - normalized->bv_val;
1739 if( normalized->bv_len == 0 ) {
1740 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1741 normalized->bv_val[0] = ' ';
1742 normalized->bv_val[1] = '\0';
1743 normalized->bv_len = 1;
1746 return LDAP_SUCCESS;
1750 numericStringValidate(
1756 if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX;
1758 for(i=0; i < in->bv_len; i++) {
1759 if( !SLAP_NUMERIC(in->bv_val[i]) ) {
1760 return LDAP_INVALID_SYNTAX;
1764 return LDAP_SUCCESS;
1768 numericStringNormalize(
1773 struct berval *normalized )
1775 /* removal all spaces */
1778 assert( val->bv_len );
1780 normalized->bv_val = ch_malloc( val->bv_len + 1 );
1783 q = normalized->bv_val;
1786 if ( ASCII_SPACE( *p ) ) {
1787 /* Ignore whitespace */
1794 /* we should have copied no more then is in val */
1795 assert( (q - normalized->bv_val) <= (p - val->bv_val) );
1797 /* null terminate */
1800 normalized->bv_len = q - normalized->bv_val;
1802 if( normalized->bv_len == 0 ) {
1803 normalized->bv_val = ch_realloc( normalized->bv_val, 2 );
1804 normalized->bv_val[0] = ' ';
1805 normalized->bv_val[1] = '\0';
1806 normalized->bv_len = 1;
1809 return LDAP_SUCCESS;
1812 #ifndef SLAP_NVALUES
1814 objectIdentifierFirstComponentMatch(
1819 struct berval *value,
1820 void *assertedValue )
1822 int rc = LDAP_SUCCESS;
1824 struct berval *asserted = (struct berval *) assertedValue;
1828 if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
1829 return LDAP_INVALID_SYNTAX;
1832 /* trim leading white space */
1833 for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
1837 /* grab next word */
1838 oid.bv_val = &value->bv_val[i];
1839 j = value->bv_len - i;
1840 for( i=0; !ASCII_SPACE(oid.bv_val[i]) && i < j; i++ ) {
1845 /* insert attributeTypes, objectclass check here */
1846 if( OID_LEADCHAR(asserted->bv_val[0]) ) {
1847 rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
1850 if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
1851 MatchingRule *asserted_mr = mr_bvfind( asserted );
1852 MatchingRule *stored_mr = mr_bvfind( &oid );
1854 if( asserted_mr == NULL ) {
1855 rc = SLAPD_COMPARE_UNDEFINED;
1857 match = asserted_mr != stored_mr;
1860 } else if ( !strcmp( syntax->ssyn_oid,
1861 SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
1863 AttributeType *asserted_at = at_bvfind( asserted );
1864 AttributeType *stored_at = at_bvfind( &oid );
1866 if( asserted_at == NULL ) {
1867 rc = SLAPD_COMPARE_UNDEFINED;
1869 match = asserted_at != stored_at;
1872 } else if ( !strcmp( syntax->ssyn_oid,
1873 SLAP_SYNTAX_OBJECTCLASSES_OID ) )
1875 ObjectClass *asserted_oc = oc_bvfind( asserted );
1876 ObjectClass *stored_oc = oc_bvfind( &oid );
1878 if( asserted_oc == NULL ) {
1879 rc = SLAPD_COMPARE_UNDEFINED;
1881 match = asserted_oc != stored_oc;
1887 LDAP_LOG( CONFIG, ENTRY,
1888 "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
1889 match, value->bv_val, asserted->bv_val );
1891 Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
1892 "%d\n\t\"%s\"\n\t\"%s\"\n",
1893 match, value->bv_val, asserted->bv_val );
1896 if( rc == LDAP_SUCCESS ) *matchp = match;
1907 struct berval *value,
1908 void *assertedValue )
1910 long lValue, lAssertedValue;
1912 /* safe to assume integers are NUL terminated? */
1913 lValue = strtol(value->bv_val, NULL, 10);
1914 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1915 return LDAP_CONSTRAINT_VIOLATION;
1918 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1919 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1920 && errno == ERANGE )
1922 return LDAP_CONSTRAINT_VIOLATION;
1925 *matchp = (lValue & lAssertedValue) ? 0 : 1;
1926 return LDAP_SUCCESS;
1935 struct berval *value,
1936 void *assertedValue )
1938 long lValue, lAssertedValue;
1940 /* safe to assume integers are NUL terminated? */
1941 lValue = strtol(value->bv_val, NULL, 10);
1942 if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) {
1943 return LDAP_CONSTRAINT_VIOLATION;
1946 lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
1947 if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX)
1948 && errno == ERANGE )
1950 return LDAP_CONSTRAINT_VIOLATION;
1953 *matchp = (lValue | lAssertedValue) ? 0 : -1;
1954 return LDAP_SUCCESS;
1957 #ifndef SLAP_NVALUES
1959 #include <openssl/x509.h>
1960 #include <openssl/err.h>
1963 * Next function returns a string representation of a ASN1_INTEGER.
1964 * It works for unlimited lengths.
1967 static struct berval *
1968 asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
1972 static char digit[] = "0123456789";
1974 /* We work backwards, make it fill from the end of buf */
1975 p = buf + sizeof(buf) - 1;
1978 if ( a == NULL || a->length == 0 ) {
1986 /* We want to preserve the original */
1987 copy = ch_malloc(n*sizeof(unsigned int));
1988 for (i = 0; i<n; i++) {
1989 copy[i] = a->data[i];
1993 * base indicates the index of the most significant
1994 * byte that might be nonzero. When it goes off the
1995 * end, we now there is nothing left to do.
2001 for (i = base; i<n; i++ ) {
2002 copy[i] += carry*256;
2003 carry = copy[i] % 10;
2008 * Way too large, we need to leave
2009 * room for sign if negative
2014 *--p = digit[carry];
2016 if (copy[base] == 0) base++;
2021 if ( a->type == V_ASN1_NEG_INTEGER ) {
2025 return ber_str2bv( p, 0, 1, bv );
2029 * Given a certificate in DER format, extract the corresponding
2030 * assertion value for certificateExactMatch
2033 certificateExactConvert(
2035 struct berval * out )
2038 unsigned char *p = in->bv_val;
2039 struct berval serial;
2040 struct berval issuer_dn;
2042 xcert = d2i_X509(NULL, &p, in->bv_len);
2045 LDAP_LOG( CONFIG, ENTRY,
2046 "certificateExactConvert: error parsing cert: %s\n",
2047 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2049 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
2050 "error parsing cert: %s\n",
2051 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2053 return LDAP_INVALID_SYNTAX;
2056 if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
2058 return LDAP_INVALID_SYNTAX;
2060 if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn )
2064 ber_memfree(serial.bv_val);
2065 return LDAP_INVALID_SYNTAX;
2070 out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
2071 out->bv_val = ch_malloc(out->bv_len);
2073 AC_MEMCPY(p, serial.bv_val, serial.bv_len);
2075 AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
2077 AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
2078 p += issuer_dn.bv_len;
2082 LDAP_LOG( CONFIG, ARGS,
2083 "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 );
2085 Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
2087 out->bv_val, NULL, NULL );
2090 ber_memfree(serial.bv_val);
2091 ber_memfree(issuer_dn.bv_val);
2093 return LDAP_SUCCESS;
2097 serial_and_issuer_parse(
2098 struct berval *assertion,
2099 struct berval *serial,
2100 struct berval *issuer_dn
2108 begin = assertion->bv_val;
2109 end = assertion->bv_val+assertion->bv_len-1;
2110 for (p=begin; p<=end && *p != '$'; p++) /* empty */ ;
2111 if ( p > end ) return LDAP_INVALID_SYNTAX;
2113 /* p now points at the $ sign, now use
2114 * begin and end to delimit the serial number
2116 while (ASCII_SPACE(*begin)) begin++;
2118 while (ASCII_SPACE(*end)) end--;
2120 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2122 bv.bv_len = end-begin+1;
2124 ber_dupbv(serial, &bv);
2126 /* now extract the issuer, remember p was at the dollar sign */
2128 end = assertion->bv_val+assertion->bv_len-1;
2129 while (ASCII_SPACE(*begin)) begin++;
2130 /* should we trim spaces at the end too? is it safe always? no, no */
2132 if( end <= begin ) return LDAP_INVALID_SYNTAX;
2135 bv.bv_len = end-begin+1;
2138 dnNormalize2( NULL, &bv, issuer_dn );
2141 return LDAP_SUCCESS;
2145 certificateExactMatch(
2150 struct berval *value,
2151 void *assertedValue )
2154 unsigned char *p = value->bv_val;
2155 struct berval serial;
2156 struct berval issuer_dn;
2157 struct berval asserted_serial;
2158 struct berval asserted_issuer_dn;
2161 xcert = d2i_X509(NULL, &p, value->bv_len);
2164 LDAP_LOG( CONFIG, ENTRY,
2165 "certificateExactMatch: error parsing cert: %s\n",
2166 ERR_error_string(ERR_get_error(),NULL), 0, 0 );
2168 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
2169 "error parsing cert: %s\n",
2170 ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
2172 return LDAP_INVALID_SYNTAX;
2175 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2176 dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn);
2180 serial_and_issuer_parse(assertedValue,
2181 &asserted_serial, &asserted_issuer_dn);
2186 slap_schema.si_syn_integer,
2187 slap_schema.si_mr_integerMatch,
2190 if ( ret == LDAP_SUCCESS ) {
2191 if ( *matchp == 0 ) {
2192 /* We need to normalize everything for dnMatch */
2196 slap_schema.si_syn_distinguishedName,
2197 slap_schema.si_mr_distinguishedNameMatch,
2199 &asserted_issuer_dn);
2204 LDAP_LOG( CONFIG, ARGS, "certificateExactMatch "
2205 "%d\n\t\"%s $ %s\"\n",
2206 *matchp, serial.bv_val, issuer_dn.bv_val );
2207 LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n",
2208 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2211 Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
2212 "%d\n\t\"%s $ %s\"\n",
2213 *matchp, serial.bv_val, issuer_dn.bv_val );
2214 Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
2215 asserted_serial.bv_val, asserted_issuer_dn.bv_val,
2219 ber_memfree(serial.bv_val);
2220 ber_memfree(issuer_dn.bv_val);
2221 ber_memfree(asserted_serial.bv_val);
2222 ber_memfree(asserted_issuer_dn.bv_val);
2228 * Index generation function
2229 * We just index the serials, in most scenarios the issuer DN is one of
2230 * a very small set of values.
2232 static int certificateExactIndexer(
2237 struct berval *prefix,
2245 struct berval serial;
2247 /* we should have at least one value at this point */
2248 assert( values != NULL && values[0].bv_val != NULL );
2250 for( i=0; values[i].bv_val != NULL; i++ ) {
2251 /* empty -- just count them */
2254 keys = ch_malloc( sizeof( struct berval ) * (i+1) );
2256 for( i=0; values[i].bv_val != NULL; i++ ) {
2257 p = values[i].bv_val;
2258 xcert = d2i_X509(NULL, &p, values[i].bv_len);
2261 LDAP_LOG( CONFIG, ENTRY,
2262 "certificateExactIndexer: error parsing cert: %s\n",
2263 ERR_error_string(ERR_get_error(),NULL), 0, 0);
2265 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2266 "error parsing cert: %s\n",
2267 ERR_error_string(ERR_get_error(),NULL),
2270 /* Do we leak keys on error? */
2271 return LDAP_INVALID_SYNTAX;
2274 asn1_integer2str(xcert->cert_info->serialNumber, &serial);
2276 xintegerNormalize( slap_schema.si_syn_integer,
2277 &serial, &keys[i] );
2278 ber_memfree(serial.bv_val);
2280 LDAP_LOG( CONFIG, ENTRY,
2281 "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0);
2283 Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
2290 keys[i].bv_val = NULL;
2292 return LDAP_SUCCESS;
2295 /* Index generation function */
2296 /* We think this is always called with a value in matching rule syntax */
2297 static int certificateExactFilter(
2302 struct berval *prefix,
2303 void * assertedValue,
2307 struct berval asserted_serial;
2310 ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL );
2311 if( ret != LDAP_SUCCESS ) return ret;
2313 keys = ch_malloc( sizeof( struct berval ) * 2 );
2314 xintegerNormalize( syntax, &asserted_serial, &keys[0] );
2315 keys[1].bv_val = NULL;
2318 ber_memfree(asserted_serial.bv_val);
2319 return LDAP_SUCCESS;
2325 check_time_syntax (struct berval *val,
2329 static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
2330 static int mdays[2][12] = {
2331 /* non-leap years */
2332 { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
2334 { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
2337 int part, c, tzoffset, leapyear = 0 ;
2339 if( val->bv_len == 0 ) {
2340 return LDAP_INVALID_SYNTAX;
2343 p = (char *)val->bv_val;
2344 e = p + val->bv_len;
2346 /* Ignore initial whitespace */
2347 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2351 if (e - p < 13 - (2 * start)) {
2352 return LDAP_INVALID_SYNTAX;
2355 for (part = 0; part < 9; part++) {
2359 for (part = start; part < 7; part++) {
2361 if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
2368 return LDAP_INVALID_SYNTAX;
2370 if (c < 0 || c > 9) {
2371 return LDAP_INVALID_SYNTAX;
2377 return LDAP_INVALID_SYNTAX;
2379 if (c < 0 || c > 9) {
2380 return LDAP_INVALID_SYNTAX;
2385 if (part == 2 || part == 3) {
2388 if (parts[part] < 0) {
2389 return LDAP_INVALID_SYNTAX;
2391 if (parts[part] > ceiling[part]) {
2392 return LDAP_INVALID_SYNTAX;
2396 /* leapyear check for the Gregorian calendar (year>1581) */
2397 if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
2398 ((parts[0] % 4 == 0) && (parts[1] == 0)))
2403 if (parts[3] > mdays[leapyear][parts[2]]) {
2404 return LDAP_INVALID_SYNTAX;
2409 tzoffset = 0; /* UTC */
2410 } else if (c != '+' && c != '-') {
2411 return LDAP_INVALID_SYNTAX;
2415 } else /* c == '+' */ {
2420 return LDAP_INVALID_SYNTAX;
2423 for (part = 7; part < 9; part++) {
2425 if (c < 0 || c > 9) {
2426 return LDAP_INVALID_SYNTAX;
2431 if (c < 0 || c > 9) {
2432 return LDAP_INVALID_SYNTAX;
2436 if (parts[part] < 0 || parts[part] > ceiling[part]) {
2437 return LDAP_INVALID_SYNTAX;
2442 /* Ignore trailing whitespace */
2443 while ( ( p < e ) && ASCII_SPACE( *p ) ) {
2447 return LDAP_INVALID_SYNTAX;
2450 switch ( tzoffset ) {
2451 case -1: /* negativ offset to UTC, ie west of Greenwich */
2452 parts[4] += parts[7];
2453 parts[5] += parts[8];
2454 for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
2458 c = mdays[leapyear][parts[2]];
2460 if (parts[part] > c) {
2461 parts[part] -= c + 1;
2466 case 1: /* positive offset to UTC, ie east of Greenwich */
2467 parts[4] -= parts[7];
2468 parts[5] -= parts[8];
2469 for (part = 6; --part > 0; ) {
2473 /* first arg to % needs to be non negativ */
2474 c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
2476 if (parts[part] < 0) {
2477 parts[part] += c + 1;
2482 case 0: /* already UTC */
2486 return LDAP_SUCCESS;
2489 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2494 struct berval *normalized )
2498 rc = check_time_syntax(val, 1, parts);
2499 if (rc != LDAP_SUCCESS) {
2503 normalized->bv_val = ch_malloc( 14 );
2504 if ( normalized->bv_val == NULL ) {
2505 return LBER_ERROR_MEMORY;
2508 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
2509 parts[1], parts[2] + 1, parts[3] + 1,
2510 parts[4], parts[5], parts[6] );
2511 normalized->bv_len = 13;
2513 return LDAP_SUCCESS;
2523 return check_time_syntax(in, 1, parts);
2528 generalizedTimeValidate(
2534 return check_time_syntax(in, 0, parts);
2538 generalizedTimeNormalize(
2543 struct berval *normalized )
2547 rc = check_time_syntax(val, 0, parts);
2548 if (rc != LDAP_SUCCESS) {
2552 normalized->bv_val = ch_malloc( 16 );
2553 if ( normalized->bv_val == NULL ) {
2554 return LBER_ERROR_MEMORY;
2557 sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
2558 parts[0], parts[1], parts[2] + 1, parts[3] + 1,
2559 parts[4], parts[5], parts[6] );
2560 normalized->bv_len = 15;
2562 return LDAP_SUCCESS;
2566 nisNetgroupTripleValidate(
2568 struct berval *val )
2573 if ( val->bv_len == 0 ) {
2574 return LDAP_INVALID_SYNTAX;
2577 p = (char *)val->bv_val;
2578 e = p + val->bv_len;
2580 if ( *p != '(' /*')'*/ ) {
2581 return LDAP_INVALID_SYNTAX;
2584 for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
2588 return LDAP_INVALID_SYNTAX;
2591 } else if ( !AD_CHAR( *p ) ) {
2592 return LDAP_INVALID_SYNTAX;
2596 if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
2597 return LDAP_INVALID_SYNTAX;
2603 return LDAP_INVALID_SYNTAX;
2606 return LDAP_SUCCESS;
2610 bootParameterValidate(
2612 struct berval *val )
2616 if ( val->bv_len == 0 ) {
2617 return LDAP_INVALID_SYNTAX;
2620 p = (char *)val->bv_val;
2621 e = p + val->bv_len;
2624 for (; ( p < e ) && ( *p != '=' ); p++ ) {
2625 if ( !AD_CHAR( *p ) ) {
2626 return LDAP_INVALID_SYNTAX;
2631 return LDAP_INVALID_SYNTAX;
2635 for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
2636 if ( !AD_CHAR( *p ) ) {
2637 return LDAP_INVALID_SYNTAX;
2642 return LDAP_INVALID_SYNTAX;
2646 for ( p++; p < e; p++ ) {
2647 if ( !SLAP_PRINTABLE( *p ) ) {
2648 return LDAP_INVALID_SYNTAX;
2652 return LDAP_SUCCESS;
2655 #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
2656 #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
2658 static slap_syntax_defs_rec syntax_defs[] = {
2659 {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
2660 X_BINARY X_NOT_H_R ")",
2661 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2662 {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
2664 {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
2666 {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
2668 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2669 {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
2671 #define berValidate blobValidate
2672 SLAP_SYNTAX_BER, berValidate, NULL},
2673 {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
2674 0, bitStringValidate, NULL },
2675 {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
2676 0, booleanValidate, NULL},
2677 {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
2678 X_BINARY X_NOT_H_R ")",
2679 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2680 {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
2681 X_BINARY X_NOT_H_R ")",
2682 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2683 {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
2684 X_BINARY X_NOT_H_R ")",
2685 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2686 {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
2687 0, countryStringValidate, NULL},
2688 {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
2689 0, dnValidate, dnPretty2},
2690 {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
2692 {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
2694 {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
2695 0, UTF8StringValidate, NULL},
2696 {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
2698 {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
2700 {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
2702 {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
2704 {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
2706 {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
2707 0, printablesStringValidate, NULL},
2708 {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
2709 SLAP_SYNTAX_BLOB, NULL, NULL},
2710 {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
2711 0, generalizedTimeValidate, NULL},
2712 {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
2714 {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
2715 0, IA5StringValidate, NULL},
2716 {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
2717 0, integerValidate, NULL},
2718 {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
2719 SLAP_SYNTAX_BLOB, blobValidate, NULL},
2720 {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
2722 {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
2724 {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
2726 {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
2728 {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
2730 {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
2731 0, nameUIDValidate, NULL},
2732 {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
2734 {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
2735 0, numericStringValidate, NULL},
2736 {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
2738 {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
2739 0, oidValidate, NULL},
2740 {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
2741 0, IA5StringValidate, NULL},
2742 {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
2743 0, blobValidate, NULL},
2744 {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
2745 0, UTF8StringValidate, NULL},
2746 {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
2748 {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
2750 {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
2751 0, printableStringValidate, NULL},
2752 {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
2753 X_BINARY X_NOT_H_R ")",
2754 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL},
2755 {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
2756 X_BINARY X_NOT_H_R ")",
2757 SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL},
2758 {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
2759 0, printableStringValidate, NULL},
2760 {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
2762 {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
2763 0, printablesStringValidate, NULL},
2764 #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
2765 {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
2766 0, utcTimeValidate, NULL},
2768 {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
2770 {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
2772 {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
2774 {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
2776 {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
2779 /* RFC 2307 NIS Syntaxes */
2780 {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
2781 0, nisNetgroupTripleValidate, NULL},
2782 {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
2783 0, bootParameterValidate, NULL},
2787 /* These OIDs are not published yet, but will be in the next
2788 * I-D for PKIX LDAPv3 schema as have been advanced by David
2789 * Chadwick in private mail.
2791 {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
2792 0, UTF8StringValidate, NULL},
2795 /* OpenLDAP Experimental Syntaxes */
2796 #ifdef SLAPD_ACI_ENABLED
2797 {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
2799 UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
2803 #ifdef SLAPD_AUTHPASSWD
2804 /* needs updating */
2805 {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
2806 SLAP_SYNTAX_HIDE, NULL, NULL},
2809 /* OpenLDAP Void Syntax */
2810 {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
2811 SLAP_SYNTAX_HIDE, inValidate, NULL},
2812 {NULL, 0, NULL, NULL}
2816 char *certificateExactMatchSyntaxes[] = {
2817 "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */,
2821 char *directoryStringSyntaxes[] = {
2822 "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */,
2825 char *integerFirstComponentMatchSyntaxes[] = {
2826 "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */,
2827 "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */,
2830 char *objectIdentifierFirstComponentMatchSyntaxes[] = {
2831 "1.3.6.1.4.1.1466.115.121.1.38" /* OID */,
2832 "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */,
2833 "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */,
2834 "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */,
2835 "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */,
2836 "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */,
2837 "1.3.6.1.4.1.1466.115.121.1.35" /* nameFormDescription */,
2838 "1.3.6.1.4.1.1466.115.121.1.37" /* objectClassDescription */,
2843 * Other matching rules in X.520 that we do not use (yet):
2845 * 2.5.13.9 numericStringOrderingMatch
2846 * 2.5.13.25 uTCTimeMatch
2847 * 2.5.13.26 uTCTimeOrderingMatch
2848 * 2.5.13.31 directoryStringFirstComponentMatch
2849 * 2.5.13.32 wordMatch
2850 * 2.5.13.33 keywordMatch
2851 * 2.5.13.35 certificateMatch
2852 * 2.5.13.36 certificatePairExactMatch
2853 * 2.5.13.37 certificatePairMatch
2854 * 2.5.13.38 certificateListExactMatch
2855 * 2.5.13.39 certificateListMatch
2856 * 2.5.13.40 algorithmIdentifierMatch
2857 * 2.5.13.41 storedPrefixMatch
2858 * 2.5.13.42 attributeCertificateMatch
2859 * 2.5.13.43 readerAndKeyIDMatch
2860 * 2.5.13.44 attributeIntegrityMatch
2862 static slap_mrule_defs_rec mrule_defs[] = {
2864 * EQUALITY matching rules must be listed after associated APPROX
2865 * matching rules. So, we list all APPROX matching rules first.
2867 #ifndef SLAP_NVALUES
2868 {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
2869 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2870 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2871 NULL, NULL, directoryStringApproxMatch,
2872 directoryStringApproxIndexer, directoryStringApproxFilter,
2875 {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
2876 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
2877 SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
2878 NULL, NULL, IA5StringApproxMatch,
2879 IA5StringApproxIndexer, IA5StringApproxFilter,
2884 * Other matching rules
2887 {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
2888 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
2889 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2891 objectIdentifierNormalize, octetStringMatch,
2892 octetStringIndexer, octetStringFilter,
2895 {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
2896 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
2897 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2899 dnNormalize, dnMatch,
2900 octetStringIndexer, octetStringFilter,
2903 {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
2904 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2905 SLAP_MR_EQUALITY | SLAP_MR_EXT,
2906 directoryStringSyntaxes,
2908 UTF8StringNormalize, octetStringMatch,
2909 octetStringIndexer, octetStringFilter,
2910 directoryStringApproxMatchOID },
2912 {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
2913 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2914 SLAP_MR_ORDERING, directoryStringSyntaxes,
2915 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2919 {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
2920 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2921 SLAP_MR_SUBSTR, NULL,
2922 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2923 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2926 {"( 2.5.13.5 NAME 'caseExactMatch' "
2927 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2928 SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
2929 NULL, UTF8StringNormalize, octetStringMatch,
2930 octetStringIndexer, octetStringFilter,
2931 directoryStringApproxMatchOID },
2933 {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
2934 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
2935 SLAP_MR_ORDERING, directoryStringSyntaxes,
2936 NULL, UTF8StringNormalize, octetStringOrderingMatch,
2940 {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
2941 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2942 SLAP_MR_SUBSTR, directoryStringSyntaxes,
2943 NULL, UTF8StringNormalize, octetStringSubstringsMatch,
2944 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2947 {"( 2.5.13.8 NAME 'numericStringMatch' "
2948 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
2949 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2950 NULL, numericStringNormalize, octetStringSubstringsMatch,
2951 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2954 {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
2955 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2956 SLAP_MR_SUBSTR, NULL,
2957 NULL, numericStringNormalize, octetStringSubstringsMatch,
2958 octetStringSubstringsIndexer, octetStringSubstringsFilter,
2961 {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
2962 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
2963 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2964 NULL, NULL, NULL, NULL, NULL, NULL},
2966 {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
2967 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
2968 SLAP_MR_SUBSTR, NULL,
2969 NULL, NULL, NULL, NULL, NULL, NULL},
2971 {"( 2.5.13.13 NAME 'booleanMatch' "
2972 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
2973 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2974 NULL, NULL, booleanMatch,
2975 octetStringIndexer, octetStringFilter,
2978 {"( 2.5.13.14 NAME 'integerMatch' "
2979 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2980 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2981 NULL, integerNormalize, integerMatch,
2982 octetStringIndexer, octetStringFilter,
2985 {"( 2.5.13.15 NAME 'integerOrderingMatch' "
2986 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
2987 SLAP_MR_ORDERING, NULL,
2988 NULL, integerNormalize, integerOrderingMatch,
2992 {"( 2.5.13.16 NAME 'bitStringMatch' "
2993 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
2994 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
2995 NULL, NULL, octetStringMatch,
2996 octetStringIndexer, octetStringFilter,
2999 {"( 2.5.13.17 NAME 'octetStringMatch' "
3000 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3001 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3002 NULL, NULL, octetStringMatch,
3003 octetStringIndexer, octetStringFilter,
3006 {"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
3007 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3008 SLAP_MR_ORDERING, NULL,
3009 NULL, NULL, octetStringOrderingMatch,
3013 {"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
3014 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3015 SLAP_MR_SUBSTR, NULL,
3016 NULL, NULL, octetStringSubstringsMatch,
3017 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3020 {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
3021 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
3022 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3024 telephoneNumberNormalize, octetStringMatch,
3025 octetStringIndexer, octetStringFilter,
3028 {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
3029 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
3030 SLAP_MR_SUBSTR, NULL,
3031 NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
3032 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3035 {"( 2.5.13.22 NAME 'presentationAddressMatch' "
3036 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
3037 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3038 NULL, NULL, NULL, NULL, NULL, NULL},
3040 {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
3041 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
3042 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3043 NULL, uniqueMemberNormalize, uniqueMemberMatch,
3047 {"( 2.5.13.24 NAME 'protocolInformationMatch' "
3048 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
3049 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3050 NULL, NULL, NULL, NULL, NULL, NULL},
3052 {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
3053 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3054 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3055 NULL, generalizedTimeNormalize, octetStringMatch,
3059 {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
3060 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
3061 SLAP_MR_ORDERING, NULL,
3062 NULL, generalizedTimeNormalize, octetStringOrderingMatch,
3066 {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
3067 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3068 SLAP_MR_EQUALITY | SLAP_MR_EXT, integerFirstComponentMatchSyntaxes,
3069 NULL, integerFirstComponentNormalize, integerMatch,
3073 {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
3074 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
3075 SLAP_MR_EQUALITY | SLAP_MR_EXT,
3076 objectIdentifierFirstComponentMatchSyntaxes,
3077 NULL, objectIdentifierFirstComponentNormalize, octetStringMatch,
3078 octetStringIndexer, octetStringFilter,
3081 #ifndef SLAP_NVALUES
3083 {"( 2.5.13.34 NAME 'certificateExactMatch' "
3084 "SYNTAX 1.2.826.0.1.3344810.7.1 )",
3085 SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
3086 certificateExactConvert, NULL, certificateExactMatch,
3087 certificateExactIndexer, certificateExactFilter,
3092 {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
3093 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3094 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3095 NULL, IA5StringNormalize, octetStringMatch,
3096 octetStringIndexer, octetStringFilter,
3097 IA5StringApproxMatchOID },
3099 {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
3100 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3101 SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
3102 NULL, IA5StringNormalize, octetStringMatch,
3103 octetStringIndexer, octetStringFilter,
3104 IA5StringApproxMatchOID },
3106 {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
3107 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3108 SLAP_MR_SUBSTR, NULL,
3109 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3110 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3113 {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
3114 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
3115 SLAP_MR_SUBSTR, NULL,
3116 NULL, IA5StringNormalize, octetStringSubstringsMatch,
3117 octetStringSubstringsIndexer, octetStringSubstringsFilter,
3120 #ifdef SLAPD_AUTHPASSWD
3121 /* needs updating */
3122 {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
3123 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
3124 SLAP_MR_EQUALITY, NULL,
3125 NULL, NULL, authPasswordMatch,
3130 #ifdef SLAPD_ACI_ENABLED
3131 {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
3132 "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
3133 SLAP_MR_EQUALITY, NULL,
3134 NULL, NULL, OpenLDAPaciMatch,
3139 {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
3140 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3142 NULL, NULL, integerBitAndMatch,
3146 {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
3147 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
3149 NULL, NULL, integerBitOrMatch,
3153 {NULL, SLAP_MR_NONE, NULL,
3154 NULL, NULL, NULL, NULL, NULL,
3159 slap_schema_init( void )
3164 /* we should only be called once (from main) */
3165 assert( schema_init_done == 0 );
3167 for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
3168 res = register_syntax( &syntax_defs[i] );
3171 fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
3172 syntax_defs[i].sd_desc );
3177 for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
3178 if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
3179 mrule_defs[i].mrd_compat_syntaxes == NULL )
3182 "slap_schema_init: Ignoring unusable matching rule %s\n",
3183 mrule_defs[i].mrd_desc );
3187 res = register_matching_rule( &mrule_defs[i] );
3191 "slap_schema_init: Error registering matching rule %s\n",
3192 mrule_defs[i].mrd_desc );
3197 res = slap_schema_load();
3198 schema_init_done = 1;
3203 schema_destroy( void )