[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An Authentication Type specifies which credentials the user
is required to supply in order to be authenticated and where the
user's authentication data are stored. It is defined by the value
of Auth-Type
attribute in LHS of a `users' entry.
7.1 Accept Authentication Type Accept unconditionally. 7.2 Reject Authentication Type Reject unconditionally. 7.3 Local Password Authentication Type Authenticate using plaintext password. 7.4 Encrypted Password Authentication Type Authenticate using MD5 encrypted password. 7.5 System Authentication Type Authenticate using system account. 7.6 SQL Authentication Type Authenticate using SQL. 7.7 PAM Authentication Type Authenticate using PAM. 7.8 Defining Custom Authentication Types 7.9 Multiple Login Checking Checking for Simultaneous Logins. 7.10 Controlling Authentication Probes
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Accept is the simplest authentication type. Users with this authentication type will be authenticated successfully without checking any credentials. Actually this means that only username is required for authentication.
This authentication type is used for each `users' entry, whose LHS contains
Auth-Type = Accept |
This authentication type can be used for guest accounts, e.g. the following profile in `users':
guest Auth-Type = Accept, Simultaneous-Use = 10 Service-Type = Framed-User, Framed-Protocol = PPP |
allows up to 10 simultaneous guest PPP accounts. To log in using such guest account it is sufficient to use username `guest' and any password.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Reject authentication type causes the request to be rejected unconditionally. It can be used to disable a user account (For another method of disabling user accounts, see section 5.10 List of Blocked Users -- `raddb/access.deny').
This authentication type is used for each `users' entry, whose LHS contains
Auth-Type = Reject |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Local Password authentication type allows to keep plaintext user passwords. Although the use of this authentication type is strongly discouraged for security reasons, this is the only authentication type that can be used with CHAP authentication.
There are two ways of using this authentication type
user-name Auth-Type = Local, User-Password = plaintext |
The plaintext is the user's plaintext password. Obviously,
user-name may not be DEFAULT
nor BEGIN
.
user-name Auth-Type = Local, Password-Location = SQL |
When the user is authenticated using such profile, its password
is retrieved from the authentication database using auth_query
.
The configuration of SQL authentication is described in
detail in 5.11.2 Authentication Server Parameters.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Encrypted Password type allows to keep user's passwords encrypted via DES or MD5 algorithm. There are two ways of using this authentication type.
user-name Auth-Type = Crypt-Local, User-Password = crypt-pass |
The Crypt-Password
is a shortcut for the above notation:
user-name Crypt-Password = crypt-pass |
user-name Auth-Type = Crypt-Local, Password-Location = SQL |
Using this profile, the user's password is retrieved from the
authentication database using auth_query
.
The configuration of SQL authentication is described in
detail on 5.11.2 Authentication Server Parameters.
The shortcut for this notation is Auth-Type = SQL
.
In any case, the passwords used with this authentication type must be either DES or MD5 hashed.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The System authentication type requires that the user have a valid system account on the machine where the radius server is running. The use of this type is triggered by setting
Auth-Type = System |
in the LHS of a `users' entry.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Setting Auth-Type = SQL
or Auth-Type = Mysql
in the LHS of a `users' entry is a synonym for
Auth-Type = Crypt-Local, Password-Location = SQL |
and is provided as a shortcut and for backward compatibility with previous versions of GNU Radius.
For description of SQL authentication, see 7.4 Encrypted Password Authentication Type. The configuration of SQL subsystem is described in 5.11 SQL Configuration -- `raddb/sqlserver'.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
PAM authentication type indicates that a user should be authenticated using PAM (Pluggable Authentication Module) framework. The simplest way of usage is:
Auth-Type = PAM |
Any user whose `users' profile contains the above, will be
authenticated via PAM, using service name `radius'.
If you wish to use another service name, set it using Auth-Data
attribute, e.g.:
Auth-Type = PAM, Auth-Data = pam-service |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The are three ways to define custom authentication types:
You can write a PAM module implementing the new authentication
type. Then, specifying Auth-Type = PAM
allows to apply
it (see section 7.7 PAM Authentication Type).
Alternatively, you may write a Scheme procedure implementing the new
authentication type. To apply it, use Scheme-Procedure
attribute
in RHS. The Auth-Type = Accept
can be used in LHS if
the whole authentication burden is to be passed to the Scheme procedure.
For example, if one wrote a procedure my-auth
, to apply it to
all users, one will place the following profile in his `users'
file:
DEFAULT Auth-Type = Accept Scheme-Procedure = "my-auth" |
For a discussion of how to write Scheme authentication procedures, See section 11.3.2 Authentication with Scheme.
The third way to implement your own authentication method is using an external program. This is less effective than the methods described above, but may be necessary sometimes. To invoke the program, use the following statement in the RHS of `users' entry:
Exec-Program-Wait = "progname args" |
The progname must be the full path to the program, args --- any arguments it needs. The usual substitutions may be used in args to pass any request attributes to the program (see section 5.14 Macro Substitution).
For a detailed description of Exec-Program-Wait
attribute and
an example of its use, see 14.3.7 Exec-Program-Wait
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The number of sessions a user can have open simultaneously can be
restricted by setting Simultaneous-Use
attribute in the user's
profile LHS (see section 14.3.25 Simultaneous-Use
). By default the number
of simultaneous sessions is unlimited.
When a user with limited number of simultaneous logins authenticates
himself, Radius counts the number of the sessions that are already
opened by this user. If this number is equal to the value of
Simultaneous-Use
attribute the authentication request is
rejected.
This process is run in several stages. First, Radius retrieves the
information about currently opened sessions from one of its accounting
databases. Then, it verifies whether all these sessions are still
active. This pass is necessary since an open entry might be a result
of missing Stop
request. Finally, the server counts the
sessions and compares their count with the value of
Simultaneous-Use
attribute.
The following subsections address each stage in detail.
7.9.1 Retrieving Session Data 7.9.2 Verifying Active Sessions
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Radius retrieves the list of sessions currently opened by the user either from the system database (see section 8.1 System Accounting), or from the SQL database (see section 8.3 SQL Accounting). The system administrator determines which method to use.
By default, system accounting database is used. Its advantages are simplicity and ease of handling. It has, however, a serious deficiency: the information is kept in the local files. If you run several radius servers, each of them has no easy way of knowing about the sessions initiated by other servers.
This problem is easy to solve if you run SQL accounting (see section 8.3 SQL Accounting). In this case, each radius server stores the data in your SQL database and can easily retrieve them from there.
To enable use of SQL database for multiple login checking, do the following:
In your `raddb/config' file set:
mlc { method sql; }; |
In your `raddb/sqlserver' file, specify the queries for retrieving the information about open sessions and, optionally, a query to close an existing open record.
There are two queries for retrieving the information:
mlc_user_query
returns the list of sessions opened by the user,
mlc_realm_query
returns the list of sessions opened for the
given realm. Each of them should return a list of 5-element
tuples(4):
user-name, nas-ip-address, nas-port-id, acct-session-id |
Here is an example of mlc_user_query
and mlc_realm_query
:
mlc_user_query SELECT user_name,nas_ip_address,\ nas_port_id,acct_session_id \ FROM calls \ WHERE user_name='%C{User-Name}' \ AND status = 1 mlc_realm_query SELECT user_name,nas_ip_address,\ nas_port_id,acct_session_id \ FROM calls \ WHERE realm_name='%C{Realm-Name}' |
Apart from these two queries you may also wish to provide a query for
closing a hung record. By default, radiusd
will use
acct_stop_query
. If you wish to override it, supply a query
named mlc_stop_query
, for example:
mlc_stop_query UPDATE calls \ SET status=4,\ acct_session_time=unix_timestamp(now())-\ unix_timestamp(event_date_time) \ WHERE user_name='%C{User-Name}' \ AND status = 1 \ AND acct_session_id='%C{Acct-Session-Id}' |
See section 5.11.4.1 Writing SQL Accounting Query Templates, for detailed information on how to write these queries.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Whatever database radiusd
uses, an open entry in it does not
necessary mean that the corresponding session is still being
active. So, after retrieving the information about user sessions,
Radius verifies on corresponding NASes whether these are actually
active.
For each entry in the session list, if its NAS acknowledges the session, the session count is incremented. Otherwise, such entry is marked as closed in the database and is not counted.
There may also be cases when the NAS is unreachable due to some
reasons. In such cases the Radius behavior is determined by the value
of checkrad-assume-logged
in `config' file
auth statement (raddb/config). If the value is yes
,
Radius assumes the session is still active and increases the session
count, otherwise it proceeds as if the NAS returned negative reply.
To query a NAS, Radius first looks up its type and additional parameters
in `naslist' file (see section 5.4 NAS List -- `raddb/naslist'). There are two
predefined NAS types that cause Radius to act immediately without
querying tne NAS: the special type `true' forces Radius to act
as if the NAS returned 1, the type `false' forces it to act
as if the NAS returned 0. If the type is neither of this predefined types,
Radius uses it as a look up key into the `nastypes' file
(see section 5.5 NAS Types -- `raddb/nastypes') and tries to retrieve an entry which has
matching type. If such entry does not exist, Radius issues the error
message and acts accordingly to the value of configuration variable
checkrad-assume-logged
. Otherwise, Radius determines the query
method to use from the second field of this entry, and constructs method
arguments by appending arguments from the `naslist' entry to
those of nastypes
entry. Note, that the former take precedence over the
latter, and can thus be used to override default values specified
in `nastypes'.
Having determined the query method and its argument, Radius queries
NAS and analyzes its output by invoking a user-supplied
Rewrite function. The function to use
is specified by the function=
argument to the method. It is
called each time a line of output is received from the NAS (for
finger queries) or a variable is received (for SNMP queries). The
process continues until the function returns 1 or the last line
of output is read or a timeout occurs whichever comes first.
If the user-function returns 1 it is taken to mean the user's session is now active at the NAS, otherwise, if it replies 0 or if the end of output is reached, it is taken to mean the user's session is not active.
The syntax conventions for user-supplied functions are described in detail in 11.2.5 Login Verification Functions.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Authentication probe is an attempt of a user to use other user's account, by guessing his password. The obvious indication of an authentication probe is appearence of several consecutive authentication failures for the same user. Of course, if the intruder is given sufficient number of such probes he will sooner or later succeed in finding the actual password. The conventional method to prevent this from occurring is to keep failure counters for each user and to lock the account when its failure countrer reaches a predefined limit. Notice that a legitimate user may fail (sometimes even several times in sequence) in entering his password so, two important points should always be observed. First, failure counters record the number of consecutive authentication failures and they are reset after each successive authentication. Secondly, the maximum number of allowed consecutive failures should be set sufficiantly high.
The version 1.3 offers two ways for controlling authentication probes: using external programs and using special SQL queries.
To control authentication probes using external programs, use the
combination of Exec-Program-Wait
and
Auth-Failure-Trigger
. The program specified by
Auth-Failure-Trigger
is executed each time an authentication
attempt failed. When both attributes are used together, the program
invoked by Auth-Failure-Trigger
can update the failure
counter, and the one invoked by Exec-Program-Wait
can compare
the counter value with the predefined limit and reject authentication
when both values become equal. Such approach is most useful in
conjunction with BEGIN
profile.
Let's suppose the program `/sbin/check_failure' accepts a user name and returns 1 if the failure counter for this user has reached maximum allowed value. Otherwise it returns 0 and clears the counter. Another program, `/sbin/count_failure' increases failure counter value for the given user name. Assuming our basic authentication type is `PAM', the `raddb/users' file will look as follows:
BEGIN NULL Exec-Program-Wait = "/sbin/check_failure %C{User-Name}", Auth-Failure-Trigger = "/sbin/count_failure %C{User-Name}", Fall-Through = Yes DEFAULT Auth-Type = PAM Service-Type = Framed-User, Framed-Protocol = PPP [... Other profiles ...] |
The BEGIN
profile will be executed before any other profile.
It will add to the RHS Exec-Program-Wait
and
Auth-Failure-Trigger
attributes and then radiusd
will
proceed to finding a matching profile (due to Fall-Through
attribute). When such profile is found, the user will be authenticated
according to the method set up by the profile's Auth-Type
attribute. If authentication fails, `/sbin/count_failure'
will be called and the user name passed to it as the argument. Otherwise,
`/sbin/check_failure' will be invoked.
To complete the example, here are working versions of both programs.
Failure counters for each user name are kept in separate file in
`/var/log/radius/fails' directory. Both programs are written
in bash
.
#! /bin/bash test $# -eq 1 || exit 1 MAXFAIL=8 REGDIR=/var/log/radius/fails if [ -r "$REGDIR/$1" ]; then read COUNT < "$REGDIR/$1" COUNT=$((COUNT+1)) else COUNT=1 fi echo $COUNT > "$REGDIR/$1" # End of /sbin/count_failure |
#! /bin/bash test $# -eq 1 || exit 1 MAXFAIL=8 REGDIR=/var/log/radius/fails if [ -r "$REGDIR/$1" ]; then read COUNT < "$REGDIR/$1" if [ $COUNT -ge $MAXFAIL ]; then echo "Reply-Message=\"Too many login failures. Your account is locked\"" exit 1 else rm "$REGDIR/$1" fi fi exit 0 # End of check_failure |
Another way of controlling authentication probes is by using
SQL database to store failure counters. Two queries are
provided for this purpose in `raddb/sqlserver' file:
auth_success_query
is executed upon each successful
authentication, and auth_failure_query
is executed upon
each authentication failure. Both queries are not expected to return
any values. One obvious purpose of auth_failure_query
would be to
update failure counters and that of auth_success_query
would be
to clear them. The auth_query
or group_query
should then
be modified to take into account the number of authentication
failures.
The default SQL configuration GNU Radius is shipped with provides a working example of using these queries. Let's consider this example.
First, we create a special table for keeping authentication failure counters for each user:
CREATE TABLE authfail ( # User name this entry refers to user_name varchar(32) binary default '' not null, # Number of successive authentication failures for this user count int, # Timestamp when this entry was last updated time datetime DEFAULT '1970-01-01 00:00:00' NOT NULL, # Create a unique index on user_name UNIQUE uname (user_name) ); |
The query auth_fail_query
will increment the value of
count
column for the user in question:
auth_failure_query UPDATE authfail \ SET count=count+1,time=now() \ WHERE user_name='%C{User-Name}' |
The query auth_success_query
will clear count
:
auth_success_query UPDATE authfail \ SET count=0,time=now() \ WHERE user_name='%C{User-Name}' |
Now, the question is: how to use this counter in authentication? The answer is quite simple. First, let's create a special group for all the users whose authentication failure counter has reached its maximum value. Let this group be called `*LOCKED_ACCOUNT*'. We'll add the following entry to `raddb/users':
DEFAULT Group = "*LOCKED_ACCOUNT*", Auth-Type = Reject Reply-Message = "Your account is currently locked.\n\ Please, contact your system administrator\n" |
which will reject all such users with an appropriate reply message.
The only thing left now is to rewrite group_query
so that it
returns `*LOCKED_ACCOUNT*' when authfail.count
reaches its
maximum value. Let's say this maximum value is 8. Then the following
query will do the job:
group_query SELECT user_group FROM groups \ WHERE user_name='%u' \ UNION \ SELECT CASE WHEN (SELECT count > 8 FROM authfail \ WHERE user_name='%u') THEN '*LOCKED_ACCOUNT*' END |
The default configuration comes with these queries commented out. It is up to you to uncomment them if you wish to use SQL-based control over authentication failures.
Notice the following important points when using this approach:
UNION
. Earlier
versions of MySQL
lacked this support, so if you run
MySQL
make sure you run a reasonably new version (at least
4.0.18).
auth_failure_query
and auth_success_query
assume the database already contains an entry for each user. So,
when adding a new user to the database, make sure to insert
an appropriate record into authfails
table, e.g.
INSERT INTO authfail VALUES('new-user',0,now()); |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |