[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Beside the Radius server and accompanying utilities, GNU Radius provides a set of utilities to be used as Radius clients.
The following sections describe in detail the parts of the Radius client package.
13.1 Client Configuration Configuration file is common for all client utilities. 13.2 radtest Radius client shell. 13.3 radsession Send arbitrary requests to Radius server. 13.4 nas.scm
A NAS implementation for GNU/Linux machines. 13.5 pam_radius.so
A PAM module for authentication via Radius.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
All programs from the client package share the same configuration file: `raddb/client.conf'. The file uses simple line-oriented syntax. Empty lines are ignored; the command `#' introduces an end-of-line comment.
The source IP is introduced with the source_ip
statement. Its
syntax is:
source_ip ip-addr |
where ip-addr must be the IP in dotted-quad notation.
The Radius server to send the requests to is introduced with
server
statement:
server name ip-addr secret auth-port acct-port |
Its parts are:
If several server
statement are present, they are tried in
turn until one of them replies to the request.
The amount of time a client program waits for the reply from a
server is configured using the timeout
statement:
timeout number |
If the program does not receive any response within number seconds,
it assumes the server does not respond and either retries the
transmission or tries the next available server. The number of retries is
set with the retry
statement:
retry number |
The example `raddb/client.conf' follows:
server first 10.11.10.1 secret 1645 1646 server second 10.11.10.1 secret 1645 1646 source_ip 127.0.0.1 timeout 3 retry 5 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Radtest
is a radius client shell, providing a simple and
convenient language for sending requests to RADIUS servers and
analyzing their reply packets.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(This message will disappear, once this node revised.)
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There are four basic data types in radtest
language: integer
,
ipaddr
, string
and avlist
.
13.2.2.1 Numeric Values Integers and IP addresses. 13.2.2.2 Character Strings 13.2.2.3 Lists of A/V pairs
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Integer means a signed integer value in the range -2147483648..2147483647.
Ipaddr is an unsigned integer value suitable for representing IPv4 addresses. These can be input either as decimal numbers or as IP addresss in usual "dotted-quad" notation.
As a convenience measure, RADIUS request code names can be used in integer context. The following table lists currently defined request names with their integer codes:
Access-Request | 1 |
Access-Accept | 2 |
Access-Reject | 3 |
Accounting-Request | 4 |
Accounting-Response | 5 |
Accounting-Status | 6 |
Password-Request | 7 |
Password-Ack | 8 |
Password-Reject | 9 |
Accounting-Message | 10 |
Access-Challenge | 11 |
Status-Server | 12 |
Status-Client | 13 |
Ascend-Terminate-Session | 31 |
Ascend-Event-Request | 33 |
Ascend-Event-Response | 34 |
Ascend-Allocate-IP | 51 |
Ascend-Release-IP | 52 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
String is an arbitrary string of characters. Any input token consisting of letters of Latin alphabet, decimal digits, underscores dashes and dots and starting with a Latin alphabet letter or underscores is considered a string. To input strings containing other letters, surround them by double quotes. The following are valid strings:
A-string "String, containing white space" |
The double quote character `"' must be preceeded by a backslash `\' if it is part of a string:
"Always quote \" character" |
Generally speaking, `\' is an escape character, that alters the meaning of the immediately following character. If it is located at the end of the line, it allows to input newline character to strings:
"This string contains a \ newline character." |
Other special escape sequences are:
If the character following the backslash is not one of those specified, the backslash is ignored.
An important variant of string
is a numeric string,
or STRNUM for short. A numeric string is a string that
can be converted to a number, for example "+2"
. This concept
is used for type conversion between integer
and string
values.
Another way to represent strings is using here document syntax. Its format is as follows:
<<[-]delimiter text delimiter |
Delimiter is any word you choose to delimit the text, text represent the text of the string. If delimiter is prepended by a dash, any leading tabulation characters will be removed from text. This allows for natural indentation of `here document' constructs.
The `here document' construct is especially useful to represent strings containing embedded newlines, as shown in the example below:
print <<EOT usage: foo [OPTIONS] [NAME...] OPTIONS are: -h Print this help list. EOT |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Avlist are whitespace or comma-separated lists of RADIUS attribute-value pairs. A syntax for A/V pair is
name op value |
where name is attribute name, op is a comparison
operator (`=', `!=', `<', `<=', `>',
`>='), and value is any valid radtest
data
or expression.
An A/V pair list must be enclosed in parentheses. This is an
example of an A/V pair list consisting of two pairs:
( User-Name = "test" NAS-IP-Address = 10.10.10.1 ) |
An empty pair list is represented by a pair of parentheses: ()
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The following keywords are reserved in radtest
:
acct, and, auth, begin, break, case, continue, do, else, end, exit, expect, getopt, if, in, input, not, or, print, return, send, set, shift, while |
The reserved keywords may be used as variable names, provided that the following requrements are met:
'case' = 1 |
${case} + 2 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Variables are means of storing data values at one point of your
program for using them in another parts of it. Variables can be
assigned either in the program itself, or from the radtest
command line.
13.2.4.1 Using Variables 13.2.4.2 Variable Assignments 13.2.4.3 Dereferencing Variables 13.2.4.4 Accessing Elements of A/V Pair Lists 13.2.4.5 Assignment Options 13.2.4.6 Built-in Variables
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The name of a variable must be a sequence of letters, digits,
underscores and dashes, but it may not begin with a digit or dash. Notice,
that in contrast to the majority of programming languages, use of
dashes (minus signs) is allowed in user names. This is because
traditionally RADIUS attribute names contain dashes, so
extending this practice to variable names makes radtest
programs more consistent. On the other hand, this means that you
should be careful when using minus sign as a subtraction
operator (see minus-ambiguity). Case is significant in variable names:
a
and A
are different variables.
A name of a variable may coincide with one of radtest
reserved
keywords. See section 13.2.3 Reserved Keywords, for description on how to use such
variables.
A few variables have special built-in meanings (see section 13.2.4.6 Built-in Variables). Such variables can be assigned and accessed just as any other ones. All built-in variables names are entirely upper-case.
Variables are never declared, they spring into existence when an assignment is made to them. The type of a variable is determined by the type of the value assigned to it.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An assignment stores a new value into a variable. It's syntax is quite straightforward:
variable = expression |
As a result of the assignment, the expression is evaluated and its value is assigned to variable. If variable did not exist before the assignment, it is created. Otherwise, whatever old value it had before the assignment is forgotten.
It is important to notice that variables do not have permanent types. The type of a variable is the type of whatever value it currently holds. For example:
foo = 1 print $foo => 1 foo = "bar" print $foo => bar foo = ( User-Name = "antonius" NAS-IP-Address = 127.0.0.1 ) print $foo => ( User-Name = "antonius" NAS-IP-Address = 127.0.0.1 ) |
Another important point is that in radtest
, assignment is
not an expression, as it is in many other programming languages. So
C
programmers should resist temptation to use assignments in
expressions. The following is not correct:
x = y = 1 |
Finally, if the variable name coincides with one of radtest
keywords, it must be enclosed in single quotes:
'case' = 1 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Dereferencing a variable means accessing its value. The simplest form of dereferencing is by prepending a dollar sign to the variable name:
foo = 1 print foo => foo print $foo => 1 |
Notice, that in the example above, the first print
statement
understands foo
as a literal string, whereas the second one
prints the value of the variable.
Dereferencing an undefined variable produces error message:
print $x error--> variable `x' used before definition |
Optionally, the variable name may be surrounded by curly braces.
Both $foo
and ${foo}
are equivalent. The use of
the latter form is obligatory only when the variable name coincides
with one of the reserved keywords (see section 13.2.3 Reserved Keywords).
It also can be used to resolve ambiguity between using dash as
a part of user name and as a subtraction operator:
long-name = 2 $long-name => 2 $long-name-1 error--> variable `long-name-1' used before definition ${long-name}-1 => 1 $long-name - 1 => 1 |
We recommend to always surround `-' with whitespace when it is used as arithmetic operator.
The ${}
notation also permits some operations similar to
shell variable substitution.
$x error--> variable `x' used before definition ${x:-1} => 1 x = 2 ${x:-1} => 2 |
$x error--> variable `x' used before definition ${x:=1} => 1 $x => 1 |
$x error--> variable `x' used before definition ${x:?} error--> x: variable unset ${x:?foobar} error--> foobar |
radtest
prints text (or a default message, if it
is empty), reads the standard input up to the newline character
and returns the value read. Otherwise, the value of the variable
is returned. This notation provides a convenient way for asking
user to supply default values.
${x::} -| (<teletype>:1)x? ${x::Enter value of x: } -| Enter value of x: |
${variable::text}
, with the exception that the input
value will not be echoed on the screen. This notation provides a
convenient way for asking user to supply default values for variables
(such as passwords, shared secrets, etc.) while preventing them from
being compromised.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Elements of an avlist
are accessed as if it were an array,
i.e.:
$variable [ attribute-name ] |
If the attribute attribute-name is of string
data type
and variable may contain more than one pair with this attribute,
adding an asterisk after attribute-name returns concatenated
values of all such pairs:
$variable [ attribute-name * ] |
Examples:
x = (NAS-Port-Id = 127.0.0.1 \ Reply-Message = "a long" Reply-Message = " string" $x[NAS-Port-Id] => 127.0.0.1 $x[Reply-Message] => "a long" $x[Reply-Message*] => "a long string" |
<FIXME> How to get nth instance of an attribute? What gets returned if there is no such attribute in the list? </>
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
You can set any radtest
variable from the command line.
There are two ways of doing so.
First, you can use variable assignment option `--assign' (or `-a'). Its syntax is:
--assign variable=text -a variable=text |
For example:
radtest -a foobar=5 |
Another way is useful when you load a radtest
program by
`--file' or `-f'. This second way consists in including
a variable assignment in the form
variable=text |
in the command line after the script name. For example:
radtest -f myprog.rad foo=5 addr=127.0.0.1 |
This method is especially useful for executable scripts that are
run using #!
shell magic. Consider a simple script:
#! /usr/local/bin/radtest -f print $addr |
The value of addr can be given to the script from the command line as in the example below:
myprog.rad addr=127.0.0.1 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The following variables are predefined:
Contains the result of last evaluated expression.
integer
).
avlist
).
ipaddr
).
By default, it equals the IP address set via source_ip
statement
in your `client.conf' file (see section 13.1 Client Configuration).
input
statement
(see section input).
getopt
(see section getopt).
getopt
.
getopt
. If the last call to getopt
returned false,
OPTIND
contains index of the first non-optional argument
in the command line.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Normally radtest
stops parsing its command line
when it encounters either first non-optional argument
(i.e. the one not starting with dash), or an argument consisting
of two dashes. The rest of the command line starting from the
first non-optional argument forms positional parameters.
These parameters are said to form the top-level environment.
Similarly, when invoking a user-defined function (see section 13.2.7 Function Definitions), arguments passed to it are said to form the current environment of the function. These arguments are positional parameters for this function.
Positional parameters are assigned numbers starting from 1. To access
(dereference) a positional parameter, the syntax $n
is used, where n is the number of the parameter. Alternative
forms, such as ${n}
or ${n:-text}
,
can also be used. These work exactly as described in
13.2.4.3 Dereferencing Variables).
The number of positional parameters can be accessed using a special
notation $#
.
Several things need to be mentioned:
string
data
type, whereas the types of positional parameters in a function
current environment are determined before inoking the function.
$0
returns the name of the function
being evaluated. When used in the top-level environment, it returns
the name of radtest
program as given by `--file'
(`-f') option.
AWK
programmers should note that assignments
(see section 13.2.4.5 Assignment Options) are not included in the top level
environment (see example below).
For example, suppose you run:
radtest -f script.rad name foo=bar 5 |
Then, the top-level environment of program `script.rad' consists of the following variables:
$0 => script.rad $1 => name $2 => 5 |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
An expression evaluates to a value, which can be printed,
assigned to a variable, used in a conditional statement or passed
to a function. As in other languages, expressions in radtest
include literals, variable and positional parameter dereferences,
function calls and combinations of these with various operators.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Radtest
provides the common arithmetic operators, which
follow normal precedence rules (see section 13.2.6.8 Operator Precedence (How Operators Nest)), and work as
you would expect them to. The only notable exception is subtraction
operator (minus) which can be used as part of a variable or attribute
name, and therefore expressions like $x-3
are ambiguous. This
expression can be thought of either as a dereference of the variable
x-3
(see section 13.2.4.3 Dereferencing Variables), or as subtraction of the value
3
from the value of the variable x
. Radtest
always resolves this ambiguityin the favor of variable dereference.
Therefore we advise you to always surround minus sign by whitespace,
if it is used as a subtraction operator. So, instead of $x-3
,
write $x - 3
. For other methods of solving this ambiguity,
See minus-ambiguity.
This table lists the arithmetic operators in order from highest precedence to lowest:
- x
+ x
x
.
<FIXME> Should this
imply converting x to integer? </>
x * y
x / y
x % y
x + y
x - y
Unary plus and minus have the same precedence, the multiplication, division and remainder all have the same precedence, and addition and subtraction have the same precedence.
If x and y are of different data types, their values are first coerced to a common data type, selected using a set of rules (see section 13.2.6.6 Conversion Between Data Types).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
There is only one string operation: concatenation. It is represented by plus sign, e.g.:
"string" + "ent" => "stringent" |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(This message will disappear, once this node revised.)
The following operations are defined on A/V lists:
x + y
( User-Name = "foo" ) + ( Password = "bar" ) => ( User-Name = "foo" Password = "bar" ) ( User-Name = "foo" Service-Type = Login-User ) + \ ( Service-Type = Framed-User Password = "bar" ) => ( User-Name = "foo" \ Service-Type = Framed-User \ Password = "bar" ) |
x - y
( User-Name = "foo" Service-Type = Login-User ) - \ ( Service-Type = Framed-User ) => ( User-Name = "foo" ) |
Notice, that only attribute name matters, its value is ignored. <FIXME> Is this correct? Is there a better way to put it? should we provide an operation that whould compare both attribute number and its value? </>
x % y
( User-Name = "foo" Service-Type = Login-User ) - \ ( Service-Type = Framed-User ) => ( Service-Type = Login-User ) |
<FIXME> Same as above. </>
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Comparison expressions compare operands for relationships
such as equality. They return boolean values, i.e. true
or false
. The comparison operations are nonassociative,
i.e. they cannot be used together as in:
# Wrong! 1 < $x < 2 |
Use boolean operations (see section 13.2.6.5 Boolean Operations) to group comparisons together.
Comparison operations can only be used in conditional expressions.
This table lists all comparison operators in order from highest precedence to lowest (notice, however, the comment after it):
x = y
C
and AWK
programmers, please note single equal sign!
x != y
x < y
x <= y
x > y
x >= y
Operators =
and !=
have equal precedence. Operators
<
, <=
, >
, >=
have equal precedence.
Most operators are defined for all radtest
data types.
However, only =
and !=
are defined for avlist
s.
Using any other comparison operator with avlist
s produces
error.
If x and y are of different data types, their values are first coerced to a common data type, selected using a set of rules (see section 13.2.6.6 Conversion Between Data Types).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A boolean operation is a combination of comparison expressions. Boolean operations can only be used in conditional expressions.
This table lists all comparison operators in order from highest precedence to lowest.
not x
! x
x and y
x or y
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(This message will disappear, once this node revised.)
The unary negation operand is always converted to integer
type:
-(1 + 1) => -2 -(127.0.0.1 + 2) => -2130706435 - ("1" + "1") => -11 - "text" error--> cannot convert string to integer |
The unary not
operand is converted using the following rules:
integer
, no conversion is performed.
STRNUM
(see STRNUM) or
ipaddr
, it is converted to integer.
string
(but is not STRNUM
), the
result of not
is true
only if the operand is an empty
string.
avl
, the result of not
is
true
if the list is empty.
Examples:
not 0 => 1 not 10 => 0 not "23" => 0 not "0" => 1 not "text" => 0 not "" => 1 not 127.0.0.1 => 0 not 0.0.0.0 => 1 |
When operands of two different data types are used in a binary operation, one of the operands is converted (cast) to another operand's type according to the following rules:
radtest
attemtps
to convert another operand to the literal data type. If this attempt
fails, it goes on to rule 2.
STRNUM
(see STRNUM) and another is of numeric
data type (i.e. either integer
or ipaddr
), the latter is converted
to string representation.
ipaddr
and another is
integer
, the latter is converted to ipaddr
.
Radtest
prints appropriate diagnostics and aborts execution of the current
statement.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A function is a name for a particular sequence of statements. It is defined using special definition syntax (see section 13.2.7 Function Definitions). Normally a function return some value. The way to use this value in an expression is with a function call expression, which consists of the function name followed by a comma-separated list of arguments in parentheses. The arguments are expressions which provide values for the function call environment (see section 13.2.5 Positional Parameters. When there is more than one argument, they are separated by commas. <FIXME> Actually, commas in the argument list are optional. At least, now... </> If there are no arguments, write just `()' after the function name. Here are some examples:
foo() no arguments bar(1) one argument bar(1, "string") two arguments |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Operator precedence determines the order of executing operators,
when different operators appear close by in one expression.
For example, *
has higher precedence than +
; thus,
a + b * c
means to multiply b
and c
, and then add
a
to the product.
You can overrule the precedence of the operators by using
parentheses. You can think of the precedence rules as saying where
the parentheses are assumed to be if you do not write parentheses
yourself. Thus the above example is equivalent to a + (b * c)
.
When operators of equal precedence are used together, the leftmost
operator groups first. Thus, a - b + c
groups as
(a - b) + c
.
This table lists radtest
operators in order from highest
precedence to the lowest:
$
(...)
+ - not !
* / %
+ -
< <= = != > >=
and
or
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
A function is a name for a particular sequence of statements. The syntax for the function definition is:
name begin ... end |
where name is function name and `...' represent a
non-empty list of valid radtest
statements.
Notice that newline characters are obligatory after name,
begin
and before the final end
keyword.
If the function accepts arguments, these can be referenced in the
function body using $n
notation (see section 13.2.5 Positional Parameters). To return the value from the function return
statement is used.
For example, here is a function that computes sum of the squares of its two arguments:
hypo begin return $1*$1 + $2*$2 end |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Radtest
provides two commands for interaction with remote
RADIUS servers.
Command send
sends request to the server specified in
`raddb/client.conf'. Its syntax is:
send [flags] port-type code [expr-or-pair-list] |
Optional flags can be used for fine-tuning the internals of
send
. You will seldom need to use these, unless you are
developing GNU Radius. See section send, for the detailed description of these.
The first obligatory argument, port-type, specifies which RADIUS port to send the request to. Specifying `auth' will send the request to the authentication port (see section auth-port); specifying `acct' will send it to the accounting port (see section acct-port).
Argument code gives the request code. It is either a number or a symbolic request code name (see section 13.2.2.1 Numeric Values).
The last argument, expr-or-pair-list is either a
radtest
expression evaluating to avlist
or a list
of A/V pairs. These pairs will be included in the request.
Here are several examples:
# Send a |
Command send
stores the reply code into the variable
REPLY_CODE
and reply pairs into the variable REPLY
(see section 13.2.4.6 Built-in Variables).
<FIXME> How do I know if send
has failed? </>
Another primitive is expect
. Expect
takes at most two
arguments: a request code (either numeric or symbolic, (see section 13.2.2.1 Numeric Values)) and optional
list of A/V pairs (similar to send
expr-or-pair-list
argument). Expect
check if these match current
REPLY_CODE
and REPLY
values and if so, prints
the string `PASS'. Otherwise, it prints `FAIL'. This
command is designed primarily for use in GNU Radius testsuite.
Expect
is usually used right after send
, as shown
in the example below:
send auth Access-Request User-Name = "foo" User-Password = "bar" expect Access-Accept Reply-Message = "Access allowed" |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(This message will disappear, once this node revised.)
Radtest
provides two kinds of conditional statements:
if
and case
.
An if
statement in its simplest form is:
if cond stmt |
where cond is a conditional expression and stmt is a
valid radtest
statement. Optional newline may be inserted
between cond stmt.
In this form, if
evaluates the condition and if it yields true,
executes the statement. For example:
if $REPLY[NAS-IP-Address] = 127.0.0.1 print "Request from localhost" |
More complex form of this statement allows to select between the two statements:
if cond stmt-1 else stmt-2 |
Here, stmt-1 will be executed if cond evaluates to true, and stmt-2 will be executed if cond evaluates to false.
Notice, that an optional newline is allowed between cond and
stmt-1 and right after else
keyword. However, a newline
before else
constitutes an error.
If several statements should be executed in a branch of the if
statement, use compound statement as in the example below:
if $REPLY_CODE != Accounting-Response begin print "Accounting failed.\n" exit 1 end else print "Accounting succeeded.\n" |
If
statements can be nested to any depth.
Case
statement allows select a statement based on whether
a string
expression matches given regular expression. The
syntax of case
statement is:
case expr in expr-1 ) stmt-1 expr-2 ) stmt-2 ... expr-n ) stmt-n end |
where expr is a control expression, expr-1, expr-2 etc. are expressions evaluating to extended POSIX regular expressions (for the detailed description of these see section `Regular Expression Library' in Regular Expression Library).
Case
statement first evaluates expr and converts it to
string
data type. Then it evaluates each expr-n in turn
and tests if the resulting regular expression matches expr. If
so, the statement stmt-n is executed and the execution of
case
statement finishes.
The following example illustrates the concept:
case $COMMAND in "auth.*") authenticate($LIST, no) "acct") authenticate($LIST, yes) ".*") begin print "Unknown command." exit 1 end end |
Bourne shell
programmers should notice that:
Case
statement ends with end
, not esac
.
;;
at the end of each branch,
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
(This message will disappear, once this node revised.)
Two looping constructs are provided: while
and
do...while
.
The syntax of a while loop is:
while cond stmt |
Newline after cond is obligatory.
do stmt while cond |
As usual do...while
loop differs from its while
counterpart in that its stmt is executed at least once.
The looping constructs can be nested to any depth.
Two special statements are provided for branching within loop
constructs. These are break
and continue
.
Break
statement stops the execution of the current
loop statement and passes control to the statement immediately
following it
while $x < 10 begin if $x < $y break ... x = $x + 1 end print "OK\n" |
In the example above, execution of break
statement passes
control to print
statement.
Break
may also take an argument: a literal number representing
the number of nested loop statements to break from. For example, the
break
statement in the sample code below will exit from the
outermost while
:
while $y < 10 begin while $x < 10 begin if $x < $y break 2 ... x = $x + 1 end ... y = $y + 1 end print "OK\n" |
Continue
statement passes control to the condition of the
current looping construct. When used with a numeric argument, the
latter specifies the number of the nesting looping construct to
pass control to (as with break
, the innermost loop is
considered to have number 1, so continue
is equivalent
to continue 1
).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Getopt
is used to break up command line options for
subsequent parsing.
The only mandatory argument, optstring is a list of short (one-character) options to be recognized. Each short option character in optstring may be followed by one colon to indicate it has a required argument, and by two colons to indicate it has an optional argument. <FIXME> Document starting `+' and `-' chars. </>
Each subsequent invocation of getopt
processes next command
line argument. Getopt
returns true if the argument is an
option and returns false otherwise. It stores the retrieved option
(always with a leading dash) in the variable opt (OPTVAR
by default). If the option has an argument, the latter is stored
in the variable arg (OPTARG
by default). Index of the
next command line argument to be processed is preserved in the
variable ind (OPTIND
by default).
The usual way of processing command line options is by invoking
getopt
in a condition expression of while
loop and
analyzing its return values within the loop. For example:
while getopt "hf:" case $OPTVAR in "-h") print "Got -h option\n" "-f") print "Got -f option. Argument is " $OPTARG "\n" ".*") begin print "Unknown option: " $OPTVAR "\n" exit 1 end end end |
If expr is given, name must also be present.
If name is not given, variable INPUT is used by default.
radtest
command line options. Options should
be a valid radtest
command line (see section 13.2.1 Invoking radtest).
$2
becomes
$1
, $3
becomes $2
etc. $#
is decremented.
$0
is not affected.
If expr is given, it is evaluated, converted to integer and
used as shift value. Thus shift 2
shifts all positional
parameters left by 2.
It is an error to use return
outside of a function definition.
See section 13.2.10 Loops, for the detailed discussion of the subject.
See section 13.2.10 Loops, for the detailed discussion of the subject.
REPLY_CODE
and reply A/V pairs in
the variable REPLY
(see section 13.2.8 Interacting with Radius Servers).
flags are a whitespace-separated list of variable assignments. Following variables are understood:
repeat=n
id=n
keepauth=1
avlist
, or an immediate
avlist
(see section 13.2.2.3 Lists of A/V pairs). In the latter case, the parentheses
around the list are optional.
REPLY_CODE
matches code and, optionally, if
REPLY
matches expr-or-pair-list. If so, print the
string `PASS', otherwise print `FAIL'.
See section 13.2.8 Interacting with Radius Servers, for the detailed discussion of this statement.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
As an example, let's consider radauth
program
(see section 12.6 radauth
). Its main purpose is to send authentication
request to the remote server, analyze its reply and if it is
positive, send an appropriate accounting record, thereby initiating
user's session. Optionally, the script should also be able to
send a lone accounting record.
In the discussion below, we will show and explain subsequent parts of the script text. For the ease of explanation, each line of program text will be prepended by its ordinal line number.
The script begins as follows:
1 #! /usr/bin/radtest -f 2 3 while getopt "n:s:P:hv" 4 begin 5 case $OPTVAR in 6 "-n") NASIP = $OPTARG 7 "-s") SID = $OPTARG 8 "-P") PID = $OPTARG 9 "-v") set -v |
radtest
in order to interpret the program.
Getopt
(see section getopt) in line 3 analyzes each
subsequent command line argument and if it is an option checks
whether it matches one of the option letters defined in its
first argument. The option letter will be returned in OPTVAR
variable, its argument (if any) -- in OPTARG
variable.
OPTARG
value is analyzed using case
statement. Lines
6 -- 8 preserve OPTARG
values in appropriate variables for
later use. NASIP
will be used as the value of
NAS-IP-Address
attribute, SID
is the session id
(Acct-Session-Id
attribute), and PID
is the port
number (for NAS-Port-Id
attribute.
radtest
interpreter (see section 13.2.1 Invoking radtest).
The next piece of code handles `-h' and erroneous options:
10 "-h") begin 11 print <<-EOT 12 usage: radauth [OPTIONS] [COMMAND] login [password] 13 Options are: 14 -v Print verbose descriptions of what is being done 15 -n IP Set NAS IP address 16 -s SID Set session ID 17 -P PORT Set NAS port number 18 COMMAND is one of: 19 auth Send only Access-Request (default) 20 acct Send Access-Request. If successfull, send 21 accounting start request 22 start Send accounting start request 23 stop Send accounting stop request 24 EOT 25 exit 0 26 end 27 ".*") begin 28 print "Unknown option: " $OPTVAR "\n" 29 exit 1 30 end 31 end 32 end |
33 34 shift ${OPTIND}-1 35 36 if $# > 3 37 begin 38 print "Wrong number of arguments." 39 print "Try radauth -h for more info" 40 exit 1 41 end |
OPTIND
keeps the ordinal number of the first non-optional
argument. This line shifts off all the options processed by
getopt
, so that the first non-optional argument may be
addressed by $1
notation. Notice use of curly braces to
solve minus ambiguity (see minus-ambiguity).
Next piece of code:
42 43 case $1 in 44 "auth|acct|start|stop") begin 45 COMMAND=$1 46 shift 1 47 end 48 ".*") COMMAND="auth" 49 end 50 51 LOGIN=${1:?User name is not specified. Try radauth -h for more info.} 52 53 if ${NASIP:-} = "" 54 NASIP=$SOURCEIP 55 56 LIST = ( User-Name = $LOGIN NAS-IP-Address = $NASIP ) |
COMMAND
and shift arguments by one, so login becomes argument
$1
. Otherwise, assume `auth' command.
LOGIN
variable. Otherwise, print diagnostic message and exit.
NASIP
variable from the built-in
variable SOURCEIP
(see section 13.2.4.6 Built-in Variables)
LIST
will hold the list of A/V pairs to be sent
to the server. This line initializes it with a list of two A/V pairs:
User-Name
and NAS-IP-Address
.
Accounting function will be used to send accounting requests to
the server. It is supposed to take a single argument: an avlist
of A/V pairs to be sent to the server.
57 58 'acct' 59 begin 60 if ${SID:-} = "" 61 input "Enter session ID: " SID 62 if ${PID:-} = "" 63 input "Enter NAS port ID: " PID 64 send auth Accounting-Request $1 + \ (Acct-Session-Id = $SID NAS-Port-Id = $PID) |
SID
(session ID) is not supplied, prompt the
user to input it.
PID
(port ID) is not supplied, prompt the
user to input it.
Acct-Session-Id
and NAS-Port-Id
attributes
to the function's first argument.
The final part of acct
function analyzes the reply from the
server:
65 if $REPLY_CODE != Accounting-Response 66 begin 67 print "Accounting failed.\n" 68 exit 1 69 end 70 print "Accounting OK.\n" 71 exit 0 72 end 73 |
Notice, that acct
never returns. Instead it exits with an
error code indicating success or failure.
The purpose of the authentication function auth
is
to send an Access-Request
to the server and perform
some actions based on its reply.
The function will take three arguments:
$1
$2
$3
The function is not expected to return. Instead it should exit to the shell with an appropriate error code.
74 'auth' 75 begin 76 send auth Access-Request $1 + (User-Password = $2) |
User-Password
pair to the list given
by the first argument to the function.
The rest of the function analyzes the reply from the server and takes
appropriate actions. Notice that if the server replies with an
Access-Challenge
packet, we will have to send subsequent
authentication requests, so this piece of code is enclosed within
a while
loop.
First, the function handles Access-Accept
and
Access-Reject
replies:
77 while 1 78 begin 79 if $REPLY_CODE = Access-Accept 80 begin 81 print "Authentication passed. " + $REPLY[Reply-Message*] + "\n" 82 if ${3:-no} = no 83 exit 0 84 'acct'($1 + ( Acct-Status-Type = Start )) 85 end else if $REPLY_CODE = Access-Reject 86 begin 87 print "Authentication failed. " + $REPLY[Reply-Message*] + "\n" 88 break |
while
loop. It will eventually be exited
either using break
, or using exit
(see below).
Access-Accept
replies:
Reply-Message
attribute from the reply
packet (see section 13.2.4.4 Accessing Elements of A/V Pair Lists).
acct
function to perform accounting. The
A/V pairs included in the accounting request are formed by adding
Acct-Status-Type
attribute to the list given by the first
argument to the function.
Access-Reject
replies. Print the reply message and
break from the loop.
Next piece of code deals with Access-Challenge
replies. For
simplicity we assume that such replies always carry user menus
(See section 5.13 Login Menus -- `raddb/menus', for the description of these). So, upon
receiving an Access-Challenge
we should print out the menu,
read the users selection and send back an Access-Request
to the server. This part is the only one that actually continues
the loop at line 77.
89 end else if $REPLY_CODE = Access-Challenge 90 begin 91 print $REPLY[Reply-Message*] 92 input 93 send auth Access-Request \ 94 (User-Name = $LOGIN User-Password = $INPUT \ State = $REPLY[State]) |
Reply-Message
attributes. There may be several instances of the attribute, hence the
use of `*' to concatenate their values together.
INPUT
variable. See section 13.2.11 Built-in Primitives, for the description of
input
statement.
Access-Request
packet with three attributes.
User-Password
contains the user reply, State
contains
the menu state from the server reply packet.
Final part of the function:
95 end else begin 96 print "Authentication failed. Reply code " + $REPLY_CODE + "\n" 97 break 98 end 99 end 100 exit 1 101 end 102 |
break
is executed either on line 88 or on line 97.
The final part selects an action based on the user command and
executes it. It is equivalent to the main
function in a
C
program:
103 case ${COMMAND} in 104 "auth") 'auth'($LIST, ${2:&Password: }, no) 105 "acct") 'auth'($LIST, ${2:&Password: }, yes) 106 "start") 'acct'($LIST+(Acct-Status-Type = Start)) 107 "stop") 'acct'($LIST+(Acct-Status-Type = Stop)) 108 ".*") begin 109 print "Unknown command. Try radauth -h for more info" 110 exit 1 111 end 112 end 113 114 # End of radauth |
COMMAND
variable.
auth
function. If the second argument is given in the
command line, its value is taken as user's password. Otherwise, the
user is prompted for the password with the string `Password: '.
The input is read with echo turned off to prevent the password from
being compromised (the `:&' construct, see section 13.2.4.3 Dereferencing Variables).
acct
function for `start' and stop
commands.
case
statement from line 103.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
radsession
is a Guile script that sends authentication and
accounting requests to the Radius server. To invoke the script, run
radsession options action |
Possible actions are:
Options determine the contents of the request's pairlist. They are:
NAS-IP-Address
attribute.
Acct-Session-Id
attribute).
NAS-Port-Id
attribute).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
nas.scm
nas.scm
is a Guile program that allows one to convert a GNU/Linux
box into a NAS. It requires Guile version 1.4 or better and PPP
version 2.3.7 or better.
To use it, you will basically need to do the following:
ln -s libexec/nas.scm /etc/ppp/ip-up ln -s libexec/nas.scm /etc/ppp/ip-down |
Here, libexec denotes the location of your libexec directory,
where nas.scm
is installed. If not overridden at configure
time, it defaults to `prefix/libexec'. These links assure
that ppp
will invoke nas.scm
when the user's session
starts and ends, thus giving it a possibility to send accounting
requests.
nas-log-facility
, specifying the syslog
facility to be used for logging, and pppd-args
, keeping the
arguments to be given to ppp
.
getty
.
For example, if you use mgetty
, then the `inittab'
entries for dial-up lines will look like:
d0:345:respawn:/sbin/mgetty ttyS0 vt100 d1:345:respawn:/sbin/mgetty ttyS1 vt100 ... |
mgetty
's `login.config' will then contain the following line:
* - - /usr/local/libexec/nas.scm @ |
If you use agetty
, then the `inittab' will contain
(with the long lines split for readability)
d0:345:respawn:/sbin/agetty -mt60 \ -l /usr/local/libexec/nas.scm 38400,19200,9600 \ ttyS0 vt100 d1:345:respawn:/sbin/agetty -mt60 \ -l /usr/local/libexec/nas.scm 38400,19200,9600 \ ttyS1 vt100 ... |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
pam_radius.so
pam_radius.so
is a PAM module for Radius
authentication. The module understands the following command line options:
Debugging levels equal to or greater than 10 compromise users' passwords, so use them sparingly.
attr: Service-Type=type |
The pam_radius.so
module logs its messages under LOG_AUTH
syslog facility.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |