**** xref:raddb/sites-available/doc/tacacs.adoc[TACACS+]
***** xref:raddb/sites-available/tacacs.adoc[Virtual Server]
**** xref:raddb/sites-available/tls.adoc[TLS]
-***** xref:raddb/sites-available/tls-cache.adoc[TLS Cache]
**** xref:raddb/sites-available/vmps.adoc[VMPS]
**** xref:raddb/sites-available/dynamic-clients.adoc[Dynamic Clients]
The solution instead is to use `:=` when referring to structural attributes by name, or instead using the name of a leaf attribute (e.g. `Vendor-Specific.Cisco.AVPair`), and then using `+=` on the leaf.
-In most situations, the simplest approach for structural data types is to just create the leaf attributes. e.g. `&foo.bar.baz := 5`. If any parent attribute is missing, it will be automatically created. That is, operations on leaf types will just "do the right thing" most of the time, so there is no need to explicitly refer to a structural data type by name.
+In most situations, the simplest approach for structural data types is to just create the leaf attributes. e.g. `foo.bar.baz := 5`. If any parent attribute is missing, it will be automatically created. That is, operations on leaf types will just "do the right thing" most of the time, so there is no need to explicitly refer to a structural data type by name.
There are some situations where it is useful to refer to structural attributes by name, as given in the examples below.
.Copying a Structural Attribute by Name
----
bob Password.Cleartext := "hello"
- Vendor-Specific.Cisco := &control.Vendor-Specific.Cisco
+ Vendor-Specific.Cisco := control.Vendor-Specific.Cisco
----
-This example copies the `Vendor-Specific.Cisco` group from the `&control` list. If the attribute does not exist in the control list, nothing is done.
+This example copies the `Vendor-Specific.Cisco` group from the `control` list. If the attribute does not exist in the control list, nothing is done.
Structural attributes can be created from a string, as with the xref:reference:unlang/edit.adoc[edit] functionality. Note that the string should not contain brackets such as `"{ AVPair = 'hello' }"`.
=== Item Values
-The values for items can be a simple value such as `192.0.2.1`, an xref:reference:xlat/index.adoc[xlat] string to expand such as `"Hello %{User-Name}"`, or an xref:reference:unlang/attr.adoc[attribute reference] such as `&request.Filter-Id`.
+The values for items can be a simple value such as `192.0.2.1`, an xref:reference:xlat/index.adoc[xlat] string to expand such as `"Hello %{User-Name}"`, or an xref:reference:unlang/attr.adoc[attribute reference] such as `request.Filter-Id`.
-The attribute references should have an `&` prefix, to more clearly separate them from enumeration values such as `Service-Type := Framed-User`.
+The attribute references don't require an `&` prefix, to more clearly separate them from enumeration values such as `Service-Type := Framed-User`.
References can be to an attribute which has a different data type than the attribute named on the left-hand side of the check item or reply item. In which case the values will be automatically cast to the correct type, as documented in the xref:reference:unlang/condition/cmp.adoc[conditional comparison] and xref:reference:unlang/edit.adoc[edit] pages.
#
bob NAS-IP-Address == 192.0.2.1, Password.Cleartext := "hello"
Reply-Message := "Hello %{User-Name}",
- Framed-IP-Address := &request.Framed-IP-Address
+ Framed-IP-Address := request.Framed-IP-Address
----
// Copyright (C) 2023 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
* xref:raddb/sites-available/status.adoc[status]
* xref:raddb/sites-available/tacacs.adoc[tacacs]
* xref:raddb/sites-available/tls.adoc[tls]
-* xref:raddb/sites-available/tls-cache.adoc[tls cache]
* xref:raddb/sites-available/virtual.example.com.adoc[virtual example com]
* xref:raddb/sites-available/vmps.adoc[vmps]
+++ /dev/null
-```
-server proxy {
- namespace = radius
-
- listen {
- type = Access-Request
-
- transport = udp
-
- udp {
- ipaddr = *
- port = 2812
- }
- }
-
-```
-
-## Packet Processing sections
-
-The sections below are called when a RADIUS packet has been
-received.
-
- * recv Access-Request - for authorization and authentication
- * recv Status-Server - for checking the server is responding
-
-
-
-### Receive Access-Request packets
-
-```
-recv Access-Request {
- update control {
- &Auth-Type := proxy
- }
-}
-
-authenticate proxy {
- radius
-}
-
-}
-```
-
-== Default Configuration
-
-```
-```
-
-// Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
-// This documentation was developed by Network RADIUS SAS.
+++ /dev/null
-
-This virtual server controls caching of TLS sessions.
-
-When a TLS session is used, the server will automatically create
-the following attributes in the session-state list. These attributes
-are the ones for the *server* certificate.
-
-
-If a client certificate is required (e.g. EAP-TLS or sometimes PEAP / TTLS),
-the following attributes are also created in the session-state list:
-
-
-
-
-
-
-This section can be run to verify a client certificate if
-additional checks need to be performed beyond standard
-checks verification against a trust chain, CRLs and OCSP.
-
-Attributes extracted from the certificates forming the
-client certificate chain will be in the session state list.
-
-Returning 'ok', 'updated' or 'noop' will cause the verification
-to succeed. Other return codes will cause the verification
-to fail.
-
-
-
-This section is run whenever the server needs to read an
-entry from the TLS session cache.
-
-It should read the attribute &session-state.TLS-Session-Data
-from the cache, along with any other attributes which
-were in the cache
-
-On success it should return 'ok' or 'updated'.
-
-The return code has no real effect on session processing
-and will just cause the server to emit a warning.
-
-
-
-
-This section is run whenever the server needs to write an
-entry to the TLS session cache.
-
-It should write the attribute &session-state.Session-Data
-to the cache, along with any other attributes which
-need to be cached.
-
-On success it should return 'ok' or 'updated'.
-
-The return code has no real effect on session processing
-and will just cause the server to emit a warning.
-
-
-
-
-This section is run whenever the server needs to delete an
-entry from the TLS session cache.
-
-On success it should return 'ok', 'updated', 'noop' or 'notfound'
-
-The return code has no real effect on session processing
-and will just cause the server to emit a warning.
-
-
-
-
-This section is run after certificate attributes are added
-to the request list, and before performing OCSP validation.
-
-It should read the attribute &control.TLS-OCSP-Cert-Valid
-from the cache.
-
-On success it should return 'ok', 'updated', 'noop' or 'notfound'
-To force OCSP validation failure, it should return 'reject'.
-
-
-
-
-This section is run after OCSP validation has completed.
-
-It should write the attribute &reply.TLS-OCSP-Cert-Valid
-to the cache.
-
-On success it should return 'ok' or 'updated'.
-
-The return code has no real effect on session processing
-and will just cause the server to emit a warning.
-
-
-
-== Default Configuration
-
-```
-# TLS-Cert-Serial
-# TLS-Cert-Expiration
-# TLS-Cert-Subject
-# TLS-Cert-Issuer
-# TLS-Cert-Common-Name
-# TLS-Cert-Subject-Alt-Name-Email
-# TLS-Client-Cert-Serial
-# TLS-Client-Cert-Expiration
-# TLS-Client-Cert-Subject
-# TLS-Client-Cert-Issuer
-# TLS-Client-Cert-Common-Name
-# TLS-Client-Cert-Subject-Alt-Name-Email
-server tls-cache {
- namespace = tls
- verify certificate {
- ok
- }
- load session {
- &control.Cache-Allow-Insert := no
- cache_tls_session
- }
- store session {
- &control.Cache-TTL := 0
- cache_tls_session
- }
- clear session {
- &control.Cache-TTL := 0
- &control.Cache-Allow-Insert := no
- cache_tls_session
- }
- load ocsp-state {
- &control.Cache-Allow-Insert := no
- cache_ocsp
- }
- store ocsp-state {
- &control.Cache-TTL := "%{&reply.TLS-OCSP-Next-Update * -1}"
- &control.Cache-Allow-Merge := no
- cache_ocsp
- }
-}
-```
-
-// Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
-// This documentation was developed by Network RADIUS SAS.
-= &Attribute References
+= Attribute References
.Syntax
[source,unlang]
foo = 2
-EAP-Message[&foo]
+EAP-Message[foo]
----
The `<index>` can also be an expression which is calculated at run time. The expression _must_ not cause the server to call an external database, script, etc. The main purpose of these expressions is to calculated an index without first placing it into another attribute.
subrequest and recursively calling the DHCPv6 virtual server.
[source,unlang]
----
-subrequest &Packet-Type &Relay-Message reply.Relay-Message {
+subrequest Packet-Type Relay-Message reply.Relay-Message {
call dhcpv6 {}
}
----
.Examples
[source,unlang]
----
-if (User-Name && &EAP-Message) { ...
+if (User-Name && EAP-Message) { ...
----
// Copyright (C) 2021 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
The most common use-case for conditions is to perform comparisons.
The `lhs` and `rhs` of a conditional comparison can be
-xref:unlang/attr.adoc[&Attribute-Name] or xref:type/index.adoc[data]. The
+xref:unlang/attr.adoc[Attribute-Name] or xref:type/index.adoc[data]. The
the `OP` is an operator, commonly `==` or `\<=`. It is used to
control how the two other portions of the condition are compared.
[options="header"]
|=====
| Syntax | Description
-| xref:unlang/attr.adoc[&Attribute-Name] | Check for attribute existence.
+| xref:unlang/attr.adoc[Attribute-Name] | Check for attribute existence.
| xref:unlang/return_codes.adoc[rcode] | Check return code of a previous module.
| xref:unlang/condition/operands.adoc[data] | Check value of data.
| xref:unlang/condition/cmp.adoc[lhs OP rhs] | Compare two kinds of data.
`back-quoted string`
----
-Any text not matching xref:unlang/attr.adoc[&Attribute-Name] or a
+Any text not matching xref:unlang/attr.adoc[Attribute-Name] or a
xref:unlang/condition/return_codes.adoc[return code] is interpreted as a value for a
particular xref:type/index.adoc[data type].
of the left side of the comparison. That is, if the left side is an
xref:type/numb.adoc[integer], the regular expression will behave as if the
value `0` was the literal string `"0"`. Similarly, if the left side is an
-xref:unlang/attr.adoc[&Attribute-Name], then the regular expression will behave
+xref:unlang/attr.adoc[Attribute-Name], then the regular expression will behave
as if the attribute was printed to a string, and the match was performed on the
resulting string.
attribute -= <expression>
...
-list1 := &list2
+list1 := list2
list1 += { attribute = value, ... }
list1 += " attribute = value, ... "
...
#
# Enforce it
#
- large <= &small
+ large <= small
- # &large now has value '10'
+ # large now has value '10'
}
----
.Example of Looping over children of a structural type.
[source,unlang]
----
-foreach string child (&TLV-Thing.[*]) {
- out += &child
+foreach string child (TLV-Thing.[*]) {
+ out += child
out += " "
}
----
[source,unlang]
----
foreach thing (Tmp-TLV-0[*]) {
- out += &thing.c
+ out += thing.c
out += " "
}
----
uint32 len
# this test ALWAYS fails, as "len" has not been assigned a value
- if (&len) {
+ if (len) {
...
}
----
A `switch` statement causes the server to evaluate _<expansion>_,
-which can be an xref:unlang/attr.adoc[&Attribute-Name] or
+which can be an xref:unlang/attr.adoc[Attribute-Name] or
xref:unlang/condition/operands.adoc[data]. The result is compared against
_<match-1>_ and _<match-2>_, etc. in order to find a match. If no
match is found, then the server looks for the `default`
.Switch over IP prefixes
[source,unlang]
----
-switch &Framed-IP-Address {
+switch Framed-IP-Address {
case 192.168/16 {
accept
}
[source,unlang]
----
-reply.Class := (octets) &Framed-IP-Address + (octets) NAS-IP-Address.
+reply.Class := (octets) Framed-IP-Address + (octets) NAS-IP-Address.
----
== %string(...)
[source,unlang]
----
recv Access-Request {
- if (&request.User-Name == "bob") {
+ if (request.User-Name == "bob") {
"%debug(4)"
} else {
"%debug(0)"
```
...
(0) recv Access-Request {
-(0) if (&request.User-Name == "bob") {
+(0) if (request.User-Name == "bob") {
(0) EXPAND %debug(4)
(0) --> 2
-(0) } # if (&request.User-Name == "bob") (...)
+(0) } # if (request.User-Name == "bob") (...)
(0) filter_username {
-(0) if (&State) {
+(0) if (State) {
(0) ...
(0) }
...
[source,unlang]
----
recv Access-Request {
- if (&request.User-Name == "bob") {
+ if (request.User-Name == "bob") {
"%debug_attr(request[*])"
}
...
```
...
(0) recv Access-Request {
-(0) if (&request.User-Name == "bob") {
+(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) 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") (...)
+(0) } # if (request.User-Name == "bob") (...)
...
```