[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1 Filters

The simplest way to extend the functionality of Radius is to use filters. A filter is an external program that communicates with Radius via its standard input and output channels.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.1 Getting Acquainted with Filters

Suppose we wish to implement an authentication method based on the user name and the user's calling station ID. We have a database of user names with valid IDs, and the new method should authenticate a user only if the combination {user_name, id} is found in this database.

We write a filter program that reads its standard input line by line. Each input line must consist of exactly two words: the user name and the calling station ID. For each input line, the program prints 0 if the {user_name, id} is found in the database and 1 otherwise. Let's suppose for the sake of example that the database is a plaintext file and the filter is written in a shell programming language. Then it will look like

 
#! /bin/sh

DB=/var/db/userlist

while read NAME CLID
do
    if grep "$1:$2" $DB; then
        echo "0"
    else
        echo "1"
    fi
done

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.2 Declaring the Filter

Here is how this filter is declared in the ‘raddb/config’ file:

 
filters {
    filter check_clid {
        exec-path "/usr/libexec/myfilter";
        error-log "myfilter.log";
        auth {
            input-format "%C{User-Name}
            %C{Calling-Station-Id}";
            wait-reply yes;
        };
    };        
};                        

Let's analyze this declaration line by line:

  1. filters {

    This keyword opens the filters declaration block. The block may contain several declarations.

  2. filter check_clid {

    This line starts the declaration of this particular filter and names it ‘check_clid’.

  3. exec-path "/usr/libexec/myfilter";

    This line tells radiusd where to find the executable image of this filter.

  4. error-log "myfilter.log";

    The diagnostic output from this filter must be redirected to the file ‘myfilter.log’ in the current logging directory

  5. auth {

    This filter will process authentication requests.

  6. input-format "%C{User-Name} %C{Calling-Station-Id}";

    Define the input line format for this filter. The %C{} expressions will be replaced by the values of the corresponding attributes from the incoming request (see section Macro Substitution).

  7. wait-reply yes;

    radiusd will wait for the reply from this filter to decide whether to authenticate the user.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.3 Invoking the Filter from a User Profile

To invoke this filter from the user profile, specify its name prefixed with ‘|’ in the value of Exec-Program-Wait attribute, like this:

 
DEFAULT Auth-Type = System,
                Simultaneous-Use = 1
        Exec-Program-Wait = "|check_clid"

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.4 Adding Reply Attributes

Apart from simply deciding whether to authenticate a user, the filter can also modify the reply pairs.

 
#! /bin/sh

DB=/var/db/userlist

while read NAME CLID
do
    if grep "$1:$2" $DB; then
        echo "0 Service-Type = Login, Session-Timeout = 1200"
    else
        echo "1 Reply-Message = 
              \"You are not authorized to log in\""
    fi
done

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.5 Accounting Filters

Let's suppose we further modify our filter to also handle accounting requests. To discern between the authentication and accounting requests we'll prefix each authentication request with the word ‘auth’ and each accounting request with the word ‘acct’. Furthermore, the input line for accounting requests will contain a timestamp.

Now, our filter program will look as follows:

 
#! /bin/sh

AUTH_DB=/var/db/userlist
ACCT_DB=/var/db/acct.db

while read CODE NAME CLID DATE
do
    case CODE
    auth)
        if grep "$1:$2" $DB; then
            echo "0 Service-Type = Login, \
                  Session-Timeout = 1200"
        else
            echo "1 Reply-Message = \
                  \"You are not authorized to log in\""
        fi
    acct)
        echo "$CODE $NAME $CLID $DATE" >> $ACCT_DB
done

Its declaration in the ‘raddb/config’ will also change:

 
filter check_clid {
    exec-path "/usr/libexec/myfilter";
    error-log "myfilter.log";
    auth {
        input-format "auth %C{User-Name} 
                      %C{Calling-Station-Id}";
        wait-reply yes;
    };
    acct {
        input-format "acct %C{User-Name} 
                      %C{Calling-Station-Id} %D";
        wait-reply no;
    };
};        

(The input-format lines are split for readability. Each of them is actually one line).

Notice wait-reply no in the acct statement. It tells radiusd that it shouldn't wait for the response on accounting requests from the filter.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

10.1.6 Invoking the Accounting Filter

To invoke the accounting filter, specify its name prefixed with a vertical bar character as a value of Acct-Ext-Program in our ‘raddb/hints’ file. For example:

 
DEFAULT NULL
        Acct-Ext-Program = "|check_clid:

[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Sergey Poznyakoff on December, 6 2008 using texi2html 1.78.