|
NAMEunlang - FreeRADIUS Processing un-languageDESCRIPTIONFreeRADIUS supports a simple processing language in its configuration files. We call it an "un-language" because the intention is NOT to create yet another programming language. If you need something more complicated than what is described here, we suggest using the Perl or Python modules rlm_perl, or rlm_python.The goal of the language is to allow simple policies to be written with minimal effort. Those policies are then applied when a request is being processed. Requests are processed through virtual servers (including the default one), in the sections titled "authorize", "authenticate", "post-auth", "preacct", "accounting", "pre-proxy", "post-proxy", and "session". These policies cannot be used in any other part of the configuration files, such as module or client configuration. KEYWORDSThe keywords for the language are a combination of pre-defined keywords, and references to loadable module names. We document only the pre-defined keywords here.Subject to a few limitations described below, any keyword can appear in any context. The language consists of a series of entries, each one line. Each entry begins with a keyword. Entries are organized into lists. Processing of the language is line by line, from the start of the list to the end. Actions are executed per-keyword.
chap # call the CHAP module
if (condition) {
else {
elsif (condition) {
foreach &Attribute-Reference {
switch <argument> {
case <argument> { A default entry can be defined by omitting the argument, as given below. This entry will be used if no other "case" entry matches. Only one default entry can exist in a "switch" section. case {
update <list> { The <list> can be one of "request", "reply", "proxy-request", "proxy-reply", "coa", "disconnect", "session-state", or "control". As of Version 3, the <list> can be omitted, in which case "request" is assumed. The "control" list is the list of attributes maintained internally by the server that controls how the server processes the request. Any attribute that does not go in a packet on the network will generally be placed in the "control" list. For EAP methods with tunneled authentication sessions (i.e. PEAP and EAP-TTLS), the inner tunnel session can also reference "outer.request", "outer.reply", and "outer.control". Those references allow you to address the relevant list in the outer tunnel session. The "coa" and "disconnect" sections can only be used when the server receives an Access-Request or Accounting-Request. Use "request" and "reply" instead of "coa" when the server receives a CoA-Request or Disconnect-Request packet. Adding one or more attributes to either of the "coa" or "disconnect" list causes server to originate a CoA-Request or Disconnect-Request packet. That packet is sent when the current Access-Request or Accounting-Request has been finished, and a reply sent to the NAS. See raddb/sites-available/originate-coa for additional information. The "session-state" list is primarily used for EAP. Attributes put into the "session-state" list are saved for the next packet in the session. They are automatically retrieved when the next packet is received. The only contents permitted in an "update" section are attributes and values. The contents of the "update" section are described in the ATTRIBUTE REFERENCE and ATTRIBUTE ASSIGNMENT sections below.
redundant {
load-balance { In general, we recommend using "redundant-load-balance" instead of "load-balance".
redundant-load-balance {
authorize { ATTRIBUTE REFERENCESAttributes may be referenced via the following syntax:&Attribute-Name &Attribute-Name:TAG &Attribute-Name[NUM] &<list>:Attribute-Name &<list>:Attribute-Name:TAG[NUM] Where <list> is one of "request", "reply", "control", "proxy-request", "proxy-reply", or "outer.request", "outer.reply", "outer.control", "outer.proxy-request", or "outer.proxy-reply". just as with the "update" section, above. The "<list>:" prefix is optional, and if omitted, is assumed to refer to the "request" list. The TAG portion is a decimal integer between 1 and 31. Please see RFC 2868 for more information about tags. Tags can only be used for attributes which are marked in the dictionary as "has_tag". The NUM portion is used when there are multiple attributes of the same name in a list. The "Attribute-Name" reference will return the first attribute. Using an array offset allows the policy to refer to the second and subsequent attributes. If '*' is used in the NUM portion, it evaluates to all instances of the attribute in the request. If 'n' is used in the NUM portion, it evaluates to the last instance of the attribute in the request. When an attribute name is encountered, the given list is examined for an attribute of the given name. Some examples are: User-Name Note that unlike C, there is no way to define new attributes at run-time. They MUST be declared in a dictionary file, and loaded when the server starts. All attributes are defined in the dictionaries that accompany the server. These definitions define only the name and type, and do not define the value of the attribute. When the server receives a packet, it uses the packet contents to look up entries in the dictionary, and instantiates attributes with a name taken from the dictionaries, and a value taken from the packet contents. This process means that if an attribute does not exist, it is usually because it was not contained in a packet that the server received. Once the attribute is instantiated, it is added to a list. It can then be referenced, updated, replaced, etc. CONDITIONSThe conditions are similar to C conditions in syntax, though quoted strings are supported, as with the Unix shell.
(foo) Evaluates to true if 'foo' is a non-empty string (single quotes, double quotes, or back-quoted). Also evaluates to true if 'foo' is a non-zero number. Note that the language is poorly typed, so the string "0000" can be interpreted as a numerical zero. This issue can be avoided by comparing strings to an empty string, rather than by evaluating the string by itself. If the word 'foo' is not a quoted string, then it can be taken as a reference to a named attribute. See "Referencing attribute lists", below, for examples of attribute references. The condition evaluates to true if the named attribute exists. Otherwise, if the word 'foo' is not a quoted string, and is not an attribute reference, then it is interpreted as a reference to a module return code. The condition evaluates to true if the most recent module return code matches the name given here. Valid module return codes are given in MODULE RETURN CODES, below.
(!foo) Evaluates to true if 'foo' evaluates to false, and vice-versa. Short-circuit operators (foo || bar) "&&" and "||" are short-circuit operators. "&&" evaluates the first condition, and evaluates the second condition if and only if the result of the first condition is true. "||" is similar, but executes the second command if and only if the result of the first condition is false.
(foo == bar) Compares 'foo' to 'bar', and evaluates to true if the comparison holds true. Valid comparison operators are "==", "!=", "<", "<=", ">", ">=", "=~", and "!~", all with their usual meanings. The operators ":=", "^=" and "=" are assignment operators, and are not allowed for comparisons. The operators "<", "<=", ">", and ">=" are also allowed for checking that an IP address is contained within a network. For example: if (<ipaddr>192.0.2.1 < 192.0.2.0/24) { This comparison succeeds, because the address 192.0.2.1 is
contained within the network 192.0.2.0/24.
(&User-Name == "foo") Compares the value of the User-Name attribute to the string 'foo', and evaluates to true if the comparison holds true. Similarly, (&Framed-IP-Address == 192.0.2.1) Compares the value of the Framed-IP-Address attribute to the IP
address 192.0.2.1. This IP address does not need to be quoted.
(&User-Name == &Filter-Id) Compares the value of the User-Name attribute to the contents of the Filter-Id attribute, and evaluates to true if the comparison holds true. Unlike the previous example, this comparison is done in a type-safe way. For example, comparing the IP addresses 1.2.3.4 and 127.0.0.1 as strings will return different results than comparing them as IP addresses. The "&" character in the condition means that the comparison "refers" to the Filter-Id attribute. If left off, it means that the User-Name attribute is compared to the literal string "Filter-Id". Where the left-hand side is an attribute, the "&" can be omitted. However, it is allowed for backwards compatibility. e.g. The comparison "(&User-Name == &Filter-Id)" is equivalent to the example above. We recommend using attribute references instead of printing attributes to a string, e.g. (User-Name == "%{Filter-Id}"). Attribute references will be faster and more efficient. The conditions will check only the first occurrence of an attribute. If there is more than one instance of an attribute, the following syntax should be used: (&Attribute-Name[*] == "foo") Using the "[*]" syntax means that it checks all of the instances of the named attribute. If one attribute matches, the condition succeeds. If none match, the condition fails.
(<type>foo == bar) The left-hand-side of a condition can be "cast" to a specific data type. The data type must be one which is valid for the dictionaries. e.g. "integer", "ipaddr", etc. The comparison is performed in a type-safe way, as with "Inter-Attribute Comparisons", above. Both sides of the condition are parsed into temporary attributes, and the attributes compared via type-specific methods. The temporary attributes have no other effect, and are not saved anywhere. Casting allows conditions to perform type-specific comparisons. In previous versions of the server, the data would have to be manually placed into an intermediate attribute (or attributes), and then the attribute (or attributes) compared. The use of a cast allows for simpler policies. Casts are allowed only on the left-hand side argument of a condition. Conditions may be nested to any depth, subject only to line length limitations (8192 bytes). DATA TYPESThere are only a few data types supported in the language. Reference to attributes, numbers, and strings. Any data type can appear in stand-alone condition, in which case they are evaluated as described in "Simple conditions", above. They can also appear (with some exceptions noted below) on the left-hand or on the right-hand side of a comparison.
word Text that is not enclosed in quotes is interpreted
differently depending on where it occurs in a condition. On the left hand side
of a condition, it is interpreted as a reference to an attribute. On the right
hand side, it is interpreted as a simple string, in the same manner as a
single-quoted string.
Using attribute references permits limited type-specific comparisons, as seen in the examples below. if (&User-Name == "bob") {
Double-quoted strings are expanded by inserting the value
of any attributes (see ATTRIBUTE REFERENCES, below) before being evaluated. If
the result is a number it is evaluated in a numerical context.
String length is limited by line-length, usually about 8000 characters. A double quote character can be used in a string via the normal back-slash escaping method. ("like \"this\" !")
EXPANSIONSAttributes are expanded using the ATTRIBUTE REFERENCE syntax described above, and surrounding the reference with "%{...}"%{Attribute-Reference} The result will be a string which contains the value of the attribute which was referenced, as a printable string. If the attribute does not exist, the result will be an empty string. Results of regular expression matches If a regular expression match has previously been
performed, then the special variable %{0} will contain a copy of the matched
portion of the input string. The variables %{1} through %{32} will contain the
substring matches, starting from the left-most capture group, onwards. If
there are more than 32 capture groups, the additional results will not be
accessible. If the server is built with libpcre, the results of named capture
groups are available using the "%{regex:capture group}" expansion.
They will also be accessible using the variables described above. Every time a
regular expression is evaluated, whether it matches or not, the capture group
values will be cleared.
Obtaining results from databases It is useful to query a database for some information,
and to use the result in a condition. The following syntax will call a module,
pass it the given string, and replace the string expansion with the resulting
string returned from the module.
%{module: string ...} The syntax of the string is module-specific. Please read the module documentation for additional details. Conditional Syntax Conditional syntax similar to that used in Unix shells
may also be used.
String lengths and arrays Similar to a Unix shell, there are ways to reference
string lengths, and the second or more instance of an attribute in a list. If
you need more than this functionality, we suggest using a real language.
ATTRIBUTE ASSIGNMENTSThe attribute lists described above may be edited by listing one or more attributes in an "update" section. Once the attributes have been defined, they may be referenced as described above in the ATTRIBUTE REFERENCES section.The following syntax defines attributes in an "update" section. Each attribute and value has to be all on one line in the configuration file. There is no need for commas or semi-colons after the value. Attribute-Reference = value Attribute Reference The Attribute-Reference must be a reference (see above),
using a name previously defined in a dictionary. If an undefined name is used,
the server will return an error, and will not start.
Enforcement and Filtering Operators The following operators may also be used in addition to
the ones listed above. Their function is to perform enforcement or filtering
on attributes in a list.
OTHER KEYWORDSOther keywords in the language are taken from the names of modules loaded by the server. These keywords are dependent on both the modules, and the local configuration.Some use keywords that are defined in the default configuration file are:
MODULE RETURN CODESWhen a module is called, it returns one of the following codes to "unlang", with the following meaning.notfound information was not found These return codes can be tested for in a condition, as described above in the CONDITIONS section. See also the file doc/configurable_failover for additional methods of trapping and modifying module return codes. FILES/usr/local/share/examples/freeradius/raddb/radiusd.confSEE ALSOradiusd.conf(5), dictionary(5)AUTHORAlan DeKok <aland@deployingradius.com>
Visit the GSP FreeBSD Man Page Interface. |