unlang(5) FreeRADIUS Processing un-language unlang(5) NAME unlang - FreeRADIUS Processing un-language DESCRIPTION FreeRADIUS 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 language is similar to C in some respects, and is also similar to Unix shell scripts in other respects. The keywords for the language are "if", "else", "elsif", "switch", "case", and "update". Subject to some limitations below on "switch" and "case", any keyword can appear in any context. KEYWORDS if Checks for a particular condition. If true, the block after the condition is processed. Otherwise, the block is ignored. if (condition) { ... } else Define a block to be executed only if the previous "if" condi‐ tion returned false. else { ... } elsif Define a block to be executed only if the previous "if" condi‐ tion returned false, and if the specified condition evaluates to true. elsif (condition) { ... } switch Evaluate the given string, and choose the first matching "case" statement inside of the current block. No statement other than "case" can appear in a "switch" block. switch "string" { ... } case Define a static string to match a parent "switch" statement. A "case" statement cannot appear outside of a "switch" block. case string { ... } update Update a particular attribute list, based on the attributes given in the current block. update { attribute = value ... } The can be one of "request", "reply", "proxy-request", "proxy-reply", or "control". The "control" list is the list of attributes maintainted 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 a detailed description of the contents of the "update" sec‐ tion, see the ATTRIBUTES section below. CONDITIONS The conditions are similar to C conditions in syntax, though quoted strings are supported, as with the Unix shell. Simple conditions (foo) Evalutes to true if ’foo’ is a non-empty string, or if ’foo’ is a non-zero number. Negation (!foo) Evalutes to true if ’foo’ evaluates to false, and vice-versa. Short-circuit operators (foo || bar) (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. Comparisons (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. Invalid comparison operators are ":=" and "=". STRINGS AND NUMBERS Strings and numbers can appear as stand-alone conditions, 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. Numbers Numbers are composed of decimal digits. Floating point, hex, and octal numbers are not supported. The maximum value for a number is machine-dependent, but is usually 32-bits, including one bit for a sign value. "strings" Double-quoted strings are expanded by inserting the value of any variables (see VARIABLES, below) before being evaluated. If the result is a number it can be evaluated in a numerical context. ’strings’ Single-quoted strings are evaluated as-is. ‘strings‘ Back-quoted strings are evaluated by expanding the contents of the string, as described above for double-quoted strings. The resulting command given inside of the string in a sub-shell, and taking the output as a string. This behavior is much the same as that of Unix shells. Note that for security reasons, the input string is split into command and arguments before variable expansion is done. For performance reasons, we suggest that the use of back-quoted strings be kept to a minimum. Executing external programs is relatively expensive, and executing a large number of programs for every request can quickly use all of the CPU time in a server. If you believe that you need to execute many programs, we suggest finding alternative ways to achieve the same result. In some cases, using a real language may be sufficient. /regex/i These strings are valid only on the right-hand side of a compar‐ ison, and then only when the comparison operator is "=~" or "!~". They are regular expressions, as implemented by the local regular expression library on the system. This is usually Posix regular expressions. The trailing ’i’ is optional, and indicates that the regular expression match should be done in a case-insensitive fashion. If the comparison operator is "=~", then parantheses in the reg‐ ular expression will define variables containing the matching text, as described below in the VARIABLES section. VARIABLES Run-time variables are referenced using the following syntax %{Variable-Name} Note that unlike C, there is no way to declare variables, or to refer to them outside of a string context. All references to variables MUST be contained inside of a double-quoted or back-quoted string. Many potential variables 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 variable. When the server receives a packet, it uses the packet contents to look up entries in the dictio‐ nary, and instantiates variables with a name taken from the dictionar‐ ies, and a value taken from the packet contents. This process means that if a variable does not exist, it is usually because it was not mentioned in a packet that the server received. Once the variable is instantiated, it is added to an appropriate attribute list, as described below. In many cases, attributes and variables are inter-changeble, and are often talked about that way. However, variables can also refer to run-time calls to modules, which may perform operations like SQL SELECTs, and which may return the result as the value of the variable. Referencing attribute lists Attribute lists may be referenced via the following syntax %{:Attribute-Name} Where is one of "request", "reply", "proxy-request", "proxy-reply", or "control", as described above in the documen‐ tation for the "update" section. The ":" prefix is optional, and if omitted, is assumed to refer to the "request" list. When a variable is encountered, the given list is examined for an attribute of the given name. If found, the variable refer‐ ence in the string is replaced with the value of that attribute. Some examples are: %{User-Name} %{request:User-Name} # same as above %{reply:User-Name} 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 input string. The variables %{1} through %{8} will contain the sub‐ string matches, starting from the left-most parantheses, and onwards. If there are more than 8 parantheses, the additional results will not be placed into any variables. 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 variable ref‐ erence 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. %{Foo:-bar} When attribute Foo is set, returns value of Foo When attribute Foo is unset, returns literal string ’bar’ %{Foo:-%{Bar}} When attribute Foo is set, returns value of attribute Foo When attribute Foo is unset, returns value of attribute Bar (if any) %{Foo:-%{Bar:-baz}} When attribute Foo is set, returns value of attribute Foo When attribute Foo is unset, returns value of attribute Bar (if any) When attribute Bar is unset, returns literal string ’baz’ String lengths and arrays Similar to a Unix shell, there are ways to reference string lenths, and the second or more instance of an attribute in a list. If you need this functionality, we recommend using a real language. %{#string} The number of characters in %{string}. If %{string} is not set, then the length is not set. e.g. %{#Junk-junk:-foo} will yeild the string "foo". %{Attribute-Name[index]} Reference the N’th occurance of the given attribute. The syntax %{:Attribute-Name[index]} may also be used. The indexes start at zero. This feature is NOT available for non-attribute dynamic translations, like %{sql:...}. For example, %{User-Name[0]} is the same as %{User-Name} The variable %{Cisco-AVPair[2]} will reference the value of the THIRD Cisco-AVPair attribute (if it exists) in the request packet, %{Attribute-Name[#]} Returns the total number of attributes of that name in the relevant attribute list. The number will usually be between 0 and 200. For most requests, %{request:User-Name[#]} == 1 %{Attribute-Name[*]} Expands to a single string, with the value of each array member separated by a newline. %{#Attribute-Name[index]} Expands to the length of the string %{Attribute- Name[index]}. ATTRIBUTES The 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 VARIABLES 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-Name = value Attribute names The Attribute-Name must be a name previously defined in a dic‐ tionary. If an undefined name is used, the server will return an error, and will not start. Operators The operator used to assign the value of the attribute may be one of the following, with the given meaning. = Add the attribute to the list, if and only if an attribute of the same name is already present in that list. := Add the attribute to the list. If any attribute of the same name is already present in that list, its value is replaced with the value of the current attribute. += Add the attribute to the tail of the list, even if attributes of the same name are already present in the list. -= Remove all matching attributes from the list. Both the attribute name and value have to match in order for the attribute to be removed from the list. Values The format of the value is attribute-specific, and is usually a string, integer, IP address, etc. Prior to the attribute being instantiated, the value is handled as described above in the STRINGS AND NUMBERS section. This flexibility means that, for example, you can assign an IP address value to an attribute by specifying the IP address directly, or by having the address returned from a database query, or by having the address returned as the output of a program that is executed. FILES /etc/raddb/vmpsd.conf, /etc/raddb/radiusd.conf SEE ALSO radiusd.conf(5), vmpsd.conf(5), dictionary(5) AUTHOR Alan DeKok 12 Jun 2007 unlang(5)