trusty (5) unlang.5.gz

Provided by: freeradius-common_2.1.12+dfsg-1.2ubuntu8.2_all bug

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 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.

KEYWORDS

       The 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 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.

       module-name
              A reference to the named module.  When processing reaches this point, the pre-compiled  module  is
              called.   The module may succeed or fail, and will return a status to "unlang" if so.  This status
              can be tested in a condition.  See the "Simple Conditions" text in  the  CONDITIONS  section,  and
              MODULE RETURN CODES, below.

                   chap  # call the CHAP module
                   sql   # call the SQL module
                   ...

       if
              Checks  for  a  particular  condition.   If  true,  the  block  after  the condition is processed.
              Otherwise, the block is ignored.  See CONDITIONS, below, for documentation on the  format  of  the
              conditions.

                   if (condition) {
                        ...
                   }

       else
              Define a block to be executed only if the previous "if" condition returned false.

                   else {
                        ...
                   }

       elsif
              Define  a  block  to  be  executed  only if the previous "if" condition 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.   If  the  string  is  surrounded by double quotes, it is expanded as described in the DATA
              TYPES section, below.

              No statement other than "case" can appear in a "switch" block.

                   switch "string" {
                        ...
                   }

       case
              Define a static string to match a parent "switch" statement.   The  strings  given  here  are  not
              expanded as is done with the parent "switch" statement.

              A "case" statement cannot appear outside of a "switch" block.

                   case string {
                        ...
                   }

              A default entry can be defined by omitting the static string.  This entry will be used if no other
              "case" entry matches.  Only one default entry can exist in a "switch" section.

                   case {
                        ...
                   }

       update
              Update a particular attribute list, based on the attributes given in the current block.

                   update <list> {
                        attribute = value
                        ...
                   }

              The <list> can be one of "request", "reply", "proxy-request", "proxy-reply", "coa",  "disconnect",
              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  backwards  compatibility with older versions, "check" is accepted as a synonym for "control".
              The use of "check" is deprecated, and will be removed in a future release.

              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 only contents permitted in an "update" section are attributes and values.  The contents of the
              "update" section are described in the ATTRIBUTES section below.

       redundant
              This section contains a simple list of modules.  The first module is called when  the  section  is
              being  processed.  If the first module succeeds in its operation, then the server stops processing
              the section, and returns to the parent section.

              If, however, the module fails, then the next module in the list is tried, as described above.  The
              processing continues until one module succeeds, or until the list has been exhausted.

              Redundant  sections  can  contain only a list of modules, and cannot contain keywords that perform
              conditional operations (if, else, etc) or update an attribute list.

                   redundant {
                        sql1 # try this
                        sql2 # try this only if sql1 fails.
                        ...
                   }

       load-balance
              This section contains a simple list of modules.  When the section is entered, one module is chosen
              at  random  to  process the request.  All of the modules in the list should be the same type (e.g.
              ldap or sql).  All of the modules in the list  should  behave  identically,  otherwise  the  load-
              balance section will return different results for the same request.

              Load-balance sections can contain only a list of modules, and cannot contain keywords that perform
              conditional operations (if, else, etc) or update an attribute list.

                   load-balance {
                        ldap1     # 50% of requests go here
                        ldap2     # 50% of requests go here
                   }

              In general, we recommend using "redundant-load-balance" instead of "load-balance".

       redundant-load-balance
              This section contains a simple list of modules.  When the section is entered, one module is chosen
              at  random  to process the request.  If that module succeeds, then the server stops processing the
              section.  If, however, the module fails, then one of the remaining modules is chosen at random  to
              process  the  request.  This process repeats until one module succeeds, or until the list has been
              exhausted.

              All of the modules in the list should be the same type (e.g. ldap or sql).  All of the modules  in
              the  list  should  behave  identically,  otherwise  the load-balance section will return different
              results for the same request.

              Load-balance sections can contain only a list of modules, and cannot contain keywords that perform
              conditional operations (if, else, etc) or update an attribute list.

                   redundant-load-balance {
                        ldap1     # 50%, unless ldap2 is down, then 100%
                        ldap2     # 50%, unless ldap1 is down, then 100%
                   }

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 (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 comparings
              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.

       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 "=".

       Conditions may be nested to any depth, subject only to line length limitations (8192 bytes).

DATA TYPES

       There 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.

       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.

       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") {
                        ...
                   if (Framed-IP-Address > 127.0.0.1) {
                        ...
                   if (Service-Type == Login-User) {

       "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 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\" !")

       'strings'
              Single-quoted  strings  are  evaluated as-is.  Their values are not expanded as with double-quoted
              strings above, and they are not interpreted as attribute references.

       `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 comparison, 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  regular  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 dictionary, and instantiates variables with
       a  name taken from the dictionaries, 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

                   %{<list>:Attribute-Name}

              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.

              When a variable is encountered, the given list is examined for an attribute of the given name.  If
              found, the variable reference 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}
                   %{outer.reqest:User-Name} # from inside of a TTLS/PEAP tunnel

       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  substring
              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 reference
              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}
                     If %{Foo} has a value, returns that value.
                     Otherwise, returns literal string "bar".

              %{%{Foo}:-%{Bar}}
                     If %{Foo} has a value, returns that value.
                     Otherwise, returns the expansion of %{Bar}.

                     These   conditional   expansions   can  be  nested  to  almost  any  depth,  such  as  with
                     %{%{One}:-%{%{Two}:-%{Three}}}

       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#}
                     Will  print  the integer value of the attribute, rather than a decoded VALUE or date.  This
                     feature applies only to attributes of type "date", "integer", "byte", and "short".  It  has
                     no  effect  on  any  other attributes.  It is used when the numerical value is needed (e.g.
                     Unix seconds), rather than a humanly-readable string.

                     e.g. If a request contains "Service-Type = Login-User", the expansion  of  %{Service-Type#}
                     will yeild "1".

              %{Attribute-Name[index]}
                     Reference  the  N'th  occurance  of  the  given  attribute.  The syntax %{<list>: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 dictionary.  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 not  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.

       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.

              -=     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.

              ==     Keep all matching attributes.  Both the attribute name and value have to match in order for
                     the attribute to remain in the list.

                     Note that this operator is very different than the '=' operator listed above!

              <=     Keep all attributes having values less than, or equal to, the value given here.  Any larger
                     value  is  replaced  by the value given here.  If no attribute exists, it is added with the
                     value given here, as with "+=".

                     This operator is valid only for attributes of integer type.

              >=     Keep all attributes having values greater than, or equal to, the  value  given  here.   Any
                     larger value is replaced by the value given here.  If no attribute exists, it is added with
                     the value given here, as with "+=".

                     This operator is valid only for attributes of integer type.

              !*     Delete all occurances of the named attribute, no matter what the value.

       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 may be expanded as described above in the
              DATA TYPES section, above.  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.

              When  string  values  are  finally  assigned  to a variable, they can have a maximum length of 253
              characters.  This limit is due in part to both protocol and internal  server  requirements.   That
              is,  the  strings  in the language can be nearly 8k in length, say for a long SQL query.  However,
              the output of that SQL query should be no more than 253 characters in length.

OTHER KEYWORDS

       Other 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:

       fail   Cause the request to be treated as if a database failure had occurred.

       noop   Do nothing.  This also serves as an instruction to the configurable failover tracking that nothing
              was done in the current section.

       ok     Instructs the server that the request was processed properly.  This keyword can be used  to  over-
              ride   earlier  failures,  if  the  local  administrator  determines  that  the  faiures  are  not
              catastrophic.

       reject Causes the request to be immediately rejected

MODULE RETURN CODES

       When a module is called, it returns one of the following codes to "unlang", with the following meaning.

            notfound        information was not found
            noop            the module did nothing
            ok              the module succeeded
            updated         the module updated the request
            fail            the module failed
            reject          the module rejected the request
            userlock        the user was locked out
            invalid         the configuration was invalid
            handled         the module has handled the request itself

       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

       /etc/raddb/radiusd.conf

SEE ALSO

       radiusd.conf(5), dictionary(5)

AUTHOR

       Alan DeKok <aland@deployingradius.com>

                                                   19 May 2010                                         unlang(5)