Note module return codes
[freeradius.git] / man / man5 / unlang.5
index 4731a94..64ebbba 100644 (file)
@@ -1,4 +1,16 @@
-.TH unlang 5 "12 Jun 2007" "" "FreeRADIUS Processing un-language"
+.\"     # DS - begin display
+.de DS
+.RS
+.nf
+.sp
+..
+.\"     # DE - end display
+.de DE
+.fi
+.RE
+.sp
+..
+.TH unlang 5 "19 May 2010" "" "FreeRADIUS Processing un-language"
 .SH NAME
 unlang \- FreeRADIUS Processing un\-language
 .SH DESCRIPTION
@@ -8,16 +20,45 @@ 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.
+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.
 .SH 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.
+.IP 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.
+
+.DS
+       chap  # call the CHAP module
+.br
+       sql   # call the SQL module
+.br
+       ...
+.DE
 .IP if
 .br
 Checks for a particular condition.  If true, the block after the
-condition is processed.  Otherwise, the block is ignored.
+condition is processed.  Otherwise, the block is ignored.  See
+CONDITIONS, below, for documentation on the format of the conditions.
 
 .DS
        if (condition) {
@@ -53,8 +94,11 @@ returned false, and if the specified condition evaluates to true.
 .IP switch
 .br
 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.
+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.
 
 .DS
        switch "string" {
@@ -65,8 +109,11 @@ can appear in a "switch" block.
 .DE
 .IP case
 .br
-Define a static string to match a parent "switch" statement.  A "case"
-statement cannot appear outside of a "switch" block.
+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.
 
 .DS
        case string {
@@ -76,9 +123,9 @@ statement cannot appear outside of a "switch" block.
        }
 .DE
 
-A "default" entry can be defined by not specifying a static string.
-This entry will be used if no other "case" entry matches.  Only one
-"default" entry can exist in a "switch" section.
+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.
 
 .DS
        case {
@@ -103,14 +150,110 @@ the current block.
 .DE
 
 The <list> 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.
+"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.  For a detailed description of the contents of the "update"
-section, see the ATTRIBUTES section below.
+values.  The contents of the "update" section are described in the
+ATTRIBUTES section below.
+.IP 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.
+
+.DS
+       redundant {
+.br
+               sql1    # try this
+.br
+               sql2    # try this only if sql1 fails.
+.br
+               ...
+.br
+       }
+.DE
+.IP 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.
+
+.DS
+       load-balance {
+.br
+               ldap1   # 50% of requests go here
+.br
+               ldap2   # 50% of requests go here
+.br
+       }
+.DE
+
+In general, we recommend using "redundant-load-balance" instead of
+"load-balance".
+.IP 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.
+
+.DS
+       redundant-load-balance {
+.br
+               ldap1   # 50%, unless ldap2 is down, then 100%
+.br
+               ldap2   # 50%, unless ldap1 is down, then 100%
+.br
+       }
+.DE
 .SH CONDITIONS
 The conditions are similar to C conditions in syntax, though
 quoted strings are supported, as with the Unix shell.
@@ -121,8 +264,23 @@ conditions
        (foo)
 .DE
 
-Evalutes to true if 'foo' is a non-empty string, or if 'foo' is a
-non-zero number.
+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.
 .IP Negation
 .DS
        (!foo)
@@ -154,25 +312,59 @@ 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 "=".
-.SH 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.
-.IP Numbers
+.PP
+Conditions may be nested to any depth, subject only to line length
+limitations (8192 bytes).
+.SH 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.
+.IP 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.
 .PP
-"strings"
+word
+.RS
+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.
+
+.DS
+       if (User-Name == "bob") {
+.br
+               ...
+.br
+       if (Framed-IP-Address > 127.0.0.1) {
+.br
+               ...
+.br
+       if (Service-Type == Login-User) { 
+.DE
+.RE
+.IP """strings"""
 .RS
 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.
+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\\" !")
 .RE
 .IP 'strings'
-Single-quoted strings are evaluated as-is.
+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.
 .IP `strings`
 Back-quoted strings are evaluated by expanding the contents of the
 string, as described above for double-quoted strings.  The resulting
@@ -237,9 +429,10 @@ Attribute lists may be referenced via the following syntax
        %{<list>:Attribute-Name}
 .DE
 
-Where <list> is one of "request", "reply", "proxy-request",
-"proxy-reply", or "control", as described above in the documentation
-for the "update" section.  The "<list>:" prefix is optional, and if
+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
@@ -252,6 +445,8 @@ string is replaced with the value of that attribute.  Some examples are:
        %{request:User-Name} # same as above
 .br
        %{reply:User-Name}
+.br
+       %{outer.reqest:User-Name} # from inside of a TTLS/PEAP tunnel
 .DE
 .RE
 .PP
@@ -284,18 +479,17 @@ Conditional Syntax
 .RS
 Conditional syntax similar to that used in Unix shells may also be
 used.
-.IP %{Foo:-bar}
-When attribute Foo is set, returns value of Foo
-When attribute Foo is unset, returns literal string 'bar'
-
-.IP %{Foo:-%{Bar}}
-When attribute Foo is set, returns value of attribute Foo
-When attribute Foo is unset, returns value of attribute Bar (if any)
-
-.IP %{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'
+.IP %{%{Foo}:-bar}
+If %{Foo} has a value, returns that value.
+.br
+Otherwise, returns literal string "bar".
+.IP %{%{Foo}:-%{Bar}}
+If %{Foo} has a value, returns that value.
+.br
+Otherwise, returns the expansion of %{Bar}.
+
+These conditional expansions can be nested to almost any depth, such
+as with %{%{One}:-%{%{Two}:-%{Three}}}
 .RE
 .PP
 String lengths and arrays
@@ -308,6 +502,15 @@ 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".
+.IP %{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".
 .IP %{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
@@ -354,7 +557,7 @@ the following, with the given meaning.
 .RS
 .IP =
 Add the attribute to the list, if and only if an attribute of the same
-name is already present in that list.
+name is not already present in that list.
 .IP := 
 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
@@ -362,47 +565,109 @@ the current attribute.
 .IP +=
 Add the attribute to the tail of the list, even if attributes of the
 same name are already present in the list.
+.RE
+.PP
+Enforcement and Filtering Operators
+.RS
+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.
 .IP -=
 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.
+.IP ==
+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!
 .IP <=
-Enforce that the integer value of the attribute is less than or equal
-to the value given here.  If there is no attribute of the same name in
-the list, the attribute is added with the given value, is with "+=".
-If an attribute in the list exists, and has value less than given
-here, it's value is unchanged.  If an attribute in the exists, and has
-value greater than given here, it's value is replaced with the value
-given here.
+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.
 .IP >=
-Enforce that the integer value of the attribute is greater than or
-equal to the value given here.  If there is no attribute of the same
-name in the list, the attribute is added with the given value, is with
-"+=".  If an attribute in the list exists, and has value greater than
-given here, it's value is unchanged.  If an attribute in the exists,
-and has value less than given here, it's value is replaced with the
-value given here.
+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.
+.IP !*
+Delete all occurances of the named attribute, no matter what the
+value.
 .RE
 .IP Values
 .br
 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
+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.
+.SH 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:
+.IP fail
+Cause the request to be treated as if a database failure had occurred.
+.IP noop
+Do nothing.  This also serves as an instruction to the configurable
+failover tracking that nothing was done in the current section.
+.IP 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.
+.IP reject
+Causes the request to be immediately rejected
+.SH MODULE RETURN CODES
+When a module is called, it returns one of the following codes to
+"unlang", with the following meaning.
+
+.DS
+       notfound        information was not found
+.br
+       noop            the module did nothing
+.br
+       ok              the module succeeded
+.br
+       updated         the module updated the request
+.br
+       fail            the module failed
+.br
+       reject          the module rejected the request
+.br
+       userlock        the user was locked out
+.br
+       invalid         the configuration was invalid
+.br
+       handled         the module has handled the request itself
+.DE
+
+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.
 .SH FILES
-/etc/raddb/vmpsd.conf,
 /etc/raddb/radiusd.conf
 .SH "SEE ALSO"
 .BR radiusd.conf (5),
-.BR vmpsd.conf (5),
 .BR dictionary (5)
 .SH AUTHOR
 Alan DeKok <aland@deployingradius.com>