Subject: Equality Matching of ACI Values

From: "Steven Legg" <[email-masked]>
Date: Thu, 19 Jul 2001 18:05:51 +1000

LDAPexters,

The semantics of equality matching for attribute values of the ACI syntax
has been little discussed. The current draft of the access control model
simply uses the general purpose directoryComponentsMatch rule from
draft-legg-ldapext-component-matching-03.txt as the equality matching
rule for the entryACI and subtreeACI attributes. The
directoryComponentsMatch
rule returns true if and only if all the component parts of two ACI values
being compared are the same. The precise meaning of "the same" depends on
the ASN.1 definition for the ACI syntax and is determined by the provisions
of the component matching draft.

A reasonable target for the design of an equality matching rule for the ACI
syntax is for the equality test to align with the semantic equivalence of
the values being compared. That is, two ACIs are equal if they mean the
same thing and are not equal if they mean different things. With such a
rule redundant duplication of access control information is prevented and
semantically distinct ACIs are never blocked from being added to the same
entry.

For most of the fields in an ACI the generic matching by
directoryComponentsMatch aligns quite nicely with semantic equivalence
within
the access control model. If two values of a field mean the same thing
directoryComponentsMatch says they are equal and if they mean different
things directoryConmponentsMatch says they are not equal. However, there
are two fields, <ipAddress> and <userid>, where the generic matching is
not well aligned and the discrepancy may not be to everyone's liking.

When I defined directoryComponentsMatch I also described a way of extending
it, so we can vary the meaning of "the same" for ACI matching in a
straightforward way if that is what the group wants. Later in this message
I show what that would look like for the access control model draft.

The component matching framework also provides ways of partially matching
ACI values. Some of the possible changes discussed below alter the ASN.1
definition for the ACI syntax and so have consequences on the partial
matching of ACIs (which are also discussed).

----------------------------------------------------------------------------
---

(1) IP Addresses

RFC 2373 allows leading zero digits in the number parts of the textual
representations of IP addresses and also allows for compressed
representations
of addresses. A single IP address can therefore have multiple
representations.
The ABNF for ACIs allows these multiple representations and the IP addresses
are copied verbatim into a UTF8String in the binary encoding. These multiple
representations for IP addresses aren't considered equal by the generic
matching semantics of directoryComponentsMatch since it just does a
caseIgnoreMatch of the IP address character strings.

Here are our options.

(1.A) Leave things as they are.

So two ACI values that have the same IP address for a machineSubject, but
using different representations, will not be equal, even if all the other
fields in the ACI are the same.

For example, these three ACI values mean the same thing but are not equal
as things are currently defined:

	grant:r#[all]#authnLevel:strong:ipAddress:::10.9.8.7
	grant:r#[all]#authnLevel:strong:ipAddress:::10.09.08.07
	grant:r#[all]#authnLevel:strong:ipAddress:0:0:0:0:0:0:10.9.8.7

If I wanted to use the componentFilterMatch matching rule to search for
ACIs that contain a particular IP address, e.g. with this filter,

	(entryACI:componentFilterMatch:=item:{
		component "subject.pureSubject.machineSubject.ipAddress.*.single",
		rule caseIgnoreMatch, value "::10.9.8.7" })

then I will only find the ACIs with exactly the representation of the IP
address I've chosen to search on. Also, the lexicographic ordering of IP
address textual representations doesn't conform to the natural ordering
of IPv6 addresses, so I can't write a sensible filter to match ACIs with IP
addresses less than or greater some presented value (according to the
caseIgnoreOrderingMatch rule "::10.9.8.7" is greater than "::10.10.8.7" !).

(1.B) Constrain the ABNF for <ipAddress> so that each IP address can be
represented in only one way.

There are a number of ways this could be done. One solution is to disallow
leading zero digits in all fields, require leading zero fields to be
compressed, but otherwise mandate the x:x:x:x:x:x:d.d.d.d form be used,
so for example, ::10.9.8.7 is okay but ::10.09.08.07 and
0:0:0:0:0:0:10.9.8.7
are not. This would clean up the equality matching, but the ordering
relationship is still all wrong. Different constraints would enable sensible
ordering matches but require less convenient representations of legacy
IPv4 addresses.

(1.C) Change the ASN.1 type corresponding to <ipAddress> to
IPAddress ::= OCTET STRING (SIZE(16)).

The conceptual data type for IP addresses that directoryComponentsMatch
operates on then becomes the address's 128 bit identifier. This implies a
notional translation from the textual representation (the ABNF for an ACI
doesn't change) into the 128 bit identifier before any comparison takes
place.
The default matching rule that directoryComponentsMatch applies to IPAddress
component values will be octetStringMatch.

These three ACI values will be equal because the corresponding 128 bit
identifier is the same in each case according to octetStringMatch:

	grant:r#[all]#authnLevel:strong:ipAddress:::10.9.8.7
	grant:r#[all]#authnLevel:strong:ipAddress:::10.09.08.07
	grant:r#[all]#authnLevel:strong:ipAddress:0:0:0:0:0:0:10.9.8.7

Because of the change to the associated ASN.1, the binary representation
of an ACI would contain IP addresses as their 128 bit identifiers
regardless of the textual representation used in the LDAP string
representation of the ACI value. It also means that if an ACI value is
converted to the binary representation and then back into the LDAP
string representation the textual representation of the IP addresses
may change (e.g. the first ACI value above may come back looking like
the third value).

Also, component matching becomes more awkward because the textual
representations cannot be used. To search for ACIs that contain a
particular IP address I would have to use a filter like this:

	(entryACI:componentFilterMatch:=item:{
		component "subject.pureSubject.machineSubject.ipAddress.*.single",
		rule octetStringMatch, value '0000000000000000000000000a090807'H })

It works but it isn't pretty. At least octetStringOrderingMatch conforms
to the appropriate ordering relationship for IP addresses so
componentFilterMatch can be used to find ACIs containing IP addresses
greater than or less than an asserted value.

(1.D) Derive a variant of directoryComponentsMatch that compares the textual
representations of IP addresses in exactly the way we want.

We can define an equality matching rule for IP address strings, let's call
it ipAddressMatch, which simply evaluates to true if and only if the
component value and assertion value represent the same 128 bit
IPv6 address, regardless of the format in which they are presented.

To make ipAddressMatch semantics apply when matching IP address fields of
values of the entryACI and subtreeACI attributes the equality matching rule
for these attributes has to be replaced with a variant of
directoryComponentsMatch, let's call it aciMatch, which is just like
directoryComponentsMatch except that it uses ipAddressMatch to compare
IPAddress components. I've provided some text at the end of this message
that shows how this would be written up in the ACM draft.

These three ACI values will be equal according to aciMatch:

	grant:r#[all]#authnLevel:strong:ipAddress:::10.9.8.7
	grant:r#[all]#authnLevel:strong:ipAddress:::10.09.08.07
	grant:r#[all]#authnLevel:strong:ipAddress:0:0:0:0:0:0:10.9.8.7

If I want to search for ACIs that contain a particular IP address then
this filter,

	(entryACI:componentFilterMatch:=item:{
		component "subject.pureSubject.machineSubject.ipAddress.*.single",
		rule ipAddressMatch, value "::10.9.8.7" })

will find the ACIs with any valid representation of the IP address (e.g.
::10.9.8.7, ::10.09.08.07 and 0:0:0:0:0:0:10.9.8.7 will match each other).

If we also define an ipAddressOrderingMatch that conforms to the necessary
ordering relationship for IP addresses then componentFilterMatch can also
be used to find ACIs containing IP addresses greater than or less than an
asserted value.

----------------------------------------------------------------------------
---

2) It isn't clear what sort of matching should apply to a <userid>
in a <uAuthzId> subject.

The ASN.1 type corresponding to <userid> in the ABNF for an ACI is UserID.
UserID is defined to be a UTF8String in the -08 draft of the Access
Control Model. A revised draft is expected to be submitted by Friday (20th)
in which the corresponding ASN.1 type will have changed to OCTET STRING.
There are pros and cons either way, but there is also an improved solution
in the same style as (1.D).

The <userid> is one form of authorization identity defined in RFC 2829 and
is rendered as a UTF8 character string. RFC 2829 imposes no particular
interpretation on the authorization identity strings. Whether, for example,
"SMITH" and "smith" represent the same identity or different identities
is a local implementation or deployment matter. Spaces in the identity
strings may or may not be significant. If <userid> is mapped to an ASN.1
UTF8String directoryComponentsMatch will default to a caseIgnoreMatch of
identities, possibly regarding two separate identities as the same identity.
If <userid> is mapped to an ASN.1 OCTET STRING directoryComponentsMatch
will default to an octet comparison of the identities, possibly failing
to recognize two authorization identities as being the same.

Here are the options.

(2.A) Retain OCTET STRING as the ASN.1 type of UserID.

This is the conservative approach.

The disadvantage of having UserID defined as an OCTET STRING is that if
I want to use componentFilterMatch to search for ACIs that contain a
particular <userid> then I can only apply octetStringMatch to the UserID
component, e.g. like so:

	(entryACI:componentFilterMatch:=item:{
		component "subject.pureSubject.idBasedSubject.oneSubject.user",
		rule octetStringMatch, value '736D697468'H })

I can't use caseIgnore or caseExact equality, ordering or substrings rules.
They are undefined on OCTET STRING components.

(2.B) Change the ASN.1 type of UserID back to UTF8String.

If a deployment uses case sensitive user IDs two ACIs that apply to
completely different users can evaluate to equal. For example, these
two ACIs would be equal:

	grant:r#[all]#authnLevel:strong:authzId-u:SMITH
	grant:r#[all]#authnLevel:strong:authzId-u:smith

and so couldn't appear in the same entry. That presents a problem for
managing
ACIs if "SMITH" and "smith" are different users.

The advantage of defining UserID as a UTF8String is that it is possible
to use componentFilterMatch in a more convenient way to search for ACIs
that contain a particular user ID, e.g. with a filter like this:

	(entryACI:componentFilterMatch:=item:{
		component "subject.pureSubject.idBasedSubject.oneSubject.user",
		rule caseIgnoreMatch, value "smith" })

It is also possible to use ordering or substrings rules, and the caseExact
counterparts of the caseIgnore rules. The client chooses between caseIgnore
and caseExact matching to suit their deployment.

(2.C) Derive a variant of directoryComponentsMatch that compares UTF8String
UserID components character by character.

UserID is defined to be a UTF8String again and we define an equality
matching rule, let's call it characterStringMatch, which evaluates to
true if and only if the attribute/component value and assertion value
match exactly character by character. Letter case and all spaces are
significant.

If we aren't already doing so to implement (1.D), we define aciMatch
as a variant of directoryComponentsMatch, to (additionally)
compare UserID components using characterStringMatch.

These two ACI values will not be equal according to aciMatch
(the conservative approach):

	grant:r#[all]#authnLevel:strong:authzId-u:SMITH
	grant:r#[all]#authnLevel:strong:authzId-u:smith

However, because UserID is a UTF8String it is possible to use filters
like these:

	(entryACI:componentFilterMatch:=item:{
		component "subject.pureSubject.idBasedSubject.oneSubject.user",
		rule caseIgnoreMatch, value "smith" })

	(entryACI:componentFilterMatch:=item:{
		component "subject.pureSubject.idBasedSubject.oneSubject.user",
		rule caseExactMatch, value "smith" })

----------------------------------------------------------------------------
---

The easiest thing to do is just stay with the status quo, options (1.A)
and (2.A), and accept their idiosyncracies. With regard to (1), IP address
subjects should be discouraged anyway, so perhaps we shouldn't be too
worried
about how well they are matched.

The solutions with the nicest all round properties are (1.D) and (2.C).
What follows is the text that would be added to the Access Control Model
draft to effect these changes. Then the only other changes that need to
be made are to replace directoryComponentsMatch with aciMatch in the
definitions for entryACI and subtreeACI, and to redefine the UserID ASN.1
type as a UTF8String. No changes to the ABNF would be required.

----------------------------------------------------------------------------
---

The LDAP definition for the aciMatch matching rule is:

( <OID-to-be-supplied> NAME 'aciMatch'
    SYNTAX 1.2.36.79672281.1.5.3 )

The aciMatch matching rule is derived from the directoryComponentsMatch
matching rule in [DirCompMatch]. The derived matching semantics of
aciMatch are defined by the following table, using the convention
described in Section 7.2 of [DirCompMatch].

  ASN.1 Type  | Matching Rule
  ============+=====================
  UserID      | characterStringMatch
  IPAddress   | ipAddressMatch

The LDAP definition for the characterStringMatch matching rule is:

( <OID-to-be-supplied> NAME 'characterStringMatch'
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )

The characterStringMatch rule evaluates to true if and only if the
attribute or component value and the assertion value have the same
number of characters and corresponding characters are the same.
Letter case and whitespace characters are significant in the comparison.
This matching rule may be applied to attribute or component values
of the DirectoryString ASN.1 type, any of the ASN.1 restricted character
string types, or their ASN.1 subtypes.

The LDAP definition for the ipAddressMatch matching rule is:

( <OID-to-be-supplied> NAME 'ipAddressMatch'
    SYNTAX <OID-IPAddress-syntax> )

The ipAddressMatch rule evaluates to true if and only if the attribute
or component value and the assertion value represent the same 128 bit
IPv6 address identifier, regardless of the textual format in which they
are presented.

The LDAP definition for the IPAddress syntax is:

( <OID-IPAddress-syntax> DESC 'IPAddress' )

This syntax corresponds to the IPAddress ASN.1 type from Section 4.1.2.
The LDAP string representation of attribute or assertion values in this
syntax is described by the <ipAddress> rule in Section 4.1.1.

----------------------------------------------------------------------------
---

Cast your votes !

Regards,
Steven

---

From: Ellen Stokes <[email-masked]>
Date: Tue, 24 Jul 2001 15:09:07 -0500

Folks,

Since Steven Legg put out the options and proposed resolutions,
there has been no comment on the mailing list.

The authors plan to change the draft to reflect 1A and 2A.

Speak your comments now...

Ellen

>From: "Steven Legg" <[email-masked]>
>To: <[email-masked]>
>Subject: Equality Matching of ACI Values
>Date: Thu, 19 Jul 2001 18:05:51 +1000
>Message-ID: <[email-masked]>
>MIME-Version: 1.0
>Content-Type: text/plain;
>         charset="iso-8859-1"
>Content-Transfer-Encoding: 7bit
>X-Priority: 3 (Normal)
>X-MSMail-Priority: Normal
>X-Mailer: Microsoft Outlook 8.5, Build 4.71.2377.0
>Importance: Normal
>X-MimeOLE: Produced By Microsoft MimeOLE V4.72.2120.0
>Resent-Message-ID: <"68HuxC.A.NOC.JTpV7"@glacier>
>Resent-From: [email-masked]
>X-Mailing-List: <[email-masked]>
>X-Loop: [email-masked]
>Precedence: list
>Resent-Sender: [email-masked]
>
>
>LDAPexters,
>
>                 component 
> "subject.pureSubject.machineSubject.ipAddress.*.single",
>                 component 
> "subject.pureSubject.machineSubject.ipAddress.*.single",
>                 component 
> "subject.pureSubject.machineSubject.ipAddress.*.single",
>                 component 
> "subject.pureSubject.idBasedSubject.oneSubject.user",
>                 component 
> "subject.pureSubject.idBasedSubject.oneSubject.user",
>                 component 
> "subject.pureSubject.idBasedSubject.oneSubject.user",
>                 component 
> "subject.pureSubject.idBasedSubject.oneSubject.user",