]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
remove much alternation
authorAlan T. DeKok <aland@freeradius.org>
Fri, 6 Oct 2023 11:45:59 +0000 (07:45 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 6 Oct 2023 11:48:14 +0000 (07:48 -0400)
perl -p -i -e 's/%{%{([^%{}]+)}:-%{([^%{}]+)}}/%{\&$1 || \&$2}/g'  $(git grep -l ':-' raddb/)

and then re-build the antora docs from the raddb sources

46 files changed:
doc/antora/modules/raddb/pages/mods-available/cache_eap.adoc
doc/antora/modules/raddb/pages/mods-available/couchbase.adoc
doc/antora/modules/raddb/pages/mods-available/delay.adoc
doc/antora/modules/raddb/pages/mods-available/files.adoc
doc/antora/modules/raddb/pages/mods-available/ldap.adoc
doc/antora/modules/raddb/pages/mods-available/linelog.adoc
doc/antora/modules/raddb/pages/mods-available/mschap.adoc
doc/antora/modules/raddb/pages/mods-available/radutmp.adoc
doc/antora/modules/raddb/pages/mods-available/redis.adoc
doc/antora/modules/raddb/pages/mods-available/redis_ippool.adoc
doc/antora/modules/raddb/pages/mods-available/rediswho.adoc
doc/antora/modules/raddb/pages/mods-available/redundant_sql.adoc
doc/antora/modules/raddb/pages/mods-available/rest.adoc
doc/antora/modules/raddb/pages/mods-available/sql.adoc
doc/antora/modules/raddb/pages/mods-available/sqlcounter.adoc
doc/antora/modules/raddb/pages/mods-available/sqlippool.adoc
doc/antora/modules/raddb/pages/mods-available/winbind.adoc
doc/antora/modules/raddb/pages/sites-available/abfab-tls.adoc
doc/antora/modules/raddb/pages/sites-available/challenge.adoc
doc/antora/modules/raddb/pages/sites-available/coa-relay.adoc
doc/antora/modules/raddb/pages/sites-available/copy-acct-to-home-server.adoc
doc/antora/modules/raddb/pages/sites-available/default.adoc
doc/antora/modules/raddb/pages/sites-available/dhcp.adoc
doc/antora/modules/raddb/pages/sites-available/eap-aka-sim.adoc
doc/antora/modules/raddb/pages/sites-available/ldap_sync.adoc
doc/antora/modules/raddb/pages/sites-available/proxy-inner-tunnel.adoc
doc/antora/modules/raddb/pages/sites-available/resource-check.adoc
doc/antora/modules/raddb/pages/sites-available/robust-proxy-accounting.adoc
doc/antora/modules/raddb/pages/sites-available/vmps.adoc
raddb/mods-available/cache_eap
raddb/mods-available/couchbase
raddb/mods-available/files
raddb/mods-available/ldap
raddb/mods-available/linelog
raddb/mods-available/radutmp
raddb/mods-available/redis_ippool
raddb/mods-available/rediswho
raddb/mods-available/sqlcounter
raddb/mods-available/sqlippool
raddb/mods-available/winbind
raddb/mods-config/files/accounting
raddb/mods-config/sql/main/mysql/extras/wimax/queries.conf
raddb/mods-config/sql/main/postgresql/queries.conf
raddb/mods-config/sql/main/sqlite/queries.conf
raddb/policy.d/accounting
raddb/sites-available/dhcp

index 96ed97fe7f192d7acc8e5b955d816ac03219d07f..6d11bdaac8bf524843219b9ee4d078c249ad4873 100644 (file)
@@ -68,7 +68,7 @@ update <section> { ... }::
 
 ```
 cache cache_eap {
-       key = "%{%{control.State}:-%{%{reply.State}:-%{State}}}"
+       key = "%{&control.State || &reply.State || &State}"
        ttl = 15
        update reply {
                &reply += &reply
index 47d6f2207b29eb2e3e79548468de6f6206e306ba..1397d8867ff1e8f4992a730ed598bd9efce555b6 100644 (file)
@@ -191,7 +191,7 @@ couchbase {
 #              send_hello = "false"
 #              detailed_errcodes = "true"
        }
-       acct_key = "radacct_%{%{Acct-Unique-Session-Id}:-%{Acct-Session-Id}}"
+       acct_key = "radacct_%{&Acct-Unique-Session-Id || &Acct-Session-Id}"
        doctype = "radacct"
        expire = 2592000
        update {
@@ -222,7 +222,7 @@ couchbase {
                &Acct-Output-Gigawords  = 'outputGigawords'
                &Event-Timestamp        = 'lastUpdated'
        }
-       user_key = "raduser_%md5(%tolower(%{%{Stripped-User-Name}:-%{User-Name}}))"
+       user_key = "raduser_%md5(%tolower(%{&Stripped-User-Name || &User-Name}))"
 #      read_clients = no
        client {
                view = "_design/client/_view/by_id"
index 3f0983b040e1679bdca11e615f0ea2e80b4c6458..33b40441fa5b30cbb233dab4bb034532aa306abf 100644 (file)
@@ -73,7 +73,7 @@ received.
 
 ```
 delay {
-       delay = 1.0
+       delay = 1.0s
 #      force_reschedule = no
 #      relative = no
 }
index cb91d344a7430ee1022427e8c3fa03e04688e7c0..88b7677f30c58b341e81ef10ea550d114747d017 100644 (file)
@@ -6,7 +6,15 @@
 
 The `users` file as located in `raddb/mods-config/files/authorize`. (Livingston-style format).
 
-See "man 1 users" for more information.
+See `man 1 users` for more information.
+
+
+
+NOTE: Temporarily (2023-08-27), the check items only supports
+"real" attributes.  This limitation will be removed when the module
+is rewritten to support xlat expressions for conditions.
+
+The module also does not support xlat expansions on the RHS.
 
 
 
@@ -42,7 +50,7 @@ They will be renamed in a future release.
 ```
 files {
        moddir = ${modconfdir}/${.:instance}
-#      key = "%{%{Stripped-User-Name}:-%{User-Name}}"
+#      key = "%{&Stripped-User-Name || &User-Name}"
        filename = ${moddir}/authorize
 #      usersfile = ${moddir}/authorize
        acctusersfile = ${moddir}/accounting
index 209402481fb5b6cc6e1abf34c322572c63ad1793..ea2114715792320b6d5821b578819a53b73937eb 100644 (file)
@@ -825,8 +825,8 @@ ldap {
 #      edir_autz = no
        user {
                base_dn = "${..base_dn}"
-               filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
-#              filter = "(&(objectClass=user)(sAMAccountName=%{%{Stripped-User-Name}:-%{User-Name}})(memberOf:1.2.840.113556.1.4.1941:=cn=group,${..base_dn}))"
+               filter = "(uid=%{&Stripped-User-Name || &User-Name})"
+#              filter = "(&(objectClass=user)(sAMAccountName=%{&Stripped-User-Name || &User-Name})(memberOf:1.2.840.113556.1.4.1941:=cn=group,${..base_dn}))"
                sasl {
 #                      mech = 'PLAIN'
 #                      authname = &User-Name
@@ -846,7 +846,7 @@ ldap {
                filter = '(objectClass=posixGroup)'
 #              scope = 'sub'
 #              name_attribute = cn
-#              membership_filter = "(|(member=%{control.Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
+#              membership_filter = "(|(member=%{control.Ldap-UserDn})(memberUid=%{&Stripped-User-Name || &User-Name}))"
                membership_attribute = 'memberOf'
 #              cacheable_name = 'no'
 #              cacheable_dn = 'no'
index 297eb5c7c2df82f1e7dbbc7a89c786543c00b296..cdea40763bcdc3692b606ddd7365ade2cb365861 100644 (file)
@@ -72,6 +72,14 @@ Pairs may be attributes attribute reference `&User-Name` , `xlat`, `literal` or
 
 
 
+header:: Optional header line format for file output
+
+If the destination is "file" and header is set, then this
+is expanded and output as the first line when a new file
+is created.
+
+
+
 destination:: What should be done with log messages.
 
 May be one of:
@@ -129,13 +137,12 @@ a limited range should set this to `yes`.
 The connection pool for TCP and Unix socket connections.
 
 
-start::
+start:: Connections to create during module instantiation.
 
-Connections to create during module instantiation.
 If the server cannot create specified number of
 connections during instantiation it will exit.
-Set to 0 to allow the server to `start` without the
-web service being available.
+Set to `0` to allow the server to start without the
+external service being available.
 
 
 
@@ -148,13 +155,16 @@ max:: Maximum number of connections.
 If these connections are all in use and a new one
 is requested, the request will NOT get a connection.
 
-Setting `max` to LESS than the number of threads means
+Setting `max` to *LESS* than the number of threads means
 that some threads may starve, and you will see errors
-like 'No connections available and at `max` connection limit'
+like _No connections available and at max connection limit_.
 
 Setting `max` to MORE than the number of threads means
 that there are more connections than necessary.
 
+If `max` is not specified, then it defaults to the number
+of workers configured.
+
 
 
 spare:: Spare connections to be left idle.
@@ -346,6 +356,7 @@ linelog {
                Access-Reject = "Sent reject: %{User-Name}"
                Access-Challenge = "Sent challenge: %{User-Name}"
        }
+#      header = ""
        destination = file
        file {
                filename = ${logdir}/linelog
@@ -396,9 +407,9 @@ linelog log_accounting {
                Start = "Connect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address})"
                Stop = "Disconnect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address}) %{Acct-Session-Time} seconds"
                Interim-Update = ""
-               Accounting-On = "NAS %%{Net.Src.IP} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) just came online"
-               Accounting-Off = "NAS %{Net.Src.IP} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) just went offline"
-               unknown = "NAS %{Net.Src.IP} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) sent unknown Acct-Status-Type %{Acct-Status-Type}"
+               Accounting-On = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) just came online"
+               Accounting-Off = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) just went offline"
+               unknown = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) sent unknown Acct-Status-Type %{Acct-Status-Type}"
        }
 }
 ```
index 33d6681ee2a01e67fc2999997d5a70089db1e337..a72e8aee07980e19eb041c4c3dab0422ffded5ff 100644 (file)
@@ -306,6 +306,7 @@ TIP: We give both examples here, but *only one should be used*.
 
 
 
+
 use_open_directory::
 
 For Apple Server, when running on the same machine as Open Directory.
@@ -399,7 +400,7 @@ mschap {
 #      require_encryption = yes
 #      require_strong = yes
 #      with_ntdomain_hack = no
-#      ntlm_auth = "/path/to/ntlm_auth --request-nt-key  --allow-mschapv2 --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%mschap(Challenge):-00} --nt-response=%{%mschap(NT-Response):-00}"
+#      ntlm_auth = "/path/to/ntlm_auth --request-nt-key  --allow-mschapv2 --username=%{&Stripped-User-Name || &User-Name || 'None'} --challenge=%{%mschap(Challenge) || 00} --nt-response=%{%mschap(NT-Response) || 00}"
 #      ntlm_auth_timeout = 10
        winbind {
 #              username = "%mschap(User-Name)"
@@ -421,8 +422,8 @@ mschap {
 #              ntlm_auth = "/usr/bin/ntlm_auth --helper-protocol=ntlm-change-password-1"
 #              ntlm_auth_username = "username: %mschap(User-Name)"
 #              ntlm_auth_domain = "nt-domain: %mschap(NT-Domain)"
-#              local_cpw = "%exec(/path/to/script %mschap(User-Name) %{MS-CHAP-New-Password.Cleartext})"
-#              local_cpw = "%sql(UPDATE radcheck set value='%{MS-CHAP-New-NT-Password}' where username='%{User-Name}' and attribute='Password.NT'}"
+#              local_cpw = %exec('/path/to/script', %mschap(User-Name), %{MS-CHAP-New-Password.Cleartext})
+               local_cpw = %sql("UPDATE radcheck set value='%{MS-CHAP-New-NT-Password}' where username='%{User-Name}' and attribute='Password.NT'")
        }
 #      use_open_directory = yes
 #      allow_retry = yes
index cf06f2fbecd865317edc46928c5ed9fc665810eb..e54b1cfd9dc7a77e618d2ae5590b2be3415c9a4c 100644 (file)
@@ -32,7 +32,7 @@ However, that the size of the field in the `utmp` data
 structure is small, around `32` characters, so that will limit
 the possible choices of keys.
 
-TIP: You may want instead: `%{%{Stripped-User-Name}:-%{User-Name}}`.
+TIP: You may want instead: `%{&Stripped-User-Name || &User-Name}`.
 
 
 
index f8a3fef434af642cda0441f0a14589fadb3104b8..0ae3aeee747739f95beca8063c3937a6d9a18d9c 100644 (file)
@@ -5,7 +5,7 @@
 = REDIS Module
 
 The `redis` module handles connections to a redis database,
-and the `%{redis: ...}` dynamic expansion.
+and the `%redis( ...)` dynamic expansion.
 
 See also https://redis.io/documentation for documentation on the
 Redis database.
index 2aaefaa7b8e2199afe67b5e79f7a3bd1af6a45af..ea8cf64a4dba569f8526da4e50dc43b033a5ab72 100644 (file)
@@ -145,9 +145,9 @@ redis_ippool {
 #      wait_timeout = 2
 #      gateway = &NAS-Identifier
        owner = &Client-Hardware-Address
-#      owner = "%{%{Client-Identifier}:-%{Client-Hardware-Address}}"
+#      owner = "%{&Client-Identifier || &Client-Hardware-Address}"
 #      owner = "%{Vendor-Specific.ADSL-Forum.Agent-Circuit-ID} %{Calling-Station-Id}"
-       requested_address = "%{%{Requested-IP-Address}:-%{Net.Src.IP}}"
+       requested_address = "%{&Requested-IP-Address || &Net.Src.IP}"
 #      ipv4_integer = yes
        allocated_address_attr = &reply.Your-IP-Address
        range_attr = &reply.IP-Pool.Range
index 65d4db8d98cdc671c0ca4ae1fbcf85e83973a380..54e99fe7a89dfb44f04b88647cb10f5c71886f9e 100644 (file)
@@ -104,17 +104,17 @@ rediswho {
        trim_count = 15
        expire_time = 86400
        Start {
-               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
+               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{&NAS-IP-Address || &NAS-IPv6-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
                trim =   "LTRIM %{User-Name} 0 ${..trim_count}"
                expire = "EXPIRE %{User-Name} ${..expire_time}"
        }
        Interim-Update {
-               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
+               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{&NAS-IP-Address || &NAS-IPv6-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
                trim =   "LTRIM %{User-Name} 0 ${..trim_count}"
                expire = "EXPIRE %{User-Name} ${..expire_time}"
        }
        Stop {
-               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
+               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{&NAS-IP-Address || &NAS-IPv6-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
                trim =   "LTRIM %{User-Name} 0 ${..trim_count}"
                expire = "EXPIRE %{User-Name} ${..expire_time}"
        }
index 8e89970964a5b0449adaaa4edd2994b92e934a56..16e6c1a0669135cca527555f39d4ebb17458803c 100644 (file)
@@ -30,7 +30,7 @@ name of the `virtual` module.  In the example below,
 it will be `redundant_sql`.  You can then use this expansion
 just like any other:
 
-       &reply.Filter-Id := "%{redundant_sql: ... }"
+       &reply.Filter-Id := "%redundant_sql( ... )"
 
 In this example, the expansion is done via module `sql1`, and if
 that expansion fails, using module `sql2`.
index fda58b3d86fd4f439a160c03d4c38e9196bb1869..2d907e06f756e01ef1c489480554a06f5ab1815a 100644 (file)
@@ -186,7 +186,7 @@ The following config items may be listed in any of the sections:
 | `data`         | Send custom freeform data in the HTTP body. `Content-type`
                    may be specified with `body`. Will be expanded.
                    Values from expansion will not be escaped, this should be
-                   done using the appropriate `xlat` method e.g. `%{urlquote:<attr>}`
+                   done using the appropriate `xlat` method e.g. `%urlquote(<attr>)`
 | `force_to`     | Force the response to be decoded with this decoder.
                    May be 'plain' (creates reply.REST-HTTP-Body), 'post' or 'json'.
 | `tls`          | TLS settings for HTTPS.
index 6b2ae82381284a9fefe2e426d0f059397e6f68a0..95ebde6fe1b7063ad452d5b6a01c249db6968192 100644 (file)
@@ -25,6 +25,15 @@ oracle, postgresql, sqlite and unixodbc.
 
 
 
+NOTE: Temporarily (2023-08-27), the check items only support "real"
+attributes.  This limitation will be removed when the module is
+rewritten to support maps (for assignments) and xlat expressions
+(for conditions).
+
+The module also does not support xlat expansions on the RHS.
+
+
+
 ## Configuration Settings
 
 
@@ -296,7 +305,7 @@ groups to the `control` list.  The "group_attribute" can then be used to check g
 That check will be done internally, and will not result in a database lookup.  This also means that
 it is now possible to do group comparisons based on regular expressions.
 
-It is possible to force a dynamic group lookup via the expansion `%{sql.group:foo}`.  This
+It is possible to force a dynamic group lookup via the expansion `%sql.group(foo)`.  This
 expansion returns `true` if the user is a member of that SQL group, and `false` otherwise.
 
 NOTE: The `SQL-Group` attribute is only available after the SQL module has been run.
index beab166e2f63aed50810106ac8a5217bb35624ea..2805a90af6b6faa8912ef63280f06569305df428 100644 (file)
@@ -128,7 +128,7 @@ NOTE: You may need to edit `raddb/dictionary` to add the `Expire-After` attribut
 #      sqlcounter <name> {
 #      sql_module_instance = sql_foo
 #      reset = 12h
-#      key = "%{%{Stripped-User-Name}:-%{User-Name}}"
+#      key = "%{&Stripped-User-Name || &User-Name}"
 #      if (&control.Daily-Session-Time > 3600) {
 #               &Reply-Message := "You've used up more than one hour today"
 #               reject
@@ -141,7 +141,7 @@ sqlcounter dailycounter {
        counter_name = &control.Daily-Session-Time
        check_name = &control.Max-Daily-Session
        reply_name = &reply.Session-Timeout
-       key = "%{%{Stripped-User-Name}:-%{User-Name}}"
+       key = "%{&Stripped-User-Name || &User-Name}"
        reset = daily
        $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf
 }
index 91b29496396356d10950a7a23955702ea7b3d590..aaafd59fd5de3c29452c41db11c3b52e0154154d 100644 (file)
@@ -77,7 +77,7 @@ For DHCPv4 the owner will likely be specified by:
   * `%{dhcpv4.Client-Hardware-Address}` which binds the lease to the
   mac address of the user's device.
 
-  * `%{%{dhcpv4.Client-Identifier}:-%{dhcpv4.Client-Hardware-Address}}`
+  * `%{&dhcpv4.Client-Identifier || &dhcpv4.Client-Hardware-Address}`
   which binds the lease to either the custom identifier set by the
   DHCP client, or if this is absent, the mac address of the user's
   device.
@@ -109,7 +109,7 @@ requested_address:: The IP address being renewed or released.
 For RADIUS the requested_address will almost always be `%{radius.Framed-IP-Address}`.
 
 For DHCPv4 the requested_address will almost always be
-`%{%{dhcpv4.Requested-IP-Address}:-%{dhcpv4.Client-IP-Address}}`.
+`%{&dhcpv4.Requested-IP-Address || &dhcpv4.Client-IP-Address}`.
 
 
 
@@ -161,10 +161,10 @@ sqlippool {
        pool_name = IP-Pool.Name
        allocated_address_attr = radius.Framed-IP-Address
        owner = "%{radius.Calling-Station-ID}"
-#      owner = "%{%{dhcpv4.Client-Identifier}:-%{dhcpv4.Client-Hardware-Address}}"
+#      owner = "%{&dhcpv4.Client-Identifier || &dhcpv4.Client-Hardware-Address}"
        requested_address = "%{radius.Framed-IP-Address}"
-#      requested_address = "%{%{dhcpv4.Requested-IP-Address}:-%{dhcpv4.Client-IP-Address}}"
-       gateway = "%{%{radius.NAS-Identifier}:-%{radius.NAS-IP-Address}}"
+#      requested_address = "%{&dhcpv4.Requested-IP-Address || &dhcpv4.Client-IP-Address}"
+       gateway = "%{&radius.NAS-Identifier || &radius.NAS-IP-Address}"
        messages {
                exists = "Existing IP: %{reply.${..allocated_address_attr}} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
                success = "Allocated IP: %{reply.${..allocated_address_attr}} from %{control.IP-Pool.Name} (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
index 3aaf613e9942ba917afa3fd4ca714b3f11b45cee..7115ba0dd650b08bfcc3fdf8c4c866778e4c95fc 100644 (file)
@@ -151,10 +151,10 @@ increase lifetime/idle_timeout.
 
 ```
 winbind {
-       username = "%{%{Stripped-User-Name}:-%{User-Name}}"
+       username = "%{&Stripped-User-Name || &User-Name}"
 #      domain = ""
        group {
-               search_username = "%{%{Stripped-User-Name}:-%{User-Name}}"
+               search_username = "%{&Stripped-User-Name || &User-Name}"
 #              add_domain = yes
        }
        pool {
index e3ae8dee93ad72fabf3d9da8f2ae6a6e1de01a8a..9b80abbd173b17441bbc11bd10fbca42842a3ca6 100644 (file)
@@ -106,7 +106,7 @@ listen {
                require_client_cert = yes
                verify {
                }
-               psk_query = "%{psksql:select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'}"
+               psk_query = %psksql("select hex(key) from psk_keys where keyid = '%{TLS-PSK-Identity}'")
        }
        virtual_server = abfab-idp
        clients = radsec-abfab
index 5d4efac29d2dea5486ecef113c82423ae42aba08..d3223a84d94ee9086fd5d5223bd163355b4719e8 100644 (file)
@@ -6,6 +6,7 @@
 
 
 
+
 If there's no State attribute, then this is the request from
 the user.
 
@@ -40,13 +41,16 @@ Do PAP authentication with the password.
 #      to be "hello".  The server will send them a challenge
 #      consisting of a random number 0..9.  The user has to respond
 #      with that number.
-listen {
-       type = auth
-       ipaddr = *
-       port = 2000
-       virtual_server = challenge
-}
 server challenge {
+       namespace = radius
+       listen {
+               type = Access-Request
+               transport = udp
+               udp {
+                       ipaddr = *
+                       port = 2000
+               }
+       }
 recv Access-Request {
        if (!&State) {
                &control.Auth-Type := Step1
@@ -59,7 +63,7 @@ recv Access-Request {
 }
 authenticate step1 {
        pap
-       &session-state.Tmp-Integer-0 := "%{randstr:n}"
+       &session-state.Tmp-Integer-0 := "%randstr(n)"
        &reply.Reply-Message := &session-state.Tmp-Integer-0
        challenge
 }
index f05eab217f881762423ac81ef423f05e7ad9d93c..ba6942f055d9f52541ffd430c8f290058c1c141a 100644 (file)
@@ -158,7 +158,7 @@ Uncomment if the NAS does not expect User-Name
 Call the radius client module instance for the NAS-IP-Address
 
 
-Repeat this for each NAS
+Repeat this block for each NAS
 
 
 
@@ -168,7 +168,7 @@ Increment count of sent updates
 
 
 
-Likely a missing "case" if we can't map NAS-IP-Address to a module
+Likely a missing "case" block if we can't map NAS-IP-Address to a module
 
 
 
@@ -218,30 +218,30 @@ server coa {
                }
        }
        recv CoA-Request {
-#              &control.Tmp-String-0 := "%{sql:SELECT IFNULL(GROUP_CONCAT(CONCAT(nasipaddress,'#',acctsessionid) separator '|'),'') FROM (SELECT * FROM radacct WHERE ('%{User-Name}'='' OR UserName='%{User-Name}') AND ('%{Acct-Session-Id}'='' OR acctsessionid = '%{Acct-Session-Id}') AND AcctStopTime IS NULL) a}"
-#              &control.Tmp-String-0 := "%{sql:SELECT STRING_AGG(CONCAT(nasipaddress,'#',acctsessionid),'|') FROM (SELECT * FROM radacct WHERE ('%{User-Name}'='' OR UserName='%{User-Name}') AND ('%{Acct-Session-Id}'='' OR acctsessionid = '%{Acct-Session-Id}') AND AcctStopTime IS NULL) a}"
+#              &control.Tmp-String-0 := %sql("SELECT IFNULL(GROUP_CONCAT(CONCAT(nasipaddress,'#',acctsessionid) separator '|'),'') FROM (SELECT * FROM radacct WHERE ('%{User-Name}'='' OR UserName='%{User-Name}') AND ('%{Acct-Session-Id}'='' OR acctsessionid = '%{Acct-Session-Id}') AND AcctStopTime IS NULL) a")
+#              &control.Tmp-String-0 := %sql("SELECT STRING_AGG(CONCAT(nasipaddress,'#',acctsessionid),'|') FROM (SELECT * FROM radacct WHERE ('%{User-Name}'='' OR UserName='%{User-Name}') AND ('%{Acct-Session-Id}'='' OR acctsessionid = '%{Acct-Session-Id}') AND AcctStopTime IS NULL) a")
                &control.Tmp-Integer-0 := 0
-               if ("%(explode:&control.Tmp-String-0 |)") {
+               if ("%explode(&control.Tmp-String-0, '|')") {
                        foreach &control.Tmp-String-0 {
                                if ("%{Foreach-Variable-0}" =~ /([^#]*)#(.*)/) {
-                                       &control.Tmp-IP-Address-0 := "%{1}"
-                                       &control.Tmp-String-1 := "%{2}"
+                                       &control.NAS-IP-Address := "%{1}"
+                                       &control.Acct-Session-Id := "%{2}"
                                        subrequest CoA-Request {
                                                &request := &parent.request
-                                               &request.Acct-Session-Id := &parent.control.Tmp-String-1
+                                               &request.Acct-Session-Id := &parent.control.Acct-Session-Id
                                                &request.Event-Timestamp := "%l"
                                                &request.Message-Authenticator := 0x00
                                                &request -= &SQL-User-Name[*]
                                                &request -= &Acct-Delay-Time[*]
                                                &request -= &Proxy-State[*]
-                                               switch &parent.control.Tmp-IP-Address-0 {
+                                               switch &parent.control.NAS-IP-Address {
                                                        case "192.0.2.1" {
                                                                &parent.control.Tmp-Integer-0 += 1
                                                                radius-originate-coa-192.0.2.1
                                                        }
-                                                       case {
+                                                       default {
                                                                &parent.control += {
-                                                                       &Reply-Message = "Missing map for NAS: %{parent.control.Tmp-IP-Address-0}"
+                                                                       &Reply-Message = "Missing map for NAS: %{parent.control.NAS-IP-Address}"
                                                                }
                                                        }
                                                }  # subrequest
index 6445ad9784fd0bdf52baed1ca8acfe17d2da4ea1..4054f193d46785bef4f43aa59b103419db53add3 100644 (file)
@@ -1,3 +1,5 @@
+WARNING: This configuration file has not been updated for v4,
+          and therefore WILL NOT WORK.  Please do not use it.
 
 
 
index fa8a7b248f382e36150f36c572a19a7929fc872e..c3540f5b6b7ae232b984675326006e461a1a26d8 100644 (file)
@@ -1443,7 +1443,7 @@ send Access-Challenge {
 }
 send Access-Accept {
 #      if (!&reply.State) {
-#              &reply.State := "0x%{randstr:16h}"
+#              &reply.State := "0x%randstr(16h)"
 #      }
        &reply += &session-state
        eap
index 431e942795203de7b1eca0dd0c121246551983fa..9a8265df9ad68aa39c2d15f6cfda47acd10ac261 100644 (file)
@@ -313,7 +313,7 @@ recv Request {
 #      &control.IP-Pool.Name := "local"
 #      dhcp_sqlippool
        if (ok) {
-               &reply.Your-IP-Address := "%{%{request.Requested-IP-Address}:-%{request.Client-IP-Address}}"
+               &reply.Your-IP-Address := "%{&request.Requested-IP-Address || &request.Client-IP-Address}"
        }
 #      ok
 }
@@ -327,9 +327,9 @@ recv Inform {
        ok
 }
 #recv Inform {
-#      &reply.Packet-Dst-Port = 67
+#      &reply.Net.Dst.Port = 67
 #      &reply.Message-Type = Ack
-#      &reply.Server-Identifier = "%{Packet-Dst-IP-Address}"
+#      &reply.Server-Identifier = "%{Net.Dst.IP}"
 #      &reply.Site-specific-28 = 0x0a00
 #      ok
 #}
index 85a4bbea6c30f359ec041fda6ee2abf26678d3ec..f23085ef0834582edf1bae60606f15fee99a807b 100644 (file)
@@ -485,7 +485,7 @@ values:
 
 - The encrypt expansions of the `rlm_cipher` module.
 - The `%(3gpp_pseudonym_encrypt:)` expansion.
-- The `%{rand:}` expansion.
+- The `%randstr()` expansion.
 
 NOTE: Add a `&reply.Next-Pseudonym-Id` attribute in this section to
 avoid having the permanent Id of the SIM exposed during subsequent
@@ -581,7 +581,7 @@ The following rcodes have special meanings in this section:
 There's not much to do here as the majority of the work for
 session resumption is done in `load session { ... }`.
 
-Add a `&reply.Next-Pseudonym-Id` attribute in this section if you want
+Add a `&reply.Next-Pseudonym` attribute in this section if you want
 to allow avoid having the permanent Id of the SIM exposed during
 subsequent authentication attempts.
 
@@ -775,7 +775,7 @@ If when sending a Reauthentication-Request a `&reply.Next-Reauth-Id`
 attribute is found, this section will be called.
 
 You should restore the contents of the following attributes using
-`&session-state.Session-ID` or `&reply.Next-Reauth-Id` as a key:
+`&request.Session-ID` as a key:
 
 - `&session-state.Counter`::           How many times this session has
                        been resumed.
@@ -798,7 +798,7 @@ provide a unified session store.
 This section will be called prior to attempting re-authentication.
 
 You should restore the contents of the following attributes using
-`&session-state.Session-ID` or `&reply.Next-Reauth-Id` as a key:
+`&request.Session-ID` as a key:
 
 - `&session-state.Counter`::           How many times this session has
                        been resumed.
@@ -826,8 +826,7 @@ The following rcodes have special meanings in this section:
 
 This section we be called if authentication or re-authentication fails.
 
-You should remove any session information stored against
-`&Next-Reauth-Id`.
+You should remove any session information stored against `&request.Session-ID`.
 
 
 == Default Configuration
index e379699532949abe24133472ea5ee5c1d7039204..adcd184a02f575265c28c2336f3609812a0a4e26 100644 (file)
@@ -1,7 +1,9 @@
 
 Sample virtual server for receiving entries from an LDAP directory
 using the https://tools.ietf.org/html/rfc4533[RFC 4533] (LDAP Content Synchronization Operation) in
-refreshAndPersist mode.
+refreshAndPersist mode, Active Directory using its LDAP_SERVER_NOTIFY_OID
+server control, or a directory implementing Persistent Search as
+described in https://tools.ietf.org/id/draft-ietf-ldapext-psearch-03.txt
 
 
 Persistent searches work in a similar way to normal searches except
@@ -14,6 +16,79 @@ to be replicated by another LDAP server, here the primary use case is
 to receive notifications of changes to entries so we can disseminate that
 information or act on it.
 
+Note: Each of the three implementations of LDAP synchronisation behave
+differently:
+
+https://tools.ietf.org/html/rfc4533[RFC 4533]
+--------
+This provides a robust mechanism to allow clients to maintain a
+cached copy of a fragment of a directory by the use of cookies which
+can be returned to the server indicating the last successfully processed
+updates from the server.
+
+However, when an object is deleted from the directory, the entry which is
+received only contains the DN, or, if the deletion is reported as part of
+the initial refresh phase it may only be the UUID.
+
+Active Direcory
+---------------
+Active Directory will only provide updates from the time the query started;
+there is no mechanism to catch up on changes which occured while the
+client was not connected.  In addition it is not possible to apply a
+filter to the query so that only a subset of objects are considered.
+
+If notification is required when objects are deleted, then the Recycle Bin
+has to be enabled on Active Directory and a query must be running which
+includes the Deleted Objects container.
+
+Active Directory will only perform persistent searches if the filter is
+(objectClass=*).  To overcome this limitation, FreeRADIUS allows other
+LDAP filters to be specified which are applied in FreeRADIUS before passing
+packets to the relevant processing sections.
+
+This implementation of LDAP filters is not intended to be complete, but
+covers the most likely to be required.
+
+One key limitation, due to not having the LDAP schema to interpret attribute
+types, is that >=, <= and bitwise filters are assumed to be on integer values.
+
+If your Active Directory tree contains multiple domains, you will need a
+query for each domain that is of interest; running a query at the base
+of the tree with a scope of "sub" does not include any domains other than
+the base.
+
+Depending on the attributes of interest, the number of notifications of
+changes received can be reduced by running the LDAP query against the
+Global Catalog rather than the normal AD LDAP server.
+
+Persistent Search
+-----------------
+Servers implementing Persistent Search have the option to return the full
+directory contents, or simply start reporting changes from the point when
+the query was run.
+
+The draft says that servers SHOULD include a changeNumber when reporting
+changes to keep track of progress - however this has not been observed in
+any testing.  If this is implemented, then it can behave in a similar
+manner to the cookie defined in https://tools.ietf.org/html/rfc4533[RFC 4533]; a search against the change log
+with a filter of (changeNumber>=n) could be used to read changes since
+change number 'n'.
+
+
+Note on user group membership
+-----------------------------
+Many directories provide a virtual memberOf attribute which lists
+which groups a user is a member of.
+
+With the directories which have been tested, including OpenLDAP and
+Active Directory it has been observed that modifying group member lists
+does not result in notification of changes to the users, even though
+other modifications to the user will result in a notification which
+can include the memberOf attribute.
+
+Instead group membeship changes are reported as changes to the group object.
+
+
 Each virtual-server may have multiple listen sections, with each
 listen section containing multiple sync sections.
 
@@ -37,11 +112,10 @@ Port to connect on, defaults to 389, will be ignored for LDAP URIs.
 Administrator account for persistent search.
 If using SASL + KRB5 these should be commented out.
 
-How long to wait after failing to initialise a persistent search
-or after receiving malformed/unexpected messages from the LDAP server.
 
-How long to wait before reinitialising the connection if we become
-disconnected from the LDAP directory.
+timeouts may need to be longer than for normal LDAP queries
+if a refresh phase returns a lot of data.
+
 
 
 SASL parameters to use for binding as the sync user.
@@ -53,171 +127,389 @@ SASL authorisation identity to proxy.
 SASL realm. Used for kerberos.
 
 
+How big the kernel's receive buffer should be.
+
+
+
+Maximum number of updates to have outstanding
+When this number is reached, no more are read, potentially
+causing the receive buffer to fill which will cause the
+change notifications to queue up on the LDAP server
+
+
+
+When directories provide cookies to track progress through
+the list of changes, these can be provided on every update,
+which can be an excessive rate.
+
+FreeRADIUS keeps track of pending change and will only call
+store Cookie once the preceding changes have been processed.
+
+These options rate limit how often cookies will be stored.
+Provided all preceding changes have been processed, cookie Store
+will be called on a timed interval or after a number of changes
+have been completed, whichever occurs first.
+
+How often to store cookies.
+
+
+
+Number of completed changes which will prompt the storing
+of a cookie
+
+
+
 Persistent searches.
 
-You can configure an unlimited (within reason), number of syncs
-to retrieve entries from the LDAP directory.
+You can configure an unlimited (within reason, and any limitations
+of the directory you are querying), number of syncs to retrieve
+entries from the LDAP directory.
 
 Where to start searching in the tree for entries
 
+
 Only return entries matching this filter
 Comment this out if all entries should be returned.
 
+
 Search scope, may be 'base', 'one', 'sub' or 'children'
 
-Specify the list of attributes to return in entries,
-one config item per LDAP attribute.
 
-If no attr config items are specified, then all attributes
-will be returned.
+Specify a map of LDAP attributes to FreeRADIUS dictionary attributes.
+
+The result of this map determines how attriubtes from the LDAP
+query are presented in the requests processed by the various
+"recv" sections below.
+
+This is a very limited form of map:
+ - the left hand side must be an attribute reference.
+ - the right hand side is LDAP attributes which will be
+   included in the query.
+ - only = and += are valid operators with = setting a
+   single instance of the attriubte and += setting as
+   many as the LDAP query returns.
+
+Protocol specific attributes must be qualified e.g. &Proto.radius.User-Name
+
+
+
+
+Since there are likely to be multiple members of
+a given group, the += operator should be used when
+defining a mapping of LDAP attribute "member" to
+FreeRADIUS attributes.
+
+
+
+If you are querying Active Directory, you are likely to
+want two queries.
+
+It should be noted that Active Directory will only respond
+to queries with the LDAP_SERER_NOTIFICATION_OID control if
+the filter is (objectClass=*) - any other filter will result
+in an error.
+
+To overcome this limitation, a subset of LDAP filter handling
+has been implemented in FreeRADIUS allowing a filter to be
+specified in this configuration.  The key limitation is
+<=, >= and bitwise filters assume attributes are numeric.
+
+The only extensible match filters supported are the Active
+Directory bitwise AND and OR.
+
+A suitable filter, to only receive notificaitons regarding
+normal user accounts could be:
+
+  (userAccountControl:1.2.840.113556.1.4.803:=512)
+
+In addition, there is nothing returned by Active Directory to
+distinguish between an object being added or being modified.
+All LDAP entries which are returned are therefore processed
+through the recv Modify section when the directory is Active
+Directory.
+
+By default Active Directory puts a limit of 5 on the number
+of persistent searches which can be active on a connection.
+
+To determine if an object is enabled or disabled, the attribute
+userAccountControl can be evaluated.  This is returned as
+string data, so will want mapping to an integer attribute
+for processing.
+
+Firstly, one based on a naming context which covers all
+user objects.  This will return results when objects are
+added, modified or restored from the Deleted Objects
+container.
+
+
+
+
+Secondly, if you have the Recycle Bin enabled in Active
+Directory and wish to be notified about deleted objects,
+add a search covering the Deleted Objects container.
+
+This will return results when an object is deleted, however
+the DN and CN of the object are changed.  The attribute
+lastKnownParent identifies where the object was deleted
+from.  However, lastKnownParent may not be returned when
+searching the Global Catalog.
+
 
 
 
 Provides FreeRADIUS with the last cookie value we received for the sync
 
+This only applies to directories implementing RFC4533, such as OpenLDAP with
+the syncprov overlay enabled.
+
+For other directories, this will be called prior to the search query being
+sent to the server, so could be used for any initial setup of cache datastores.
+
 A request will be generated with the following attributes:
 
-- &request.LDAP-Sync-DN                the base_dn of the sync.
-- &request.LDAP-Sync-Filter            the filter of the sync (optional).
-- &request.LDAP-Sync-Scope             the scope of the sync (optional).
-- &request.LDAP-Sync-attr              the attributes returned by the sync (optional).
+- &request.LDAP-Sync.DN                the base_dn of the sync.
+- &request.LDAP-Sync.Filter            the filter of the sync (optional).
+- &request.LDAP-Sync.Scope             the scope of the sync (optional).
 
 You should use these attributes to uniquely identify the sync when retrieving
 previous cookie values.
 
+In addition the attribute &request.LDAP-Sync.Directory-Root-DN will be
+populated with the root DN of the directory to aid creating a cookie if one
+has not previously been stored.
+
 Called for a sync when:
 - FreeRADIUS first starts.
 - If a sync experiences an error and needs to be restarted.
 - If a connection experiences an error and needs to be restarted.
 
 The section may return one of the following/codes attributes:
-- ok/updated and &reply.LDAP-Sync-Cookie to indicate a cookie value was loaded.
+- ok/updated and &reply.LDAP-Sync.Cookie to indicate a cookie value was loaded.
 - noop to indicate that no cookie was found.
-  A cookie value representing the current state of the LDAP server may then be
-  optionally synthesised to avoid a complete refresh phase.
 - Any other code to indicate failure.
 
+
+
+If no cookie is returned for https://tools.ietf.org/html/rfc4533[RFC 4533] servers, then the response
+to the initial search will be a complete copy of the directory.
+To avoid that, and just be notified about changes, a cookie which
+matches that which OpenLDAP expects can be mocked up with the following,
+presuming the ldap module is enabled and configured with the same
+server settings as ldap_sync.
+
+
+
+
 Stores the latest cookie we've received for a sync
 
+This only applies to directories implementing RFC4533, such as OpenLDAP with
+the syncprov overlay enabled.
+
+For directories implementing persistent search, which return changeNumber
+in the Entry Change Notice control, this section will be called with the
+changeNumber in LDAP-Sync.Cookie.
+
 A request will be generated with the following attributes:
 
-- &request.LDAP-Sync-DN                the base_dn of the sync.
-- &request.LDAP-Sync-Cookie            the cookie value to store.
-- &request.LDAP-Sync-Filter            the filter of the sync (optional).
-- &request.LDAP-Sync-Scope             the scope of the sync (optional).
-- &request.LDAP-Sync-attr              the attributes returned by the sync (optional).
+- &request.LDAP-Sync.DN                the base_dn of the sync.
+- &request.LDAP-Sync.Cookie            the cookie value to store.
+- &request.LDAP-Sync.Filter            the filter of the sync (optional).
+- &request.LDAP-Sync.Scope             the scope of the sync (optional).
 
 The return code of this section is ignored.
 
+
+
 Notification that a new entry has been added to the LDAP directory
 
-It is recommended that cached entries use LDAP-Sync-Entry-UUID as the key.
-This can be usually be retrieved from the entryUUID operational attribute.
+For directories implementing https://tools.ietf.org/html/rfc4533[RFC 4533], it is recommended that cached entries
+use LDAP-Sync.Entry-UUID as the key.
+This can usually be retrieved from the entryUUID operational attribute.
+
+The entryUUID has the benefit that it will remain constant even if an object's
+DN is changed.
 
-Delete operations may not include the DN of the object if they occur during
-a refreshDeletes phase.
+Delete and Present operations may not include the DN of the object if they occur
+during a refresh stage.
 
 A request will be generated with the following attributes:
 
-- &request.LDAP-Sync-DN                the base_dn of the sync.
-- &request.LDAP-Sync-Entry-UUID        the UUID of the object.
-- &request.LDAP-Sync-Entry-DN  the DN of the object that was added.
+- &request.LDAP-Sync.DN                the base_dn of the sync.
+- &request.LDAP-Sync.Entry-UUID        the UUID of the object. (https://tools.ietf.org/html/rfc4533[RFC 4533] directories only)
+- &request.LDAP-Sync.Entry-DN  the DN of the object that was added.
 - &*:*                         attributes mapped from the LDAP entry to FreeRADIUS
                        attributes using the update section within the sync.
-- &request.LDAP-Sync-Filter            the filter of the sync (optional).
-- &request.LDAP-Sync-Scope             the scope of the sync (optional).
-- &request.LDAP-Sync-attr              the attributes returned by the sync (optional).
+- &request.LDAP-Sync.Filter            the filter of the sync (optional).
+- &request.LDAP-Sync.Scope             the scope of the sync (optional).
+- &request.LDAP-Sync.Attr              the attributes returned by the sync (optional).
 
 The return code of this section is ignored (for now).
 
+
+
 Notification that an entry has been modified in the LDAP directory
 
-It is recommended that cached entries use LDAP-Sync-Entry-UUID as the key.
-This can be usually be retrieved from the entryUUID operational attribute.
+For directories implementing https://tools.ietf.org/html/rfc4533[RFC 4533], it is recommended that cached entries
+use LDAP-Sync.Entry-UUID as the key.
+This can usually be retrieved from the entryUUID operational attribute.
 
-Delete operations may not include the DN of the object if they occur during
-a refreshDeletes phase.
+Delete and Present operations may not include the DN of the object if they occur
+during a refresh stage.
 
 A request will be generated with the following attributes:
 
-- &request.LDAP-Sync-DN                the base_dn of the sync.
-- &request.LDAP-Sync-Entry-UUID        the UUID of the object.
-- &request.LDAP-Sync-Entry-DN  the DN of the object that was added.
+- &request.LDAP-Sync.DN                the base_dn of the sync.
+- &request.LDAP-Sync.Entry-UUID        the UUID of the object. (https://tools.ietf.org/html/rfc4533[RFC 4533] directories only)
+- &request.LDAP-Sync.Entry-DN  the DN of the object that was added.
 - &*:*                         attributes mapped from the LDAP entry to FreeRADIUS
                        attributes using the update section within the sync.
-- &request.LDAP-Sync-Filter            the filter of the sync (optional).
-- &request.LDAP-Sync-Scope             the scope of the sync (optional).
-- &request.LDAP-Sync-attr              the attributes returned by the sync (optional).
+- &request.LDAP-Sync.Filter            the filter of the sync (optional).
+- &request.LDAP-Sync.Scope             the scope of the sync (optional).
+- &request.LDAP-Sync.Original-DN       the original DN of the object, if the object was renamed
+                       and the directory returns this attribute.
 
 The return code of this section is ignored (for now).
 
+
+
 Notification that an entry has been modified in the LDAP directory
 
-It is recommended that cached entries use LDAP-Sync-Entry-UUID as the key.
-This can be usually be retrieved from the entryUUID operational attribute.
+It is recommended that cached entries use LDAP-Sync.Entry-UUID as the key.
+This can usually be retrieved from the entryUUID operational attribute.
+
+Delete and Present operations may not include the DN of the object if they occur
+during a refresh stage.
+
+A request will be generated with the following attributes:
+
+- &request.LDAP-Sync.DN                the base_dn of the sync.
+- &request.LDAP-Sync.Entry-UUID        the UUID of the object. (https://tools.ietf.org/html/rfc4533[RFC 4533] directories only)
+- &request.LDAP-Sync.Entry-DN  the DN of the object that was removed (optional).
+- &*:*                         attributes mapped from the LDAP entry to FreeRADIUS
+                       attributes using the update section within the sync,
+                       if the attributes are returned by the directory.
+- &request.LDAP-Sync.Filter            the filter of the sync (optional).
+- &request.LDAP-Sync.Scope             the scope of the sync (optional).
+
+The return code of this section is ignored (for now).
+
 
-Delete operations may not include the DN of the object if they occur during
-a refreshDeletes phase.
+
+Notification that an entry is still present and unchanged in the LDAP directory.
+
+These only occur with https://tools.ietf.org/html/rfc4533[RFC 4533] servers during initial refresh when a sync starts
+and a cookie has been provided to indicate the last known state of the directory
+according to the client.
+
+It is recommended that cached entries use LDAP-Sync.Entry-UUID as the key.
+This can usually be retrieved from the entryUUID operational attribute.
+
+Delete and Present operations may not include the DN of the object if they occur
+during a refresh stage.
 
 A request will be generated with the following attributes:
 
-- &request.LDAP-Sync-DN                the base_dn of the sync.
-- &request.LDAP-Sync-Entry-UUID        the UUID of the object.
-- &request.LDAP-Sync-Entry-DN  the DN of the object that was added (optional).
-- &request.LDAP-Sync-Filter            the filter of the sync (optional).
-- &request.LDAP-Sync-Scope             the scope of the sync (optional).
-- &request.LDAP-Sync-attr              the attributes returned by the sync (optional).
+- &request.LDAP-Sync.DN                the base_dn of the sync.
+- &request.LDAP-Sync.Entry-UUID        the UUID of the object. (https://tools.ietf.org/html/rfc4533[RFC 4533] directories only)
+- &request.LDAP-Sync.Entry-DN  the DN of the object that is still present (optional).
+- &request.LDAP-Sync.Filter            the filter of the sync (optional).
+- &request.LDAP-Sync.Scope             the scope of the sync (optional).
 
 The return code of this section is ignored (for now).
 
+
 == Default Configuration
 
 ```
-server ldap {
-       namespace = ldap
+server ldap_sync {
+       namespace = ldap_sync
        listen  {
-               type = sync
-               server = "localhost"
-#              port = 389
-#              identity = 'cn=admin,dc=example,dc=org'
-#              password = mypass
-#              sync_retry_interval = 5.0
-#              conn_retry_interval = 5.0
-               sasl {
-#                      mech = 'PLAIN'
-#                      proxy = 'autz_id'
-#                      realm = 'example.org'
+               transport = ldap
+               ldap {
+                       server = "localhost"
+#                      port = 389
+                       identity = 'cn=admin,dc=example,dc=com'
+                       password = mypass
+                       options {
+                               res_timeout = 20
+                               srv_timelimit = 120
+                               idle = 60
+                               probes = 3
+                               interval = 3
+                               reconnection_delay = 10
+                       }
+                       sasl {
+#                              mech = 'PLAIN'
+#                              proxy = 'autz_id'
+#                              realm = 'example.org'
+                       }
+#                      recv_buff = 1048576
+#                      max_outstanding = 65536
                }
+               cookie_interval = 10
+               cookie_changes = 100
                sync {
-                       base_dn = "ou=people,dc=example,dc=org"
-                       filter = "(objectClass=PosixAccount)"
-#                      scope = 'sub'
-#                      attr = 'cn'
-#                      attr = 'foo'
+                       base_dn = "ou=people,dc=example,dc=com"
+                       filter = "(objectClass=posixAccount)"
+                       scope = 'sub'
                        update {
-                               &User-Name := 'cn'
-                               &Password.With-Header := 'userPassword'
+                               &Proto.radius.User-Name = 'uid'
+                               &Password.With-Header = 'userPassword'
                        }
                }
-               sync {
-                       base_dn = "ou=groups,dc=example,dc=org"
-                       filter = "(objectClass=unixGroup}"
-               }
+#              sync {
+#                      base_dn = "ou=groups,dc=example,dc=com"
+#                      filter = "(objectClass=groupOfNames)"
+#                      scope = "sub"
+#                      update {
+#                              &Tmp-String-0 += "member"
+#                      }
+#              }
+#              sync {
+#                      base_dn = 'cn=Users,dc=example,dc=com'
+#                      filter = '(userAccountControl:1.2.840.113556.1.4.803:=512)'
+#                      scope = 'sub'
+#                      update {
+#                              &Proto.radius.User-Name = 'sAMAccountName'
+#                              &Tmp-Integer-0 = 'userAccountControl'
+#                      }
+#              }
+#              sync {
+#                      base_dn = "CN=Deleted Objects,dc=example,dc=com"
+#                      filter = '(userAccountControl:1.2.840.113556.1.4.803:=512)'
+#                      scope = "one"
+#                      update {
+#                              &Proto.radius.User-Name = 'sAMAccountName'
+#                              &Tmp-Integer-0 = 'userAccountControl'
+#                              &Tmp-String-0 = 'lastKnownParent'
+#                      }
+#              }
        }
        load Cookie {
-               debug_all
+               debug_request
+#              if (!&reply.LDAP-Sync.Cookie) {
+#                      string csn
+#                      &csn := %ldap("ldap:///%{LDAP-Sync.Directory-Root-DN}?contextCSN?base")
+#                      if (&csn) {
+#                              &reply.LDAP-Sync.Cookie := "rid=000,csn=%{csn}"
+#                              updated
+#                      }
+#              }
        }
        store Cookie {
-               debug_all
+               debug_request
        }
        recv Add {
-               debug_all
+               debug_request
        }
        recv Modify {
-               debug_all
+               debug_request
        }
        recv Delete {
-               debug_all
+               debug_request
+       }
+       recv Present {
+               debug_request
        }
 }
 ```
index 4c84df0d61cdcc562d5117c2fc356cf431b1850d..922c6ce6de7ff66f6ad6f62b7c3b457196ac4c50 100644 (file)
@@ -1,4 +1,7 @@
 
+WARNING: This configuration file has not been updated for v4,
+          and therefore WILL NOT WORK.  Please do not use it.
+
 
 
 
index 412116ba0af869f065989841713e6e23a5a154f9..c4d206613f8e5f5d14c0f01068149d91ec7ed649 100644 (file)
@@ -68,12 +68,12 @@ uses the control module, for example:
 
       pap
   }
-
   ...
+  }
 
 
 The configuration for this virtual server follows and should be amended as
-required...
+required.
 
 
 
@@ -128,7 +128,7 @@ listen {
        type = Status-Server
 }
 recv Status-Server {
-       if ("%{sql:SELECT pg_is_in_recovery()}" != "f") {
+       if ("%sql('SELECT pg_is_in_recovery()')" != "f") {
                if ("%{db_online:}" != "fail") {
                        %{db_online:fail}
                }
index 874c40767622bdb01ff98cd7f37c9997190711d7..034f2bfa0c080473af9363349a20ba0abc97e6bf 100644 (file)
@@ -1,4 +1,7 @@
 
+WARNING: This configuration file has not been updated for v4,
+          and therefore WILL NOT WORK.  Please do not use it.
+
 
 
 
index efa45e32abe5da7c5c224b9d1172a483610dcb77..4df64d46640095217cc762f00feae03c54d53b31 100644 (file)
@@ -121,7 +121,7 @@ server vmps {
                &reply.Error-Code = No-Error
                &reply.Cookie = &MAC-Address
                &reply.VLAN-Name = "please_use_real_vlan_here"
-#              &reply.VLAN-Name = "%{sql:select ... where mac='%{MAC-Address}'}"
+#              &reply.VLAN-Name = %sql("select ... where mac='%{MAC-Address}'")
        }
        send Join-Response {
                ok
index 3f111231cffc2aef6ab4a700c95353ada43b9d94..41ddc505cc1b90cac5d7d2b551c091961d2c308d 100644 (file)
@@ -59,7 +59,7 @@ cache cache_eap {
        #
        #  key:: Cache key.
        #
-       key = "%{%{control.State}:-%{%{reply.State}:-%{State}}}"
+       key = "%{&control.State || &reply.State || &State}"
 
        #
        #  ttl:: TTL for cache entries.
index c4bd339c1104bae1c068a6dccf01c223167d0f5b..d5d84833bacdca2c1fcb2bf4eca49125799cd81b 100644 (file)
@@ -57,7 +57,7 @@ couchbase {
        #
        #  This key is dynamically expanded at run time.
        #
-       acct_key = "radacct_%{%{Acct-Unique-Session-Id}:-%{Acct-Session-Id}}"
+       acct_key = "radacct_%{&Acct-Unique-Session-Id || &Acct-Session-Id}"
 
        #
        #  doctype:: Value for the 'docType' element in the json body for accounting documents.
@@ -109,7 +109,7 @@ couchbase {
        #
        #  user_key:: Couchbase document key for user documents (`unlang` supported).
        #
-       user_key = "raduser_%md5(%tolower(%{%{Stripped-User-Name}:-%{User-Name}}))"
+       user_key = "raduser_%md5(%tolower(%{&Stripped-User-Name || &User-Name}))"
 
        #
        #  read_clients:: Set to `yes` to read radius clients from the Couchbase view specified below.
index 67fe848d5b357000de2fbf5e129af67a92820f48..122a40270218d9c7b7f8355b3514da67e1deddfb 100644 (file)
@@ -35,7 +35,7 @@ files {
        #
        #  The content of this attribute is used to match the `name` of the entry.
        #
-#      key = "%{%{Stripped-User-Name}:-%{User-Name}}"
+#      key = "%{&Stripped-User-Name || &User-Name}"
 
        #
        #  filename:: The old `users` style file is now located here.
index ab1a058e68a80891cb5535bc4778d1a5f620edef..2bb6ea6068bc63b4678333b28be2c45fff4e074b 100644 (file)
@@ -247,7 +247,7 @@ ldap {
                #  filter:: Filter for user objects, should be specific enough
                #  to identify a single user object.
                #
-               filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
+               filter = "(uid=%{&Stripped-User-Name || &User-Name})"
 
                #  For Active Directory nested group, you should comment out the previous 'filter = ...'
                #  and use the below. Where 'group' is the group you are querying for.
@@ -260,7 +260,7 @@ ldap {
                #
                #  See: https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
                #
-#              filter = "(&(objectClass=user)(sAMAccountName=%{%{Stripped-User-Name}:-%{User-Name}})(memberOf:1.2.840.113556.1.4.1941:=cn=group,${..base_dn}))"
+#              filter = "(&(objectClass=user)(sAMAccountName=%{&Stripped-User-Name || &User-Name})(memberOf:1.2.840.113556.1.4.1941:=cn=group,${..base_dn}))"
 
                #
                #  sasl { ... }:: SASL parameters to use for user binds
@@ -408,7 +408,7 @@ ldap {
                #  That is, group objects with attributes that identify
                #  members (the inverse of `membership_attribute`).
                #
-#              membership_filter = "(|(member=%{control.Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))"
+#              membership_filter = "(|(member=%{control.Ldap-UserDn})(memberUid=%{&Stripped-User-Name || &User-Name}))"
 
                #
                #  membership_attribute:: The attribute, in user objects, which contain
index 32e8aaab844c180b3e0f9b2da7e799c992d6d930..d123d9a563ca3bc48e9072667af49a3e588ce691 100644 (file)
@@ -404,10 +404,10 @@ linelog log_accounting {
                #  Don't log anything for these packets.
                Interim-Update = ""
 
-               Accounting-On = "NAS %{Net.Src.IP} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) just came online"
-               Accounting-Off = "NAS %{Net.Src.IP} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) just went offline"
+               Accounting-On = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) just came online"
+               Accounting-Off = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) just went offline"
 
                #  Don't log anything for other `Acct-Status-Type` 's.
-               unknown = "NAS %{Net.Src.IP} (%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}}) sent unknown Acct-Status-Type %{Acct-Status-Type}"
+               unknown = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) sent unknown Acct-Status-Type %{Acct-Status-Type}"
        }
 }
index f12be85a8e089213fa3f2932821fdfb1cee37de5..c7ea4194253b8709a1ecb14d6e0375a64478acb6 100644 (file)
@@ -37,7 +37,7 @@ radutmp {
        #  structure is small, around `32` characters, so that will limit
        #  the possible choices of keys.
        #
-       #  TIP: You may want instead: `%{%{Stripped-User-Name}:-%{User-Name}}`.
+       #  TIP: You may want instead: `%{&Stripped-User-Name || &User-Name}`.
        #
        username = %{User-Name}
 
index 0c526b8089b831dea022b8ad758149a077152186..87b4e01feb81f236e9f315a36ef1cd0a482d9a9d 100644 (file)
@@ -83,7 +83,7 @@ redis_ippool {
        #  Otherwise the client hardware address must be used. To comply with
        #  this requirement use the following:
        #
-#      owner = "%{%{Client-Identifier}:-%{Client-Hardware-Address}}"
+#      owner = "%{&Client-Identifier || &Client-Hardware-Address}"
 
        #
        #  For purposes such as IP assignment using a RADIUS Framed-IP-Address
@@ -102,7 +102,7 @@ redis_ippool {
        #
        #  requested_address:: The IP address being renewed or released.
        #
-       requested_address = "%{%{Requested-IP-Address}:-%{Net.Src.IP}}"
+       requested_address = "%{&Requested-IP-Address || &Net.Src.IP}"
 
        #
        #  ipv4_integer:: Whether IPv4 addresses should be cast to integers, for renew operations.
index 6420cad15f05234d2f27cf84964484de748ed55d..6dc6c136574712eeeb03a5903e798f8039b03412 100644 (file)
@@ -83,7 +83,7 @@ rediswho {
        #  ### Start
        #
        Start {
-               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
+               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{&NAS-IP-Address || &NAS-IPv6-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
                trim =   "LTRIM %{User-Name} 0 ${..trim_count}"
                expire = "EXPIRE %{User-Name} ${..expire_time}"
        }
@@ -92,7 +92,7 @@ rediswho {
        #  ### Interim-Update
        #
        Interim-Update {
-               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
+               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{&NAS-IP-Address || &NAS-IPv6-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
                trim =   "LTRIM %{User-Name} 0 ${..trim_count}"
                expire = "EXPIRE %{User-Name} ${..expire_time}"
        }
@@ -101,7 +101,7 @@ rediswho {
        #  ### Stop
        #
        Stop {
-               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{%{NAS-IP-Address}:-%{NAS-IPv6-Address}},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
+               insert = "LPUSH %{User-Name} %l,%{Acct-Session-Id},%{&NAS-IP-Address || &NAS-IPv6-Address},%{Acct-Session-Time},%{Framed-IP-Address},%{%{Acct-Input-Gigawords}:-0},%{%{Acct-Output-Gigawords}:-0},%{%{Acct-Input-Octets}:-0},%{%{Acct-Output-Octets}:-0}"
                trim =   "LTRIM %{User-Name} 0 ${..trim_count}"
                expire = "EXPIRE %{User-Name} ${..expire_time}"
        }
index 4707b8f4a65991f3209160f7cc0fcf08106b037e..a11bb848bd081689c82907038ea98d8c2705d53a 100644 (file)
@@ -69,7 +69,7 @@
 #  The `query` parameter specifies the SQL query used to get the current Counter value
 #  from the database.
 #
-#      key = "%{%{Stripped-User-Name}:-%{User-Name}}"
+#      key = "%{&Stripped-User-Name || &User-Name}"
 #
 #  reset_period_start_name::  The name of the attribute which is used to store the
 #  time that the current reset period started.
@@ -112,7 +112,7 @@ sqlcounter dailycounter {
        counter_name = &control.Daily-Session-Time
        check_name = &control.Max-Daily-Session
        reply_name = &reply.Session-Timeout
-       key = "%{%{Stripped-User-Name}:-%{User-Name}}"
+       key = "%{&Stripped-User-Name || &User-Name}"
 
        reset = daily
 
index e1bb065e081f7daf7843c53552a8b3ca92addb98..6013420c6bbe05f87695cfc02c411eee215f6150 100644 (file)
@@ -88,7 +88,7 @@ sqlippool {
        #  * `%{dhcpv4.Client-Hardware-Address}` which binds the lease to the
        #    mac address of the user's device.
        #
-       #  * `%{%{dhcpv4.Client-Identifier}:-%{dhcpv4.Client-Hardware-Address}}`
+       #  * `%{&dhcpv4.Client-Identifier || &dhcpv4.Client-Hardware-Address}`
        #    which binds the lease to either the custom identifier set by the
        #    DHCP client, or if this is absent, the mac address of the user's
        #    device.
@@ -114,7 +114,7 @@ sqlippool {
 
 #       owner = "%{radius.Vendor-Specific.ADSL-Forum.Agent-Circuit-ID}.%{radius.Calling-Station-Id}"
 
-#      owner = "%{%{dhcpv4.Client-Identifier}:-%{dhcpv4.Client-Hardware-Address}}"
+#      owner = "%{&dhcpv4.Client-Identifier || &dhcpv4.Client-Hardware-Address}"
 
        #
        #  requested_address:: The IP address being renewed or released.
@@ -122,11 +122,11 @@ sqlippool {
        #  For RADIUS the requested_address will almost always be `%{radius.Framed-IP-Address}`.
        #
        #  For DHCPv4 the requested_address will almost always be
-       #  `%{%{dhcpv4.Requested-IP-Address}:-%{dhcpv4.Client-IP-Address}}`.
+       #  `%{&dhcpv4.Requested-IP-Address || &dhcpv4.Client-IP-Address}`.
        #
        requested_address = "%{radius.Framed-IP-Address}"
 
-#      requested_address = "%{%{dhcpv4.Requested-IP-Address}:-%{dhcpv4.Client-IP-Address}}"
+#      requested_address = "%{&dhcpv4.Requested-IP-Address || &dhcpv4.Client-IP-Address}"
 
        #
        #  gateway:: The device controlling access to the network or relaying
@@ -140,7 +140,7 @@ sqlippool {
        #  For DHCPv4, this device is recorded so that we can respond correctly
        #  to lease queries.
        #
-       gateway = "%{%{radius.NAS-Identifier}:-%{radius.NAS-IP-Address}}"
+       gateway = "%{&radius.NAS-Identifier || &radius.NAS-IP-Address}"
 
 #       gateway = "%{dhcpv4.Gateway-IP-Address}"
 
index f9703a724d0ecfcbe9d18eee454314761e7647a4..dd77a90957554f1a9a1119b6677ff003f72c129e 100644 (file)
@@ -25,7 +25,7 @@ winbind {
        #
        #  username:: The username to pass to `winbind` for authentication.
        #
-       username = "%{%{Stripped-User-Name}:-%{User-Name}}"
+       username = "%{&Stripped-User-Name || &User-Name}"
 
        #
        #  domain:: The windows domain.
@@ -52,7 +52,7 @@ winbind {
                #  This should generally not include a realm, so `Stripped-User-Name`
                #  is likely the best attribute if it exists.
                #
-               search_username = "%{%{Stripped-User-Name}:-%{User-Name}}"
+               search_username = "%{&Stripped-User-Name || &User-Name}"
 
                #
                #  add_domain:: Include the domain in group searches.
index 6922da1d66e4f7430ee3f651aeaa033c2a1e6328..812221a34b2d21498afee70e8eef8a6e17b9c4ec 100644 (file)
@@ -20,4 +20,4 @@
 #  Replace the User-Name with the Stripped-User-Name, if it exists.
 #
 #DEFAULT
-#      User-Name := "%{%{Stripped-User-Name}:-%{User-Name}}"
+#      User-Name := "%{&Stripped-User-Name || &User-Name}"
index 92b67e15dac73ab648cad4303e5e4f5bef686140..47443bd7724a48b79944a6ff3c07b645cbdaa432 100644 (file)
@@ -36,5 +36,5 @@ postauth_query = "INSERT INTO wimax \
                  (username, authdate, spi, mipkey, lifetime) \
                  VALUES ( \
                  '%{User-Name}', '%S' \
-                 '%{%{reply.WiMAX.MN-hHA-MIP4-SPI}:-%{reply.WiMAX.MN-hHA-MIP6-SPI}}', \
-                 '%{%{reply.WiMAX.MN-hHA-MIP4-Key}:-%{reply.WiMAX.MN-hHA-MIP6-Key}}', '%{%{reply.Session-Timeout}:-86400}' )"
+                 '%{&reply.WiMAX.MN-hHA-MIP4-SPI || &reply.WiMAX.MN-hHA-MIP6-SPI}', \
+                 '%{&reply.WiMAX.MN-hHA-MIP4-Key || &reply.WiMAX.MN-hHA-MIP6-Key}', '%{%{reply.Session-Timeout}:-86400}' )"
index bb28cffb718fb1397849be679964fd9ef9ece3ce..1344d017eaa7cde2aa69f9246f95c3c7d32ec3e0 100644 (file)
@@ -250,7 +250,7 @@ accounting {
                                        AcctTerminateCause = '%{%{Acct-Terminate-Cause}:-NAS-Reboot}', \
                                        Class = '%{Class}' \
                                WHERE AcctStopTime IS NULL \
-                               AND NASIPAddress= '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \
+                               AND NASIPAddress= '%{&NAS-IPv6-Address || &NAS-IP-Address}' \
                                AND AcctStartTime <= ${....event_timestamp}"
 
                        #
@@ -300,8 +300,8 @@ accounting {
                                        '%{Acct-Unique-Session-Id}', \
                                        '%{SQL-User-Name}', \
                                        NULLIF('%{Realm}', ''), \
-                                       '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \
-                                       NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \
+                                       '%{&NAS-IPv6-Address || &NAS-IP-Address}', \
+                                       NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \
                                        '%{NAS-Port-Type}', \
                                        ${....event_timestamp}, \
                                        ${....event_timestamp}, \
@@ -370,8 +370,8 @@ accounting {
                                        '%{Acct-Unique-Session-Id}', \
                                        '%{SQL-User-Name}', \
                                        NULLIF('%{Realm}', ''), \
-                                       '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \
-                                       NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \
+                                       '%{&NAS-IPv6-Address || &NAS-IP-Address}', \
+                                       NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \
                                        '%{NAS-Port-Type}', \
                                        ${....event_timestamp}, \
                                        ${....event_timestamp}, \
@@ -426,8 +426,8 @@ accounting {
                                        '%{Acct-Unique-Session-Id}', \
                                        '%{SQL-User-Name}', \
                                        NULLIF('%{Realm}', ''), \
-                                       '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \
-                                       NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \
+                                       '%{&NAS-IPv6-Address || &NAS-IP-Address}', \
+                                       NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \
                                        '%{NAS-Port-Type}', \
                                        TO_TIMESTAMP(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \
                                        ${....event_timestamp}, \
index 40714dc01ad445492aa4eb6752f49e204919e891..11aaa4fda0cee223e787ebb7890ae8ba57841505 100644 (file)
@@ -273,7 +273,7 @@ accounting {
                                        '%{SQL-User-Name}', \
                                        '%{Realm}', \
                                        '%{NAS-IP-Address}', \
-                                       '%{%{NAS-Port-ID}:-%{NAS-Port}}', \
+                                       '%{&NAS-Port-ID || &NAS-Port}', \
                                        '%{NAS-Port-Type}', \
                                        ${....event_timestamp}, \
                                        ${....event_timestamp}, \
@@ -343,7 +343,7 @@ accounting {
                                        '%{SQL-User-Name}', \
                                        '%{Realm}', \
                                        '%{NAS-IP-Address}', \
-                                       '%{%{NAS-Port-ID}:-%{NAS-Port}}', \
+                                       '%{&NAS-Port-ID || &NAS-Port}', \
                                        '%{NAS-Port-Type}', \
                                        (${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \
                                        ${....event_timestamp}, \
@@ -395,7 +395,7 @@ accounting {
                                        '%{SQL-User-Name}', \
                                        '%{Realm}', \
                                        '%{NAS-IP-Address}', \
-                                       '%{%{NAS-Port-ID}:-%{NAS-Port}}', \
+                                       '%{&NAS-Port-ID || &NAS-Port}', \
                                        '%{NAS-Port-Type}', \
                                        (${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \
                                        ${....event_timestamp}, \
index 8fca45425105b9bce7c8854fcffb5b463677e386..a52679ca540da54d086992d93d260b24f4c7a37d 100644 (file)
@@ -67,7 +67,7 @@ acct_unique {
        #  is not included
        #
        else {
-               &request.Acct-Unique-Session-Id := "%hex(%md5(%string(%{User-Name},%{Acct-Multi-Session-ID},%{Acct-Session-ID},%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}},%{NAS-Identifier},%{NAS-Port-ID},%{NAS-Port})))"
+               &request.Acct-Unique-Session-Id := "%hex(%md5(%string(%{User-Name},%{Acct-Multi-Session-ID},%{Acct-Session-ID},%{&NAS-IPv6-Address || &NAS-IP-Address},%{NAS-Identifier},%{NAS-Port-ID},%{NAS-Port})))"
        }
 }
 
index e3727e95e0ab9fd1166388163828c5f139762749..27708ce672f15f6d94085e1a779894448dcd220d 100644 (file)
@@ -212,7 +212,7 @@ recv Request {
 #      dhcp_sqlippool
 
        if (ok) {
-               &reply.Your-IP-Address := "%{%{request.Requested-IP-Address}:-%{request.Client-IP-Address}}"
+               &reply.Your-IP-Address := "%{&request.Requested-IP-Address || &request.Client-IP-Address}"
        }
 
        #  If Message-Type is not set, returning "ok" or