diff options
Diffstat (limited to 'doc/antora/modules/unlang/pages/xlat/builtin.adoc')
-rw-r--r-- | doc/antora/modules/unlang/pages/xlat/builtin.adoc | 891 |
1 files changed, 891 insertions, 0 deletions
diff --git a/doc/antora/modules/unlang/pages/xlat/builtin.adoc b/doc/antora/modules/unlang/pages/xlat/builtin.adoc new file mode 100644 index 0000000..f236a57 --- /dev/null +++ b/doc/antora/modules/unlang/pages/xlat/builtin.adoc @@ -0,0 +1,891 @@ += Built-In Expansions + +In addition to storing attribute references, the server has a number +of built-in expansions. These expansions act largely as functions +which operate on inputs, and produce an output. + + + +== Attribute Manipulation + +=== %{length: ... } + +The `length` expansion returns the size of the input as an integer. +When the input is a string, then the output is identical to the +`strlen` expansion. + +When the input is an attribute reference, the output is the size of +the attributes data as encoded "on the wire". + +.Return: _size_ + +.Determining the length of fixed and variable length attributes +==== +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" + &Framed-IP-Address := 192.0.2.1 +} + +update reply { + &Reply-Message := "The length of %{control:Tmp-String-0} is %{length:&control:Tmp-String-0}" + &Reply-Message += "The length of %{control:Framed-IP-Address} is %{length:&control:Framed-IP-Address}" +} +---- + +.Output +.... +The length of Caipirinha is 10 +The length of 192.168.0.2 is 4 +.... +==== + +`length` is built in to the server core. + + + +=== %{integer:<&ref>} + +Print the value of the attribute an integer. + +In normal operation, `integer` attributes are printed using the name +given by a `VALUE` statement in a dictionary. Similarly, date +attributes are printed as dates, i.e., "January 1 2010. + +The `integer` expansion applies only to attributes which can be +converted to an integer. For all other inputs, it returns `0`. + +A common usage is to find the difference between two dates. + +For example, if a request contains `Service-Type = Login-User`, the +expansion of `%{integer:&Service-Type}` will yield `1`, which is the +value associated with the `Login-User` name. Using +`%{integer:&Event-Timestamp}` will return the event timestamp as an +unsigned 32-bit number. + +.Return: _string_ + +.Determining the integer value of an enumerated attribute +==== +[source,unlang] +---- +update { + &control:Service-Type := Login-User +} +update reply { + &Reply-Message := "The value of Service-Type is %{integer:&control:Service-Type}" +} +---- + +.Output + +``` +The value of Service-Type is 1 +``` +==== + +`integer` is built in to the server core. + + + +=== %{rand:<number>} + +Generate random number from `0` to `<number>-1`. + +.Return: _uint64_ + +.Generating a random number between 0 and 511 +==== +[source,unlang] +---- +update reply { + &Reply-Message := "The random number is %{rand:512}" +} +---- + +.Output + +``` +The random number is 347 +``` +==== + +`rand` is provided by the `rlm_expr` module. + + + +=== %{tag:<attribute ref>} + +CAUTION: This expansion is deprecated and will likely be removed. + +Returns a list of tags for any attributes found using ``<attribute ref>``. + +.Return: _int8_ + +.Determining the tag value of the second instance of the `radius.Tunnel-Server-Endpoint` attribute +==== +[source,unlang] +---- +update request { + &Tunnel-Server-Endpoint := '192.0.1.1' + &Tunnel-Server-Endpoint:1 := '192.0.5.2' + &Tunnel-Server-Endpoint:1 += '192.0.3.8' + &Tunnel-Server-Endpoint:2 := '192.0.2.1' + &Tunnel-Server-Endpoint:2 += '192.0.3.4' +} + +update reply { + &Reply-Message := "The tag value of the second instance of Tunnel-Server-Enpoint is %{request:Tunnel-Server-Endpoint[1]}" +} +---- + +.Output + +``` +The tag value of the second instance of Tunnel-Server-Enpoint is 192.0.5.2 +``` +==== + +`tag` is built in to the server core. + + + +=== %{string:<data>} + +Convert input to a string (if possible). For _octets_ type attributes, this +means interpreting the data as a UTF8 string, and inserting octal escape +sequences where appropriate. + +For other types, this means printing the value in its _presentation_ format, +i.e. dotted quads for IPv4 addresses, link:https://en.wikipedia.org/wiki/ISO_8601[ISO 8601] +time for date types, enumeration values for attributes such as `radius.Service-Type` etc. + +.Return: _string_ + +.String interpolation using the raw octets value of Tmp-Octets-0, and the stringified version +==== +[source,unlang] +---- +update control { + &Tmp-Octets-0 := 0x7465737431 +} +update reply { + &Reply-Message := "The string value of %{control:Tmp-Octets-0} is %{string:%{control:Tmp-Octets-0}}" +} +---- +==== + +.Output + +``` +The string value of 0x7465737431 is test1 +``` + +`string` is built in to the server core. + + + +== Server Manipulation + +=== %{config:<key>} + +Refers to a variable in the configuration file. See the documentation +on configuration file references. + +.Return: _string_ + +.Example + +[source,unlang] +---- +"Server installed in %{config:prefix}" +"Module rlm_exec.shell_escape = %{config:modules.exec.shell_escape}" +---- + +.Output + +``` +Server installed in /opt/freeradius +Module rlm_exec.shell_escape = yes +``` + +`config` is built in to the server core. + + + +=== %{client:<key>} + +Refers to a variable that was defined in the client section for the +current client. See the sections `client { ... }` in `clients.conf`. + +.Return: _string_ + +.Example + +[source,unlang] +---- +"The client ipaddr is %{client:ipaddr}" +---- + +.Output + +``` +The client ipaddr is 192.168.5.9 +``` + +`client` is built in to the server core. + + + +=== %{debug:<level>} + +Dynamically change the debug level to something high, recording the old level. + +.Return: _string_ + +.Example + +[source,unlang] +---- +authorize { + if (&request:User-Name == "bob") { + "%{debug:4}" + } else { + "%{debug:0}" + } + ... +} +---- + +.Output (_extra informations only for that condition_) + +``` +... +(0) authorize { +(0) if (&request:User-Name == "bob") { +(0) EXPAND %{debug:4} +(0) --> 2 +(0) } # if (&request:User-Name == "bob") (...) +(0) filter_username { +(0) if (&State) { +(0) ... +(0) } +... +``` + +`debug` is built in to the server core. + + + +=== %{debug_attr:<list:[index]>} + +Print to debug output all instances of current attribute, or all attributes in a list. +expands to a zero-length string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +authorize { + if (&request:User-Name == "bob") { + "%{debug_attr:request[*]}" + } + ... +} +---- + +.Output + +``` +... +(0) authorize { +(0) if (&request:User-Name == "bob") { +(0) Attributes matching "request[*]" +(0) &request:User-Name = bob +(0) &request:User-Password = hello +(0) &request:NAS-IP-Address = 127.0.1.1 +(0) &request:NAS-Port = 1 +(0) &request:Message-Authenticator = 0x9210ee447a9f4c522f5300eb8fc15e14 +(0) EXPAND %{debug_attr:request[*]} +(0) } # if (&request:User-Name == "bob") (...) +... +``` + +`debug_attr` is built in to the server core. + + + +== String manipulation + +=== %{lpad:<&ref> <val> <char>} + +Left-pad a string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "123" +} +update reply { + &Reply-Message := "Maximum should be %{lpad:&control:Tmp-String-0 11 0}" +} +---- + +.Output + +``` +Maximum should be 00000000123 +``` + +`lpad` is provided by the `rlm_expr` module. + + + +=== %{rpad:<&ref> <val> <char>} + +Right-pad a string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "123" +} +update reply { + &Reply-Message := "Maximum should be %{rpad:&control:Tmp-String-0 11 0}" +} +---- + +.Output + +``` +Maximum should be 12300000000 +``` + +`rpad` is provided by the `rlm_expr` module. + + + +=== %{pairs:<&list:[*]>} + +Serialize attributes as comma-delimited string. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "This is a string" + &control:Tmp-String-0 += "This is another one" +} + +update reply { + &Reply-Message := "Serialize output: %{pairs:&control[*]}" +} +---- + +.Output + +``` +Serialize output: Tmp-String-0 = \"This is a string\"Tmp-String-0 = \"This is another one\" +``` + +`pairs` is provided by the `rlm_expr` module. + + + +=== %{randstr: ...} + +Get random string built from character classes. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update reply { + &Reply-Message := "The random string output is %{randstr:aaaaaaaa}" +} +---- + +.Output + +``` +The random string output is 4Uq0gPyG +``` + +`randstr` is provided by the `rlm_expr` module. + + + +=== %{strlen: ... } + +Length of given string. + +.Return: _integer_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" +} +update reply { + &Reply-Message := "The length of %{control:Tmp-String-0} is %{strlen:&control:Tmp-String-0}" +} +---- + +.Output + +``` +The length of Caipirinha is 21 +``` + +`strlen` is built in to the server core. + + + +=== %{tolower: ... } + +Dynamically expands the string and returns the lowercase version of +it. This definition is only available in version 2.1.10 and later. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "CAIPIRINHA" +} +update reply { + &Reply-Message := "tolower of %{control:Tmp-String-0} is %{tolower:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +tolower of CAIPIRINHA is caipirinha +``` + +`tolower` is provided by the `rlm_expr` module. + + + +=== %{toupper: ... } + +Dynamically expands the string and returns the uppercase version of +it. This definition is only available in version 2.1.10 and later. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "caipirinha" +} +update reply { + &Reply-Message := "toupper of %{control:Tmp-String-0} is %{toupper:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +toupper of caipirinha is CAIPIRINHA +``` + +`toupper` is provided by the `rlm_expr` module. + + + +== String Conversion + +=== %{base64: ... } + +Encode a string using Base64. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" +} +update reply { + &Reply-Message := "The base64 of %{control:Tmp-String-0} is %{base64:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The base64 of foo is Q2FpcGlyaW5oYQ== +``` + +`base64` is provided by the `rlm_expr` module. + + + +=== %{base64tohex: ... } + +Decode a base64 string (e.g. previously encoded using `base64`) to +hex. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Q2FpcGlyaW5oYQ==" +} +update reply { + &Reply-Message := "The base64tohex of %{control:Tmp-String-0} is %{base64tohex:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The base64decode of Q2FpcGlyaW5oYQ== is 436169706972696e6861 +``` + +`base64tohex` is provided by the `rlm_expr` module. + + + +=== %{hex: ... } + +Convert to hex. + +.Return: _string_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "12345" +} +update reply { + &Reply-Message := "The value of %{control:Tmp-String-0} in hex is %{hex:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The value of 12345 in hex is 3132333435 +``` + +`hex` is built in to the server core. + + + +=== %{urlquote: ... } + +Quote URL special characters. + +.Return: _string_. + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "http://example.org/" +} +update reply { + &Reply-Message += "The urlquote of %{control:Tmp-String-0} is %{urlquote:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The urlquote of http://example.org/ is http%3A%2F%2Fexample.org%2F +``` + +`urlquote` is provided by the `rlm_expr` module. + + + +=== %{urlunquote: ... } + +Unquote URL special characters. + +.Return: _string_. + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "http%%3A%%2F%%2Fexample.org%%2F" # Attention for the double %. +} +update reply { + &Reply-Message += "The urlunquote of %{control:Tmp-String-0} is %{urlunquote:%{control:Tmp-String-0}}" +} +---- + +.Output + +``` +The urlunquote of http%3A%2F%2Fexample.org%2F is http://example.org/ +``` + +`urlunquote` is provided by the `rlm_expr` module. + + + +== Hashing and Encryption + +=== %{hmacmd5:<shared_key> <string>} + +Generate `HMAC-MD5` of string. + +.Return: _octal_ + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "mykey" + &control:Tmp-String-1 := "Caipirinha" +} +update { + &control:Tmp-Octets-0 := "%{hmacmd5:%{control:Tmp-String-0} %{control:Tmp-String-1}}" +} + +update reply { + &Reply-Message := "The HMAC-MD5 of %{control:Tmp-String-1} in octets is %{control:Tmp-Octets-0}" + &Reply-Message += "The HMAC-MD5 of %{control:Tmp-String-1} in hex is %{hex:control:Tmp-Octets-0}" +} +---- + +.Output + +``` +The HMAC-MD5 of Caipirinha in octets is \317}\264@K\216\371\035\304\367\202,c\376\341\203 +The HMAC-MD5 of Caipirinha in hex is 636f6e74726f6c3a546d702d4f63746574732d30 +``` + +`hmacmd5` is provided by the `rlm_expr` module. + + + +=== %{hmacsha1:<shared_key> <string>} + +Generate `HMAC-SHA1` of string. + +.Return: _octal_ + +.Example + +[source,unlang] +---- +update { + &control:Tmp-String-0 := "mykey" + &control:Tmp-String-1 := "Caipirinha" +} +update { + &control:Tmp-Octets-0 := "%{hmacsha1:%{control:Tmp-String-0} %{control:Tmp-String-1}}" +} + +update reply { + &Reply-Message := "The HMAC-SHA1 of %{control:Tmp-String-1} in octets is %{control:Tmp-Octets-0}" + &Reply-Message += "The HMAC-SHA1 of %{control:Tmp-String-1} in hex is %{hex:control:Tmp-Octets-0}" +} +---- + +.Output + +``` +The HMAC-SHA1 of Caipirinha in octets is \311\007\212\234j\355\207\035\225\256\372ʙ>R\"\341\351O) +The HMAC-SHA1 of Caipirinha in hex is 636f6e74726f6c3a546d702d4f63746574732d30 +``` + +`hmacsha1` is provided by the `rlm_expr` module. + + + +=== %{md5: ... } + +Dynamically expands the string and performs an MD5 hash on it. The +result is binary data. + +.Return: _binary data_ + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "Caipirinha" +} +update reply { + &Reply-Message := "md5 of %{control:Tmp-String-0} is octal=%{md5:%{control:Tmp-String-0}}" + &Reply-Message := "md5 of %{control:Tmp-String-0} is hex=%{hex:%{md5:%{control:Tmp-String-0}}}" +} +---- + +.Output + +``` +md5 of Caipirinha is octal=\024\204\013md||\230\243\3472\3703\330n\251 +md5 of Caipirinha is hex=14840b6d647c7c98a3e732f833d86ea9 +``` + +`md5` is provided by the `rlm_expr` module. + + + +== Miscellaneous Expansions + +=== +%{0}+..+%{32}+ + +`%{0}` expands to the portion of the subject that matched the last regular +expression evaluated. `%{1}`..`%{32}` expand to the contents of any capture +groups in the pattern. + +Every time a regular expression is evaluated, whether it matches or not, +the numbered capture group values will be cleared. + + + +=== +%{regex:<named capture group>}+ + +Return named subcapture value from the last regular expression evaluated. + +Results of named capture groups are available using the `%{regex:<named capture +group>}` expansion. They will also be accessible using the numbered expansions +described xref:builtin.adoc#_0_32[above]. + +Every time a regular expression is evaluated, whether it matches or not, +the named capture group values will be cleared. + +[NOTE] +==== +This expansion is only available if the server is built with libpcre or libpcre2. +Use the output of `radiusd -Xxv` to determine which regular expression library in use. + +.... +... +Debug : regex-pcre : no +Debug : regex-pcre2 : yes +Debug : regex-posix : no +Debug : regex-posix-extended : no +Debug : regex-binsafe : yes +... +Debug : pcre2 : 10.33 (2019-04-16) - retrieved at build time +.... +==== + +`regex` is built in to the server core. + + + +=== +%{nexttime:<time>}+ + +Calculate number of seconds until next n hour(`s`), day(`s`), week(`s`), year(`s`). + +.Return: _string_ + +.Example: + +With the current time at 16:18, `%{nexttime:1h}` will expand to `2520`. + +[source,unlang] +---- +update reply { + &Reply-Message := "You should wait for %{nexttime:1h}s" +} +---- + +.Output + +``` +You should wait for 2520s +``` + +`nexttime` is provided by the `rlm_expr` module. + + + +=== +%{Packet-Type}+ + +The packet type (`Access-Request`, etc.) + + + +=== +%{Packet-Src-IP-Address} and %{Packet-Src-IPv6-Address}+ + +The source IPv4 or IPv6 address of the packet. See also the expansions +`%{client:ipaddr}` and `%{client:ipv6addr}`. The two expansions +should be identical, unless `%{client:ipaddr}` contains a DNS hostname. + + + +=== +%{Packet-Dst-IP-Address} and %{Packet-Dst-IPv6-Address}+ + +The destination IPv4 or IPv6 address of the packet. See also the +expansions `%{listen:ipaddr}` and `%{listen:ipv6addr}`. If the socket +is listening on a "wildcard" address, then these two expansions will be +different, as follows: the `%{listen:ipaddr}` will be the wildcard +address and `%{Packet-DST-IP-Address}` will be the unicast address to +which the packet was sent. + + + +=== +%{Packet-Src-Port} and %{Packet-Dst-Port}+ + +The source/destination ports associated with the packet. + +.Return: _string_. + +.Example + +[source,unlang] +---- +update control { + &Tmp-String-0 := "user@example.com" +} + +if (&control:Tmp-String-0 =~ /^(?<login>(.*))@(?<domain>(.*))$/) { + update reply { + &Reply-Message := "The %{control:Tmp-String-0} { login=%{regex:login}, domain=%{regex:domain} }" + } +} +---- + +.Output + +``` +The user@example.com { login=user, domain=example.com } +``` + +// Copyright (C) 2020 Network RADIUS SAS. Licenced under CC-by-NC 4.0. +// Development of this documentation was sponsored by Network RADIUS SAS. |