[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Formats for structured attributes



Hi,

On Thu, Mar 09, 2006 at 12:06:09PM -0500, Nelson, David wrote:

> Emile van Bergen writes...
>  
> > Where there are two bits of information for one attribute, pre-RADEXT
> > RADIUS has always taken the approach of simply putting them together
> > into C struct-like subfields. That can hardly come as a surprise, and
> > indeed, without a grouping mechanism, it's the most efficient and
> > sensible approach.
> > 
> > As long as the compound format made sense for the actual entity
> > generating or processing the attribute's contents and as long as the
> > individual member values were not needed in any RADIUS policy nor
> > generated dynamically by the RADIUS server proper, there's never been a
> > strong problem with such compound attributes, and I don't think there
> > necessarily should be any such problem now.
> 
> I think it would be very valuable to allow the expression of compound
> data elements in attribute formats that permit an extended form of data
> dictionary driven RADIUS server to add new instances of these attributes
> into the data dictionary.  What I advocate is a mechanism that
> regularizes the on-the-wire encoding of the equivalent of C-language
> structures in RADIUS attributes, such that new attributes can be added
> to a data dictionary, and the sub-elements of the structure can be
> described in that fashion.

An implementation of such a mechanism can be seen in OpenRADIUS; you can
there specify in the dictionary that an attribute contains a 'subspace',
and specify how that space is to be parsed: either as a list of fields
at fixed offsets or as a set of TLVs in whatever format. 

Each parsed item can then be addressed individually in administrator
defined policies.

> > Case in point: MS-CHAP2-Response (RFC 2548); this attribute only
> > makes sense as a whole and only to the actual MSCHAPv2 authenticator
> endpoint;
> > the values of the individual subfields are neither dynamically
> generated
> > at the RADIUS level nor interpreted by the server as part of
> > executing any local policy.
> 
> If you implement the MS-CHAP authenticator as a "plug-in" module to
> the RADIUS server, this makes some sense.

Whether or not you make that module an external plug in, it still holds
that the fewer cross dependencies, the better. 

If a dictionary driven RADIUS attribute layer is independent from the
policy engine and both are independent from the authenticators, then
everyting can evolve independently, without having to redesign everything
when one becomes obsolete. 

Currently, this is very well possible with RADIUS, even with most of the
baroque attributes that have sprung into existence over the years.

In the case of MS-CHAP, neither the packet decoder nor the policy engine
needs to know the internal structure of the CHAP Response attribute. And
the MS-CHAP authenticator only to know the value of that attribute,
together with a cleartext or RC4 password; it does not need any
knowledge about the packet or the server policy.

Another example is Ascend-Data-Filter; you can translate the textual
format into the binary format using an external tool, and simply put the
binary value in your user profile. The translation does not need to
happen separately for each request, and therefore no specific knowledge
about the attribute's internal syntax is needed by the packet encoder or
the policy engine.

A counterexample is Message-Authenticator: for verification, you need
to access both the RADIUS packet as a whole and the attribute itself,
and for generation it's worse: the attribute needs to be updated in situ
after the whole packet has been encoded. Thus, even the lowest layer of
a RADIUS implementation needed changes when this attribute was
introduced.

This was therefore a very problematic attribute, but of course it was
still the most reasonable solution for improving signatures for requests
and responses. The only alternative would be an extra fixed header,
which would create an incompatible protocol.

> > The current Extended Attribute draft uses the DIAMETER format, and the
> > only facility it has toward structured data is the 'Grouped' data
> > type, which is a *blank* container for *top level* attributes only.
> 
> Then maybe we need to discuss a more general notion of a regularized,
> and extensible data model for RADIUS that easily encompasses structured
> data.

My suggestion for the format of the attributes inside the Extended
Attribute space as described in
http://www.e-advies.nl/ietf/draft-evbergen-radext-extended-attribute-01.txt
proposes nested attributes to create structured data, and creates a
model with the following properties:

* All A/V pairs, including all subattrbutes, are still primarily made
  available as a flat list of TLVs, as in normal RADIUS, but with an
  additional Tag field as in RFC 2868. Relative ordering of instances of
  the same attribute is preserved.  

* Grouping pairs by their tags, you can create an ordered list of
  sets of A/V pairs, and uniquely address a set of pairs containing tag
  Y, or the n'th tagged set. This mechanism is already deployed in any
  NAS that supports RFC 2868.

  Thus, in a policy engine, pairs can be addressed uniquely as the
  n'th instance of attribute X with tag Y.

  Eg. (last)Tunnel-Media-Type:1 == IPv4

* Because any pair can refer to a tagged set of attributes as its 
  subordinates, using a dedicated Child-Tag field, you can create a
  nested structure of attributes.
  
  Any attribute of any type can at the same time convey a value as well
  as a set of subattributes. 

  Whether the attribute has a value, a set of subattributes, both, or
  none is *not* dependent on a-priori information about the attribute
  (eg. from the dictionary), but is made clear in the header: if the
  Length spans only the header, the attribute has no value, and if the
  Child-Tag field is zero, the attribute does not refer to any tagged
  set as its children.

* In addition to the Type field, each attribute contains a 32-bit
  STD/Vendor field that defines the number space for the Type field. It
  allows 2^24 vendors, 2^24 SDOs, 2^24 IETF standards to each govern
  2^32 attributes. 

  One particular value of the STD/Vendor field specifies that the
  attribute's Type number is to be interpreted relative to the parent
  attribute that refers to the tagged set as its child set. In other
  words, it allows each attribute to define subattributes without
  cluttering the global attribute number space.

  Because the 'locally numbered' subattributes exist in a distinct
  number space, no clashes occur, even if you look at all pairs as
  a flat list.

  While it is impossible to distinguish among *local* attributes of any
  type without looking at the nested structure created by the Tags and
  Child-Tags, it's still possible to distinguish all *local* attributes
  of a certain Type from all *global* attributes of that Type, because
  the former use a specific value in the STD/Vendor field.

* So, as long as you record each attribute's tag, child-tag, and
  preserve the relative ordering of all attributes of the same type,
  parsing a packet into a flat list does not cause you to loose any
  information at all.

  Thus, the packet decoder/encoder neither requires any knowledge about
  the nested data structure, nor does anything that addresses the
  structured data require knowledge that is only available in the
  encoder/decoder.

  The structure exists entirely on a level above the parsed list of
  Std/Vendor, Type, Tag, Child-Tag, Value tuples.

Thus, in addition to the tagged flat list perspective, my proposal for
structured data in RADIUS allows a policy engine to refer to
subattribute X in the unique tagged set that is referred to as a child
set by attribute Y.

An example: 

When a policy engine would parse a test for 
	
	Framed-Tunnel::Media-Type == IPv4, 
	
you'd first search for the STD/Vendor/Type tuple of a Framed-Tunnel
attribute in your dictionary. 

You would then look up the Type number for a Media-Type attribute that
is defined as a subattribute of Framed-Tunnel; if one is found, the
STD/Vendor/Type tuple is known, because all parent dependent attributes
use the same value for the STD/Vendor field.

If none is found, you would search for the Media-Type attribute in the
main dictionary to obtain the global STD/Vendor/Type tuple, if
Media-Type is a regular top level attribute.

Finally, you'd search for the constant value for 'IPv4' in the list of
named constants associated with that Media-Type (sub)attribute.

Then, you'd apply this test in your policy engine as follows:

Search for the first (or last) instance of the attribute on the request
list with the known 64-bit STD/Vendor/Type tuple belonging to
Framed-Tunnel, ignore the value, if any, and obtain the Child-Tag.

Next, search for the first (or last) instance of the attribute on the
request list with the known STD/Vendor/Type tuple belonging to
Media-Type and the tag found in the previous step.

You would then take the value of this instance of the attribute and 
compare it to the known value for IPv4 for this attribute. 

==

In short: in my proposal, all attributes can contain structured data,
member attributes don't need to be allocated a global Type number,
structuring can be done to any depth, and structure is preserved when
transporting a flat list of pairs.

Traversing the attribute space is simple and efficient; attributes are
aligned at 4-octet boundaries, just as with DIAMETER. By contrast,
searching for an instance of an attribute in a packet can be done using
a single unconditional 64-bit compare; each attribute starts with the
32-bit STD/Vendor field, followed by the 32-bit Type field.

The DIAMETER attribute Type space is fully incorporated, but
non-DIAMETER attributes can be defined as well, and room is created for
other SDOs to assign their own attribute Type spaces.

The only metadata about the value given by the attribute header is the
value's length in octets; without a priori knowledge of the attribute
(dictionary), the value's data type is unknown. Of course, that does not
prevent policy engines from comparing or retrieving such values; after
all, in addition to their native type, every value is also of the known
and well supported type 'string of octets'.

Of course, you may argue that this format is a bit too flexible and
provides too many ways to shoot yourself in the foot, but I think that
in cases like this, it's better to have strong style and strong data
type recommendations together with an expressive format, than a format
in which you cannot express bad thoughts at all. 

Structure evolves much slower than style, after all.

Cheers,


Emile.

-- 
E-Advies - Emile van Bergen           emile@e-advies.nl      
tel. +31 (0)78 6136282           http://www.e-advies.nl    

--
to unsubscribe send a message to radiusext-request@ops.ietf.org with
the word 'unsubscribe' in a single line as the message text body.
archive: <http://psg.com/lists/radiusext/>