Provided by: freeradius-common_2.1.10+dfsg-3_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)