Thanks for your prompt reply. Please see my comments interspersed below. On Wed, Dec 26, 2012 at 6:19 PM, Alan DeKok <aland@deployingradius.com> wrote:
JCA wrote:
I would like to be able to use a vendor-specified attribute, rather than Reply-Message, and to that end I added the following entry to the dictionary files in both client and server:
VENDOR MyVendorID 29688
BEGIN-VENDOR MyVendorID ATTRIBUTE Vendor-Attr 1 string END-VENDOR MyVendorID
(the vendor ID used here is bogus.) I also changed my users on the server as follows:
user1 User-Password != "User1Password" user1 Cleartext-Password := "User1Password" Vendor-Attr = "Authentication successful."
I'd give it a better name than that... but OK.
After launching the server on A again, and attempting an authentication from B, debugging the client on B reveals that the server is indeed sending the Vendor-Attr attribute with the value specified in the users file. The rc_avpair_gen() function in the client code on B detects a vendor-specified attribute, and after properly identifying it as MyVendorID it attempts to decode the attribute that follows by recursively invoking itself. In more detail:
The first few bytes of the data received from the server is
0x1a 0x1b 0x00 0x00 0x73 0xf8 0x01 0x15
That's how RADIUS works.
You need to add the vendor dictionary on the client side, too.
I added the VENDOR definition that I mentioned above to both client and server already.
The code then proceeds to invoking rc_dict_getattr() in order to get the attribute, using as arguments the dictionary data previously loaded when launching the client, plus the value of the attribute variable obtained above. rc_dict_getattr() will just loop over all entries in the dictionary data, trying to find a match. This is a very simple function:
Yes... there's no need to include the code here. We *do* have access to it.
I included the code because I can't understand how it could ever work. How can the comparison between attr->value and attribute, as I described, ever succeed? The value of attribute as received from rc_avpair_gen() contains both the vendor ID and the attribute identifier, whereas the value of attr->value only contains the attribute identifier. This comparison can never succeed.
The comparison in the loop above will not succeed, because attr->value is 1, whereas attribute is 0x73f80001. Therefore no match will be found, and rc_dict_getattr() will return a NULL pointer, thus causing rc_avpair_gen() to generate an error message as follows:
received unknown VSA attribute 1, vendor 29688 of length xx
where xx is the length of the "Authentication successful." string.
Thus, it would seem that the data was received correctly, but can't somehow be decoded.
Yes. You need to add the dictionary on the client side, too.
Like I said, I added to both client and server before I started testing.
The main FreeRADIUS library handles this properly, by the way. It allows you to reference attributes which don't have any dictionaries.
Anybody know what is going on here? I would be tempted to say that the rc_dict_getattr() implementation is wrong, but I find it difficult to believe that it is THAT wrong - this wouldn't be just a bug, but a huge implementation error. Therefore, I must be doing something wrong myself instead. But, what? How do I define my simple vendor-specific attribute so that rc_get_attr() can identify and decode it correctly?
Use a dictionary.
Or, update the code so that it still creates AVPairs, even if it doesn't have a dictionary entry. This is what the FreeRADIUS server does.
Alan DeKok. - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html