This patch implements tagged and encrypted attributes according to RFC 2868 (RADIUS Tunnel Authentication Attributes), in README.tunnel (included below) referred to as draft-ietf-radius-tunnel-auth-09 as it was called at the time. You'll also find that document in the doc/ directory after applying the patch. There are some other features in this patch that don't have anything to do with RFC 2868, but were easy to implement now that the infrastructure to support tags (attribute options in general) is in place anyway: * A dictionary option to 'support' NASes that use braindead length fields in their VSAs - you can now adjust the value sent, like you can with some other radius servers. Also described in README.tunnel (below). * Better handling of realm options: - fixed the broken 'trusted' option introduced in 1.6.4; - added local_acct and local_auth as synonyms for the noacct/noauth options introduced in 1.6.4, and changed their implementation a little to behave _exactly_ like if LOCAL was specified for that realm for that type of request. ---------------------------------------------------------------------------- README.Tunnel ---------------------------------------------------------------------------- TUNNEL SUPPORT: TAGGED & ENCRYPTED ATTRIBUTES 0. Introduction More and more NASes are able to set up L2TP or L2F tunnels these days. The L2F (layer 2 forwarding) protocol and the newer L2TP (layer two tunneling protocol) allows a complete PPP session to be re-framed in e.g. UDP and forwarded a the device that will actually handle the PPP session: do LCP and IPCP negotiation, assign IP addresses, apply filters, and so on. This can be used for e.g. roaming dial-up access: you dial into a NAS, the NAS recognises your realm, sets up a tunnel to your home site / ISP and forwards your PPP session to that tunnel endpoint, where you'll get authenticated and authorised as if you were directly connected to the tunnel endpoint. 1. Tunnels and Radius Obviously, the NAS needs to know the tunnel endpoint that belongs to a specific user realm. Also obviously, managing a table like this on each NAS in your network, is not really a nice job. So how can RADIUS help here? By keeping the realm-to-tunnel mapping table on the RADIUS server, and telling the NASes on request what tunneling parameters need to be applied to a specific session. The IETF draft that has the details on the new RADIUS attributes to carry these tunnel parameters is draft-ietf-radius-tunnel-auth- xx.txt (09 is the latest version, 2000-06-07). Reading it before using the new attributes is really a good idea. 2. Tunneling attributes The nasty thing about these new attributes is that they contain a sort of, but not really, optional numeric attribute tag field, which is inserted before, or overlaps with, the value field. (It's a bit of a mess, really, and the purpose isn't all that clear either - you'll have to use your imagination a bit before you really think of a good use for these tags. And afther that, you'll be left with a vague feeling like 'there must be a better way to do that, but I can't really think of one right now...'. But that may just have been me; read the ietf draft and see for yourself). Anyway, the NAS vendors like them, and it's better to use these attributes than a vendor specific solution anyway, so I've added tagged attribute support to Cistron RADIUS. Another thing is the fact that L2TP tunnels are to be authenticated themselves using a shared secret. The RADIUS attribute to tell the NAS the secret for authenticating to the other tunnel endpoint must, for obvious reasons, be encrypted. This is also specified in the draft for that attribute. 3. Changes to Cistron RADIUS There are a couple of changes with respect to Cistron's configuration files. * Dictionary files: The optional fourth field of the attribute definition lines in the dictionary in which the vendor could be specified has been changed to a more general optional options field. Multiple options are allowed, separated by commas, but be sure not to add any whitespace anywhere in the options field. Currently recognised options are: - has_tag Boolean option; specifies whether this or attribute can have a numeric tag. has_tag= (Numeric version: specify 0 (default) for no or something !=0 for yes.) - encrypt= Numeric option; specifies the encryption method for this attribute. Valid values currently are: 0 - no encryption (default) 1 - do 'Tunnel-Password'-style encryption per draft-ietf radius-tunnel-auth-09. Of course, other methods may be added if a new standard emerges. - len+= Numeric option; specifies an adjustment or to the length field of this attribute to len-= provide interoperability with RFC violating NASes that use different (plain wrong, that is) length fields in their communications. If you specify a positive value after len+, it means that the NAS sends and expects a length that is higher than the RFC specifies for this attribute. This difference is is used in three places: - it's substracted from the length field on receipt of an access request or accounting packet; - it's added to the length field again when sending a proxied request, to emulate the NASes behaviour and thus stay as transparent as possible; - it's added to the length field when replying to the NAS. Note that if an adjustment is specified for a vendor-specific attribute, only the length field encapsulated in the VSA is adjusted, not the VSA length itself. I don't know whether those strange NASes expect things this way or the whole VSA adjusted, as luckily I don't operate any of these brain-dead NASes. - vend= String option; specifies the vendor for a vendor-specific attribute. - 'Boolean' option; specifies the vendor in the old way, for backwards compatibility. This is tried after the normal options, so a vendor called 'has_tag' can only be specified using the new syntax ;-) * Users file: Check- and reply items having attributes for which the has_tag flag is present in the dictionary, may optionally have a tag specified. If no tag is specified for such an attribute, the parser will assume 0 as the tag. The syntax for a tagged attribute is: attribute[:tag] operator value An asterisk ('*') may also be specified as the tag for check items. This indicates that the check item is to be compared to a matching received attribute, regardless of its tag. Otherwise, an attribute with a different tag is considered a different attribute. This is a little different from e.g. Merit's implementation, where a tag is really considered part of the value of the attribute. This is only true if you look at how the tags are sent in a radius packet; if you look at the introduction in the ietf draft, you can see that a tag effectively says something about attributes, not about values: 'Multiple instances of each of the attributes defined below may be included in a single RADIUS packet. In this case, the attributes to be applied to any given tunnel SHOULD all contain the same value in their respective Tag fields; otherwise, the Tag field SHOULD NOT be used. If the RADIUS server returns attributes describing multiple tunnels then the tunnels SHOULD be interpreted by the tunnel initiator as alternatives and the server SHOULD include an instance of the Tunnel-Preference Attribute in the set of Attributes pertaining to each alternative tunnel. Similarly, if the RADIUS client includes multiple sets of tunnel Attributes in an Access-Request packet, all the Attributes pertaining to a given tunnel SHOULD contain the same value in their respective Tag fiels and each set SHOULD include an appropriately valued instance of the Tunnel-Preference Attribute.' It's rather vague, in my opinion, so for those who prefer Merit's syntax (attribute = :tag:value), I've provided an option in conf.h to switch between the two. Note that the selected syntax for the users file is also used as the output format in the accounting detail files. That's it, basically. If you'd like more details, look in radius.c (rad_send_reply, encrypt_attr_style_1, radrecv), files.c (userparse, mainly), dict.c and attrprint.c. If you have any suggestions for improvement, or dislike my implementation for any reason, please don't hestitate to contact me at emile@evbergen.xs4all.nl. (Miquel / Alan, this especially applies to you, of course! ;-). Emile van Bergen.