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)