XTRadius SourceForge Logo 
Home | Download | Documentation | Support | Development  
Example Script

Documentation > FAQ

1.0 Setup and Installation

1.1 How do I install XTRadius?

See the install file contained in the distribution, XTRadius is based on cistrond code, so the installation is very similar. Basically in the XTRadius directory, do the following:
cd src/
ls Makefile*
cp Makefile.OS Makefile # (Replace OS with the name of your OS)
make install

This will compile and install xtradius, and put a raddb directory in /etc. For more information on setting up and installing XTRadius, please see the quickstart guide.

1.2 How do I configure Xtradius?

Because XTRadius is based on Cistron, please visit http://www.radius.cistron.nl, and see the README and FAQ before attempting to install or configure xtradius. Only the extensions xtradius introduces on top of cistron will be covered throughout this documentation. Once you have a cistron setup working properly with the system file, please see the quickstart guide.

1.3 How do I watch what is happening in XTRadius? A user who should be able to connect is being refused login.

Run XTRadius in debug and non-daemon mode so you can watch how it is handling authentication. First make sure radiusd is not running, and issue /path/to/radiusd -sxxy. This will enable you to see everything that is happening. See the 'radiusd' man page for more startup options.

1.4 How do I make xtradius start automatically at boot time?

There are init scripts included for both RedHat and Debian in the tarball. Firstly make sure radwatch is installed (cp scripts/radwatch /usr/sbin). For redhat users, copy the rc.radiusd-redhat script in the redhat/ subdirectory to /etc/rc.d/init.d/ and run chkconfig. For debian, copy the rc.radiusd script in the scripts/ subdirectory to /etc/init.d and run update-rc.d. For other unixes/distributions it shouldn't be too hard how to modify these scripts for your own needs.

1.5 When attempting to compile the Radauth script provided with radius, I get errors such as "undefined reference to `uncompress'..."

This is due to MySQL requiring zlib. In the Makefile, there is a line that says LDFLAGS=-lmysqlclient, just change it to LDFLAGS="-lmysqlclient -lz" . Be sure that zlib is actually installed.

2.0 General

2.1 I've never run any kind of Radius server before, where should I start?

Because Xtradius is an extension to the Cistron codebase, please read the Cistrond FAQ at http://www.radius.cistron.nl/faq/ for information on setting up the XTRadius server. The aim of this documentation is to cover the xtradius extensions, not the setup. You could also read the RFCS, though they aren't exactly light reading at http://www.freeradius.org/rfc/rfc2138.txt and http://www.freeradius.org/rfc/rfc2139.txt.

2.2 How is XTRadius different from Cistron or the other Livingston based radius servers?

Because xtradius is based on the most Cistron radius package, it has all the features of Cistron, plus extensions for external authentication and accounting. Amongst the features implemented are:

Exec-Program-Account attribute: allowing an external script to be run when accounting either starts or stops
Exec-Program-Nas: script to be run for recording NAS specific data
Exec-Program-Log: script to be run for logging radius details (such as logins)
Exec-Program-Wait: although present in cistron, xtradius enhances this directive to support for exit codes (to determine login status), and send attributes back to the NAS (such as setting a Session-Timeout based on user details).

2.3 If I don't want to use external scripts for accounting authentication, why should I use XTRadius?

At the current stage there is no benefit or disadvantage to using XTRadius instead of Cistron if you don't plan to utilise the script extensions. In the future, as xtradius is developed this may change.

2.4 How do I have xtradius write accounting information to log files like other radius servers?

Create a directory called 'radacct' under your logs directory (ie /var/log/radacct), which can be written to by the radius daemon, and restart xtradius. If you wish your directory to reside somewhere else, be sure when starting radius to include "-a /path/to/directory" as an argument. Sub-directories will be made in this path for each NAS. If you include a trailing slash on the path name, no sub-directories will be created and all NAS data will be written in the radacct directory.

2.5 Every time I start xtradius I get errors like "Error: /etc/raddb/users[3]: Parse error\n(check) for entry...".

This error was introduced in 1.1-pre, which is due to carriage-returns (\r) being present in the configuration files. Simply run perl -pi'*.backup' -e 's/\r/\n/' * in the raddb directory to fix the problem... or grab the latest version of Xtradius via CVS. See http://www.xtradius.com/cvs.html.

2.6 CHAP authentication doesn't work. What am I doing wrong?

If you are doing external authentication (using a script), then you need to ensure that the script supports CHAP. If not, see the Scripts section of this FAQ, for information on how to add support for CHAP into your script. One other important thing to note is that some NAS' do not send a CHAP-Challenge attribute, which is necessary for chap authentication - instead this information is included in the header of the request packet. Versions of XTRadius 1.1pre1 and prior did not include the necessary code to extract this information from the packet, and put it into a CHAP-Challenge attribute for use with external scripts. This meant that while CHAP authentication would work fine when using the raddb/users file, it didn't work at all with external scripts. This issue has been fixed in the latest CVS.

3.0 Scripts

3.1 How do scripts work?

When a user connects to your NAS, it sends a request to the radius server (XTRadius), which contains details about the user logging in (eg. Username, password..). If XTRadius is configured to call an external script for authentication, it will run this script and give the script the auth info, either by the command line, or by setting an environment which the script can access. It is then up to the script to check various conditions (such as that the username and password match an entry in the database), and then exit with an exit-code of either 0 (grant access) or 255
(deny access). When the script exits, XTradius will pass on the status to the NAS so that it can allow or reject the user.

3.2 What language do I write scripts in?

You can write your scripts in any language you like, providing it can be executed and return an exit code. This means it can be shell script, a C program, Perl, Python.. you name it.

3.3 I've written some scripts, how do I make XTRadius use them?

Put something similar to the following at the start of your users file. Note that you may not need to use some of the directives such as Exec-Program-Nas and Exec-Program-Log. In fact, you don't even need to do anything with the "Start" packet since you can gather all the information you need from the "Stop" packet.

# These scripts will be called once the accounting first starts (after the login stage).
# See the execparams for a list of arguments being passed
DEFAULT Acct-Status-Type = "Start"
Exec-Program-Account = "/path/to/acct_start.pl %u %e %y %k %o %d %k"
Exec-Program-Nas = "/path/to/nas_start.pl %n"
Exec-Program-Log = "/path/to/radlog.pl %x %n"

# Once the user has finished their session (such as a dialup disconnecting), the radius server
# will be sent a 'stop' accounting packet containing details such as username, password,
# time session started, time session ended, and how many bytes were transferred. Call the
DEFAULT Acct-Status-Type = "Stop"
Exec-Program-Account = "/usr/local/xtradius/ixtrp/radacct.pl %u %e %y %k %o %d %k"
Exec-Program-Nas = "/usr/local/xtradius/ixtrp/nas_stop.pl %n"
Exec-Program-Log = "/usr/local/xtradius/ixtrp/radlog.pl %x %n"

# This script is used to authenticate the user. When the user first connects with login details,
# the NAS will send us a request containing the login details. Here we run auth.pl with the
# username (%u) and password (%w) on the command line. The script will exit with 0 on
# success, otherwise 255 for failure.
DEFAULT Auth-Type = External
Exec-Program-Wait = "/path/to/auth.pl %u %w",
Fall-Through = 0

3.4 Can you give me an example of granting access to a user from my script?

To grant access; In C: exit(0); In Perl and Shell: exit 0;
To deny access; In C: exit(255); In Perl and Shell: exit 255;

3.5 How do I send back attributes to the NAS such as Session-Timeout.

First make sure you have the latest CVS (as there was a bug in 1.1pre1 and prior).
Before exiting with grant access, simply have your script print out all the attributes and values on a separate lines to STDOUT. Here is an example.

In Perl:
print "Session-Timeout=200\n";
print "Idle-Timeout=30\n";
exit 0; # Grant Access

In C:
printf("Session-Timeout=%d\n", 300);
printf("Idle-Timeout=%d\n", 30);

3.6 I want to restrict multiple logins, but when I send the Simultaneous-Use=0 attribute from my script, it does not do anything.

Simultaneous-Use is not a reply attribute and therefore cannot be used from your script. When you use this attribute in your users file, radius does all the work in determining whether a user should be allowed to login by querying the NAS server (if possible), and denying access if the user is already logged in. While you cannot make use of this attribute from your script you could attempt to handle this behavior from the script itself, by either checking wtmp, querying the NAS (using the checkrad.pl script in the src/ directory), or even maintaining your own connection pool.

3.7 How do I pass attributes to my scripts via the command line?

Open the execparams file located in your raddb directory (usually /etc/raddb). Here you will see a list of attributes on the left side, and on the right side a corresponding letter. You'll notice that the letter 'u' correspons to the User-Name attribute, and the letter 'w' corresponds to the Password attribute. So if we want to pass the username and password to our authentication script, we would put something like the following in the users file:

DEFAULT Acct-Type = External
Exec-Program-Wait = "/path/to/authentication_program %u %w",
Fall-Through = 0

You need to put a percentage sign in front of the attribute codes, otherwise your script will just receive the codes themselves.

3.8 How do I pass attributes via the environment?

An environment containing available attributes is automatically setup for your script before it is run by xtradius. Look through execparams for a list of attributes which may be available by name. Accessing the environment depends on the language your script is written in, but here are a few examples:

use Env;
my $username = $ENV{'User-Name'};

#include <stdlib.h>
char *valuepair;
valuepair = getenv("User-Name");

You can check what attributes are available by executing the xtradius_test.pl script (found in the contrib/ directory) from the users file and then check /tmp/xtr.debug.

3.9 How do I handle CHAP authentication in my script?

Here's the basic procedure for implementing CHAP into your existing script. Note that to do CHAP you must have access to the plaintext password to compare it to the crypted password that you are supplied. (Add this logic to the script).

use MD5;
# Do all the existing logic of grabbing the arguments and/or
# stuff passed through ENV first.
my $given_password = ... # Crypted Password supplied by xtradius
my $want_password = ... # Get the password we want in plaintext 
if (exists $ENV{'CHAP-Challenge'}) {
	# Uhoh, it's chap let's do special stuff here,
	#(given password isn't in plaintext)
	my $chap_password = pack("H*", $given_password);
	my $chap_challenge = pack("H*", $ENV{'CHAP-Challenge'});

	# Compile an MD5 digest of the authentication information
	my $md5 = new MD5;
	$md5->add(substr($chap_password, 0, 1)); # Packet ID

	# Check that the digest matches the CHAP password
	if ($md5->digest() ne substr($chap_password, 1)) {
		# Aww, wrong password!
		exit 255;
} else {
	# Looks like it's PAP authentication (given password is in plain text)
	if ($given_password ne $want_password) {
		# Wrong, wrong wrong, goodbye!
		exit 255;

# If we got this far, then the user passed the authentication stage.
# Put in any extra logic here (such as passing back attributes).
exit 0;