RADIUS Client Frequently Asked Questions
Linux: Why does the the server or client start and run very slowly?
On Linux the source for random data, /dev/random, is sometimes blocking
for data. The server and client use a small
amount of data to prime it's generator from time to time.
Your program will block until some data is
available.
Another generator, /dev/urandom, is available and does not run out of
data. There are debates on its cryptographic strength.
There are two places to place the changes.
Command line:
-Djava.security.egd=file:/dev/urandom
Or
You can edit the file:
jre/lib/security/java.security
and change the property java.security.egd
In some versions of the JDK setting the property has no effect -
see JDK bug 6202721). It seems to work for AXL Software products.
I get the exception 'java.lang.NoClassDefFoundError:' when I start
the examples - what's wrong?
Your CLASSPATH is incorrect. The example classes are meant to run in
the directory where they're found. The batch and shell files are set
up to find the correct jar file (please look at the batch files to
see how they're trying to access the jar file). If you have extracted
everything correctly and set the CLASSPATH to include the extracted
files it will all work. There are many Web resources to help you set
up your CLASSPATH.
Why does the server say the password is bad, when it's obviously correct?
It is possible for the password to encoded properly (in any method but
PAP) yet the shared secret is wrong. The server will deduce that the
password is correct but the client will discover that the response
packet's authenticator is incorrect (mis-signed). The client must treat
the packet as an Access-Reject. Please see the section on Access-BadPacket.
What is a TLV attribute?
TLV stands for Tag / Length / Value. A RADIUS attribute consists of a
tag field (one octet), a length field (one octet) and the value field.
The length field include the tag and length field as well as the length
of the data field. All attributes are TLV attributes.
Why does the RADIUS client displays the packet as an Access-Accept but
the The RADIUSClient.authenticate() method returns 0?
See What does Access-BadPacket
mean?
What does Access-BadPacket mean?
The authenticate() or accounting() methods return 0 (Access-BadPacket)
if there are errors in the packet itself. Just receiving an Access-Accept
from the server doesn't
mean the packet is acceptable to the client. This can mean forgery
of the
reply but usually suggests misconfiguration. The RADIUSClient checks
the packet for correctness and may issue an Access_BadPacket response
in spite of the more favorable response attached to the packet.
The most common problem is mismatched secrets. The server response to
a packet is to sign it with the shared secret. The client checks the
signature using the secret. If the signatures don't match this is
a bad packet.
The particular reason can be found using the RADIUSClient.getError()
and getErrorString() methods.
Other errors include duplicate packet received, mismatched packet identifier
numbers, or a bad Message-Authenticator attribute.
The corrupt attribute error may result from actual corrupt attributes
or attributes with zero bytes of data. The latter problem can be generated
by a server that's not following the RADIUS specifications. If your
server is sending empty attributes and cannot be fixed use the RADIUSClient.allowEmptyAttributes(boolean
enable) method to work around the problem.
How do I create attributes?
Use the class AttributeList. It has many ways to create attributes, merge
attributes, and delete attributes.
How do I get the response attributes?
The RADIUSClient class makes these available as an AttributeList using
the getAttributes() method. These are available after the authentication()
or accounting() methods are called.
Why does the RADIUS server not respond?
There are many reasons for this. Please see the Trouble
Shooting Guide.
How do I perform PAP authentication?
Use the RADIUSClient's authenticate(String name, String password, AttributeList
alist) method.
How do I perform CHAP authentication?
There are two ways. The simplest is presented first:
// Create the required attributes
AttributeList aList = new AttributeList();
aList.addAttribute(Attribute.NAS_Identifier, Util.toUTF8("Pokey5"));
aList.addAttribute(Attribute.User_Name,Util.toUTF8("Gumby"));
// Authenticate using CHAP
result = r.authenticate(password.getBytes(), aList);
Here's another way:
// Create the CHAP attributes and merge them into
// the required aList attributes.
rc.createCHAP(password, aList);
rc.authenticate(aList);
How do I perform a MSCHAP or MSCHAP2 authentication?
MSCHAP authentication attributes are created by the createMSCHAP(byte[]
password, AttributeList list) method.
MSCHAP V2 authentication attributes are create by the createMSCHAP2(byte[]
name, byte[] password, AttributeList list) method.
Both return an AttributeList which is merged with other Access-Request
attributes.
// Create the required attributes
AttributeList aList = new AttributeList();
aList.addAttribute(Attribute.NAS_Identifier, Util.toUTF8("Pokey5"));
aList.addAttribute(Attribute.User_Name,Util.toUTF8("Gumby"));
// Create the MSCHAP attributes and merge them with the authentication
// attributes.
r.createMSCHAP(password.getBytes(), aList);
// Authenticate.
result = r.authenticate(aList);
MSCHAP V2 authentication is the same but uses the createMSCHAPV2()
method.
Why don't the accent characters in the User-Name look correct?
This is usually because the User-Name is not being correctly encoded
using the Util.toUTF8() method. the default encoding for the platform
may not be UTF8 (when doing IO or using String().getBytes()). Similarly
the data creating the name uses a Windows encoding that wasn't using
Unicode or UFT8 encoding. You may have to decode the data differently
before encoding it for the RADIUS client in UTF8.
Sometimes this can be seen in the length of the displayed User-Name attribute.
The Attribute.toString() or AttributeList.toString() methods will display
the User-Name. Accent characters should take up two octets, while Windows
page code will only produce one character accent octets, usually in
high ASCII values.
How do I create Vendor-Specific attributes (VSA)?
The VendorSpecific class builds VSA's. Vendor-Specific attributes allow
a company to create extensions to the RADIUS attributes. Each vendor
has a specific vendor number assigned to them.
First a little background: VSA's are attributes that contain sub-attributes.
That is to say each VSA will contain one or more RADIUS style Tag/Length/Value
(TLV) attributes. This allows the AttributeList class the create the
sub-attributes. While it's possible to place a number of VSA sub-attributes
in one Vendor-Specific attribute many RADIUS servers only examine the
first sub-attribute. It's safer to use one VSA per attribute value.
Here's an example of creating an Ascend VSA:
// Create and populate the request attribute list.
AttributeList requestList = new AttributeList();
...
// Create the Ascend VSA.
VendorSpecific vs = new VendorSpecific(Ascend.VENDORID);
vs.addAttribute(Ascend.Ascend_Disconnect_Cause, 1);
Attribute vsAttr = vs.getAttribute();
// Merge the completed VSA with the request attributes.
requestList.addAttribute(vsAttr);
There are more examples of creating and extracting VSA's in the API documentation
for the VendorSpecific class.
What about Cisco Vendor-Specific attributes?
Cisco's VSA's are a legacy from their proprietary TACACS protocol that
offers services similar to RADIUS. Cisco VSA's use what are called
Attribute Value Pairs (AVPairs). These are strings that represent the
attribute name and it's value. An example might help illustrate this.
VendorSpecific vs = new VendorSpecific(Cisco.VENDORID);
vs.addAttribute(Cisco.323_credit_amount, "323_credit_amount=1");
Or this:
VendorSpecific vs = new VendorSpecific(Cisco.VENDORID);
vs.addAttribute(Cisco.avpair, "323_credit_amount=1");
Good descriptions of AVPairs are available at Cisco.
Is it possible to disconnect a authenticated user after they have been
online for a certain period of time?
There are two time out attributes the server can send to the client.
Idle-Timeout and Session_Timeout. Both use a four byte integer usually
interpreted as seconds so twelve minutes won't be a problem. This is
typically sent to a dial-up hardware NAS which automatically disconnects
after either
value is reached. You could do the same in a software client. For example,
the Session_Timeout value is used in the AXL FTP server when it authenticates
against a
RADIUS server.
How can an authentication succeed (Access-Accept is returned) even though
there was a secret mismatch between the server and client?
Only PAP authentications are sensitive to mismatched secrets.
Other forms of authentication like CHAP and MSCHAP don't use the shared
secret to perform the authentication. The server will certainly
find the encoded password acceptable. Although the server may send back
an Access-Accept
the client is responsible for checking the signed authenticator
and rejecting the message if the signature isn't correct.
For example, a CHAP client uses an MD5 hash of a random challenge and
the plain text password to produce a hash of the password. The server
checks the MD5 of the password and the challenge and compares the two
results. If they're the same the password is correct.
The server resigns the packet using the original authenticator, the
secret, and the entire packet's contents. This is checked by the client
and if
there's a mismatch the client MUST reject the packet even if it's
an Access-Accept.
The presence of a Message-Authenticator (MA) attribute in the client
fixes the problem. The MA signs the authentication packet. The server
checks the signature which includes the shared secret. The response
packet also is provided with an MA and the client must check the
response MA for correctness. The AXL RADIUS Client can include an
MA by creating an Attribute.Message_Authenticator with any contents
(even empty). The contents are discarded by the client and replaced
with the signature.
Why do I get nothing but Access-Challenge responses from my Access-Requests?
You must pass all State attributes from the Access-Challenge to the new
Access-Request packet.
The RADIUS protocol is a 'stateless' protocol.
Each Access-Request acts like a new request each time. The server
tracks information that ties challenges to subsequent requests by using
the State attribute's value. This is opaque information and must be
returned without modification to the server. Although the standards
say only on State attribute is permitted some implementations include
more State attributes. You can extract all State attributes and merge
them with your new request as follows.
RADIUSClient rc = new RADIUSClient(...)
// Authenticate somehow
...
// Get the response attributes.
AttributeList response = rc.getAttributes();
// Extract all State attributes.
AttributeList state = response.getAttributeList(Attribute.State);
// Do something with Access-Challenge.
AttributeList request = new AttributeList();
...
// Merge the state attributes with the new request attributes.
request.mergeAttributes(state);
// Send the new authentication request.
...
What causes to server to say the packet is malformed?
If the RADIUS server is compliant with the basic packet construction
the AXL RADIUS Client will construct correct packets. However it's
possible to create attributes with a tag value of 0 or with an empty
data value. Both of these conditions are forbidden by servers. There
is no such attribute tag as 0 (valid values are 1 to 255). Attributes
must always have data with a length greater than 1 byte. Attribute
values with no value must not be sent.