[POLL] Escaping behaviour in SQL/LDAP/regexes
For FreeRADIUS v4 we have a new method of automatically escaping values used in various DSLs (Domain Specific Languages) like SQL, LDAP and regular expressions. We'd appreciate it if FreeRADIUS users could look over the policy snippets below and indicate what you expect the SQL statement to be _as executed_ (not the result of evaluating the statement). Assume the value of User-Name is: Bob'; DROP TABLE users;-- Possible answers: a) SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = 'Bob'; DROP TABLE users;--' b) SELECT * FROM my-table WHERE Service-Type = \'Framed-User\' AND User-Name = 'Bob\'; DROP TABLE users;--' c) SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = 'Bob\'; DROP TABLE users;--' d) Other. Please write expected, expanded, SQL statement. Do not return to previous statements and alter answers. The purpose of this poll is to determine what user's expect behaviour to be, prior to seeing example code or reading documentation. 1) recv authorize { string sql_condition sql_condition = "Service-Type = 'Framed-User'" %sql.query("SELECT * FROM my-table WHERE %{sql_condition} AND User-Name = '%{User-Name}'") } 2) recv authorize { string sql_condition sql_condition = %sql.safe("Service-Type = 'Framed-User'") %sql.query("SELECT * FROM my-table WHERE %{sql_condition} AND User-Name = '%{User-Name}'") } 3) recv authorize { string sql_condition sql_condition = "Service-Type = 'Framed-User'" %sql.query("SELECT * FROM my-table WHERE %sql.safe(%{sql_condition}) AND User-Name = '%{User-Name}'") } 4) recv authorize { string sql_condition sql_condition = "Service-Type = 'Framed-User'" %sql.query("SELECT * FROM my-table WHERE %sql.safe(%{sql_condition}) AND User-Name = '%sql.safe(%{User-Name})'") } Other FreeRADIUS developers please refrain from responding until the 14th of March (when we'll tally results). Many Thanks, -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS Development Team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
Arran Cudbard-Bell via Freeradius-Users <freeradius-users@lists.freeradius.org> writes:
We'd appreciate it if FreeRADIUS users could look over the policy snippets below and indicate what you expect the SQL statement to be _as executed_ (not the result of evaluating the statement).
I'm not sure if you're asking what I expect from a sane sql client or what I believe FreeRADIUS will do. I'll answer based on the first alternative since thaẗ́s what I care about.
Assume the value of User-Name is: Bob'; DROP TABLE users;--
Possible answers:
a) SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = 'Bob'; DROP TABLE users;--' b) SELECT * FROM my-table WHERE Service-Type = \'Framed-User\' AND User-Name = 'Bob\'; DROP TABLE users;--' c) SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = 'Bob\'; DROP TABLE users;--' d) Other. Please write expected, expanded, SQL statement.
My expectation is always a prepared statement in the form SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = ? called with the current User-Name variable value as a bound parameter. This will of course not work with "%{sql_condition}" as a variable. But then I don't expect "%{sql_condition}" to be a variable either. Why would it? Better write the complete statement. And if you have two almost identical statements in the configuration, then you have two almost identical statements in the configuration. Nothing to gain by combining them with some made up variable part. That's only confusing, and adding unnecessary risk of screwing up quoting/expansion. Bjørn
Assume the value of User-Name is: Bob'; DROP TABLE users;--
Possible answers:
a) SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = 'Bob'; DROP TABLE users;--' b) SELECT * FROM my-table WHERE Service-Type = \'Framed-User\' AND User-Name = 'Bob\'; DROP TABLE users;--' c) SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = 'Bob\'; DROP TABLE users;--' d) Other. Please write expected, expanded, SQL statement.
These are possible answers for each of the 4 policy snippets immediately below the possible answers. We're looking for something like: 1. a 2. b 3. c 4. d
My expectation is always a prepared statement in the form
SELECT * FROM my-table WHERE Service-Type = 'Framed-User' AND User-Name = ?
called with the current User-Name variable value as a bound parameter.
This will of course not work with "%{sql_condition}" as a variable. But then I don't expect "%{sql_condition}" to be a variable either. Why would it? Better write the complete statement.
This is a contrived set of policies. The point is to determine what user's expectation of how the variables in the SQL statement are expanded/interpolated, not to debate best practice in policy writing :) -Arran
To put it another way... We don't want to trust the data we get from the network. User-Names can be mangled with SQL syntax. And we don't want users to be able to type in "funny" names, and have the database go down. v3 fixes this by escaping just about everything, always. There are some places where the data isn't escaped, but not many. We've gradually fixed most of the weird things over the years, so that it mostly works, and mostly does what you expect. We'd like to do better for v4. So the question is what needs to be escaped, and when? For me, we'll assume that everything from the network is escaped or sanitized. Which leaves two cases: 1) an in-line SQL query foo = %sql("SELECT foo from bar where username='%{User-Name}'") 2) a constructed SQL query: stub = "SELECT foo" foo = %sql("%{stub} from bar where username='%{User-Name}'") Should the "stub" variable here be escaped? I know in this case it's safe, but that's not the point. SQL queries can contain quotes, = signs, etc. Administrators may want to put SQL queries in-place in the configuration, or they may want to construct SQL queries through intermediate variables. So should the contents of "stub" be escaped? Alan DeKok.
I have the accounting {} setting in /etc/raddb/sites-available/default. How can I prevent this configuration from breaking the accounting response if an SQL connection error occurs or radutmp fails to write to the file? The accounting response should continue even if there are logging errors. accounting { if ("%{User-Name}" =~ /@/) { radutmp sql_Fradius_log } exec attr_filter.accounting_response log_accounting } FreeRADIUS Version 3.2.7
On Mar 13, 2025, at 3:02 AM, (null) (null) via Freeradius-Users <freeradius-users@lists.freeradius.org> wrote:
I have the accounting {} setting in /etc/raddb/sites-available/default. How can I prevent this configuration from breaking the accounting response if an SQL connection error occurs or radutmp fails to write to the file? The accounting response should continue even if there are logging errors.
accounting { if ("%{User-Name}" =~ /@/) { radutmp sql_Fradius_log } exec attr_filter.accounting_response log_accounting
Add "ok". The accounting section only replies if at least one module returns OK / success. Alan DeKok.
Tried the following settings, but it still doesn't work. The accounting log breaks when SQL fails to connect, and it only returns successfully when the SQL server is up. I want to ensure that accounting responds even if it fails to save the log to radutmp or SQL. Error Message: (0) No reply from server for ID 124 socket 3 accounting { if ("%{User-Name}" =~ /@/) { radutmp sql_Fradius_log } exec attr_filter.accounting_response log_accounting ok } accounting { if ("%{User-Name}" =~ /@/) { radutmp sql_Fradius_log ok } exec attr_filter.accounting_response log_accounting }
On 13 Mar 2025, at 5:04 PM, Alan DeKok <aland@deployingradius.com> wrote:
On Mar 13, 2025, at 3:02 AM, (null) (null) via Freeradius-Users <freeradius-users@lists.freeradius.org <mailto:freeradius-users@lists.freeradius.org>> wrote:
I have the accounting {} setting in /etc/raddb/sites-available/default. How can I prevent this configuration from breaking the accounting response if an SQL connection error occurs or radutmp fails to write to the file? The accounting response should continue even if there are logging errors.
accounting { if ("%{User-Name}" =~ /@/) { radutmp sql_Fradius_log } exec attr_filter.accounting_response log_accounting
Add "ok".
The accounting section only replies if at least one module returns OK / success.
Alan DeKok.
On Mar 13, 2025, at 4:53 PM, (null) (null) via Freeradius-Users <freeradius-users@lists.freeradius.org> wrote:
Tried the following settings, but it still doesn't work.
If only there was some kind of debug output which could help.
The accounting log breaks when SQL fails to connect, and it only returns successfully when the SQL server is up. I want to ensure that accounting responds even if it fails to save the log to radutmp or SQL.
1) read the debug output to see what's going on 2) write a policy (e.g. using the "redundant" keyword ) which handles this situation. This is documented extensively. Alan DeKok.
I hope you can identify the issue here. Thank for your help. I also tried using redundancy as follows, but still no luck. :( redundant { radutmp sql_Fradius_log } ok (1) Received Accounting-Request Id 10 from 127.0.0.1:49348 to 127.0.0.1:1813 length 49 (1) User-Name = "testuser@domain" (1) Acct-Status-Type = Start (1) NAS-Port = 3 (1) # Executing section preacct from file /etc/raddb/sites-enabled/default (1) preacct { (1) [preprocess] = ok (1) policy acct_unique { (1) update request { (1) &Tmp-String-9 := "ai:" (1) } # update request = noop (1) if (("%{hex:&Class}" =~ /^%{hex:&Tmp-String-9}/) && ("%{string:&Class}" =~ /^ai:([0-9a-f]{32})/i)) { (1) EXPAND %{hex:&Class} (1) --> (1) EXPAND ^%{hex:&Tmp-String-9} (1) --> ^61693a (1) if (("%{hex:&Class}" =~ /^%{hex:&Tmp-String-9}/) && ("%{string:&Class}" =~ /^ai:([0-9a-f]{32})/i)) -> FALSE (1) else { (1) update request { (1) EXPAND %{md5:%{User-Name},%{Acct-Session-ID},%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}},%{NAS-Identifier},%{NAS-Port-ID},%{NAS-Port}} (1) --> 07956f1250babaf1ff478f016d470d4c (1) &Acct-Unique-Session-Id := 07956f1250babaf1ff478f016d470d4c (1) } # update request = noop (1) } # else = noop (1) update request { (1) &Tmp-String-9 !* ANY (1) } # update request = noop (1) } # policy acct_unique = noop (1) suffix: Checking for suffix after "@" (1) suffix: Looking up realm "domain" for User-Name = "testuser@domain" (1) suffix: No such realm "domain" (1) [suffix] = noop (1) [files] = noop (1) } # preacct = ok (1) # Executing section accounting from file /etc/raddb/sites-enabled/default (1) accounting { (1) if ("%{User-Name}" =~ /@/) { (1) EXPAND %{User-Name} (1) --> testuser@domain (1) if ("%{User-Name}" =~ /@/) -> TRUE (1) if ("%{User-Name}" =~ /@/) { (1) radutmp: EXPAND /opt/Fradius_log/shared/radius/radutmp (1) radutmp: --> /opt/Fradius_log/shared/radius/radutmp (1) radutmp: EXPAND %{User-Name} (1) radutmp: --> testuser@domain (1) [radutmp] = ok (1) sql_Fradius_log: EXPAND %{tolower:type.%{%{Acct-Status-Type}:-%{Request-Processing-Stage}}.query} (1) sql_Fradius_log: --> type.start.query (1) sql_Fradius_log: Using query template 'query' rlm_sql (sql_Fradius_log): Reserved connection (2) (1) sql_Fradius_log: EXPAND %{User-Name} (1) sql_Fradius_log: --> testuser@domain (1) sql_Fradius_log: SQL-User-Name set to 'testuser@domain' (1) sql_Fradius_log: EXPAND INSERT INTO radacct (acctsessionid, acctuniqueid, username, realm, nasipaddress, nasportid, nasporttype, acctstarttime, acctupdatetime, acctstoptime, acctsessiontime, acctauthentic, connectinfo_start, connectinfo_stop, acctinputoctets, acctoutputoctets, calledstationid, callingstationid, acctterminatecause, servicetype, framedprotocol, framedipaddress, framedipv6address, framedipv6prefix, framedinterfaceid, delegatedipv6prefix ) VALUES ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{%{NAS-Port-ID}:-%{NAS-Port}}', '%{NAS-Port-Type}', FROM_UNIXTIME(%{%{integer:Event-Timestamp}:-%l}), FROM_UNIXTIME(%{%{integer:Event-Timestamp}:-%l}), NULL, '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Framed-IPv6-Address}', '%{Framed-IPv6-Prefix}', '%{Framed-Interface-Id}', '%{Delegated-IPv6-Prefix}' ) (1) sql_Fradius_log: --> INSERT INTO radacct (acctsessionid, acctuniqueid, username, realm, nasipaddress, nasportid, nasporttype, acctstarttime, acctupdatetime, acctstoptime, acctsessiontime, acctauthentic, connectinfo_start, connectinfo_stop, acctinputoctets, acctoutputoctets, calledstationid, callingstationid, acctterminatecause, servicetype, framedprotocol, framedipaddress, framedipv6address, framedipv6prefix, framedinterfaceid, delegatedipv6prefix ) VALUES ('', '07956f1250babaf1ff478f016d470d4c', 'testuser@domain', '', '127.0.0.1', '3', '', FROM_UNIXTIME(1741878287), FROM_UNIXTIME(1741878287), NULL, '0', '', '', '', '0', '0', '', '', '', '', '', '', '', '', '', '' ) (1) sql_Fradius_log: Executing query: INSERT INTO radacct (acctsessionid, acctuniqueid, username, realm, nasipaddress, nasportid, nasporttype, acctstarttime, acctupdatetime, acctstoptime, acctsessiontime, acctauthentic, connectinfo_start, connectinfo_stop, acctinputoctets, acctoutputoctets, calledstationid, callingstationid, acctterminatecause, servicetype, framedprotocol, framedipaddress, framedipv6address, framedipv6prefix, framedinterfaceid, delegatedipv6prefix ) VALUES ('', '07956f1250babaf1ff478f016d470d4c', 'testuser@domain', '', '127.0.0.1', '3', '', FROM_UNIXTIME(1741878287), FROM_UNIXTIME(1741878287), NULL, '0', '', '', '', '0', '0', '', '', '', '', '', '', '', '', '', '' ) (1) sql_Fradius_log: ERROR: rlm_sql_mysql: ERROR 1927 (Connection was killed): 70100 (1) sql_Fradius_log: SQL query returned: server error rlm_sql (sql_Fradius_log): Released connection (2) Need more connections to reach 10 spares rlm_sql (sql_Fradius_log): Opening additional connection (7), 1 of 25 pending slots used rlm_sql_mysql: Starting connect to MySQL server rlm_sql_mysql: Couldn't connect to MySQL server root@10.0.0.79:Fradius rlm_sql_mysql: MySQL error: Can't connect to MySQL server on '10.0.0.79' (111) rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Opening connection failed (7) rlm_sql (sql_Fradius_log): Closing expired connection (5) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Closing expired connection (4) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Closing expired connection (3) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Closing expired connection (0) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket …. (3) Not sending reply to client. (3) Finished request (3) Cleaning up request packet ID 10 with timestamp +100 due to done
On 13 Mar 2025, at 10:55 PM, Alan DeKok <aland@deployingradius.com> wrote:
On Mar 13, 2025, at 4:53 PM, (null) (null) via Freeradius-Users <freeradius-users@lists.freeradius.org> wrote:
Tried the following settings, but it still doesn't work.
If only there was some kind of debug output which could help.
The accounting log breaks when SQL fails to connect, and it only returns successfully when the SQL server is up. I want to ensure that accounting responds even if it fails to save the log to radutmp or SQL.
1) read the debug output to see what's going on
2) write a policy (e.g. using the "redundant" keyword ) which handles this situation.
This is documented extensively.
Alan DeKok.
On Mar 13, 2025, at 5:12 PM, (null) (null) <kckong1@yahoo.com> wrote:
I hope you can identify the issue here. Thank for your help.
I also tried using redundancy as follows, but still no luck. :(
It's good to read the documentation on the redundant keyword: https://www.freeradius.org/documentation/freeradius-server/3.2.8/unlang/redu...
redundant { radutmp sql_Fradius_log } ok
Which means: redundant: try radutmp if that fails try sql if that fails return fail OK ? How about putitng the "ok" inside of the "redundant" block? Alan DeKok.
Alan, Just wanted to say that the solution worked perfectly—it’s awesome! Thank you for the help and support. accounting { if ("%{User-Name}" =~ /@/) { radutmp redundant { sql_Fradius_log ok } } exec attr_filter.accounting_response log_accounting }
On 13 Mar 2025, at 11:25 PM, Alan DeKok <aland@deployingradius.com> wrote:
On Mar 13, 2025, at 5:12 PM, (null) (null) <kckong1@yahoo.com> wrote:
I hope you can identify the issue here. Thank for your help.
I also tried using redundancy as follows, but still no luck. :(
It's good to read the documentation on the redundant keyword:
https://www.freeradius.org/documentation/freeradius-server/3.2.8/unlang/redu...
redundant { radutmp sql_Fradius_log } ok
Which means:
redundant: try radutmp if that fails try sql if that fails return fail
OK
?
How about putitng the "ok" inside of the "redundant" block?
Alan DeKok.
Sorry, here is the log missing part in previous mail. (1) Received Accounting-Request Id 128 from 127.0.0.1:38016 to 127.0.0.1:1813 length 49 (1) User-Name = "testuser@domain" (1) Acct-Status-Type = Start (1) NAS-Port = 3 (1) # Executing section preacct from file /etc/raddb/sites-enabled/default (1) preacct { (1) [preprocess] = ok (1) policy acct_unique { (1) update request { (1) &Tmp-String-9 := "ai:" (1) } # update request = noop (1) if (("%{hex:&Class}" =~ /^%{hex:&Tmp-String-9}/) && ("%{string:&Class}" =~ /^ai:([0-9a-f]{32})/i)) { (1) EXPAND %{hex:&Class} (1) --> (1) EXPAND ^%{hex:&Tmp-String-9} (1) --> ^61693a (1) if (("%{hex:&Class}" =~ /^%{hex:&Tmp-String-9}/) && ("%{string:&Class}" =~ /^ai:([0-9a-f]{32})/i)) -> FALSE (1) else { (1) update request { (1) EXPAND %{md5:%{User-Name},%{Acct-Session-ID},%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}},%{NAS-Identifier},%{NAS-Port-ID},%{NAS-Port}} (1) --> 073b176091b6bacf69830880ad81e980 (1) &Acct-Unique-Session-Id := 073b176091b6bacf69830880ad81e980 (1) } # update request = noop (1) } # else = noop (1) update request { (1) &Tmp-String-9 !* ANY (1) } # update request = noop (1) } # policy acct_unique = noop (1) suffix: Checking for suffix after "@" (1) suffix: Looking up realm "domain" for User-Name = "testuser@domain" (1) suffix: No such realm "domain" (1) [suffix] = noop (1) [files] = noop (1) } # preacct = ok (1) # Executing section accounting from file /etc/raddb/sites-enabled/default (1) accounting { (1) if ("%{User-Name}" =~ /@/) { (1) EXPAND %{User-Name} (1) --> testuser@domain (1) if ("%{User-Name}" =~ /@/) -> TRUE (1) if ("%{User-Name}" =~ /@/) { (1) radutmp: EXPAND /opt/Fradius_log/shared/radius/radutmp (1) radutmp: --> /opt/Fradius_log/shared/radius/radutmp (1) radutmp: EXPAND %{User-Name} (1) radutmp: --> testuser@domain (1) [radutmp] = ok (1) sql_Fradius_log: EXPAND %{tolower:type.%{%{Acct-Status-Type}:-%{Request-Processing-Stage}}.query} (1) sql_Fradius_log: --> type.start.query (1) sql_Fradius_log: Using query template 'query' rlm_sql (sql_Fradius_log): Reserved connection (2) (1) sql_Fradius_log: EXPAND %{User-Name} (1) sql_Fradius_log: --> testuser@domain (1) sql_Fradius_log: SQL-User-Name set to 'testuser@domain' (1) sql_Fradius_log: EXPAND INSERT INTO radacct (acctsessionid, acctuniqueid, username, realm, nasipaddress, nasportid, nasporttype, acctstarttime, acctupdatetime, acctstoptime, acctsessiontime, acctauthentic, connectinfo_start, connectinfo_stop, acctinputoctets, acctoutputoctets, calledstationid, callingstationid, acctterminatecause, servicetype, framedprotocol, framedipaddress, framedipv6address, framedipv6prefix, framedinterfaceid, delegatedipv6prefix ) VALUES ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{%{NAS-Port-ID}:-%{NAS-Port}}', '%{NAS-Port-Type}', FROM_UNIXTIME(%{%{integer:Event-Timestamp}:-%l}), FROM_UNIXTIME(%{%{integer:Event-Timestamp}:-%l}), NULL, '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Framed-IPv6-Address}', '%{Framed-IPv6-Prefix}', '%{Framed-Interface-Id}', '%{Delegated-IPv6-Prefix}' ) (1) sql_Fradius_log: --> INSERT INTO radacct (acctsessionid, acctuniqueid, username, realm, nasipaddress, nasportid, nasporttype, acctstarttime, acctupdatetime, acctstoptime, acctsessiontime, acctauthentic, connectinfo_start, connectinfo_stop, acctinputoctets, acctoutputoctets, calledstationid, callingstationid, acctterminatecause, servicetype, framedprotocol, framedipaddress, framedipv6address, framedipv6prefix, framedinterfaceid, delegatedipv6prefix ) VALUES ('', '073b176091b6bacf69830880ad81e980', 'testuser@domain', '', '127.0.0.1', '3', '', FROM_UNIXTIME(1741879057), FROM_UNIXTIME(1741879057), NULL, '0', '', '', '', '0', '0', '', '', '', '', '', '', '', '', '', '' ) (1) sql_Fradius_log: Executing query: INSERT INTO radacct (acctsessionid, acctuniqueid, username, realm, nasipaddress, nasportid, nasporttype, acctstarttime, acctupdatetime, acctstoptime, acctsessiontime, acctauthentic, connectinfo_start, connectinfo_stop, acctinputoctets, acctoutputoctets, calledstationid, callingstationid, acctterminatecause, servicetype, framedprotocol, framedipaddress, framedipv6address, framedipv6prefix, framedinterfaceid, delegatedipv6prefix ) VALUES ('', '073b176091b6bacf69830880ad81e980', 'testuser@domain', '', '127.0.0.1', '3', '', FROM_UNIXTIME(1741879057), FROM_UNIXTIME(1741879057), NULL, '0', '', '', '', '0', '0', '', '', '', '', '', '', '', '', '', '' ) (1) sql_Fradius_log: ERROR: rlm_sql_mysql: ERROR 1927 (Connection was killed): 70100 (1) sql_Fradius_log: SQL query returned: server error rlm_sql (sql_Fradius_log): Released connection (2) Need more connections to reach 10 spares rlm_sql (sql_Fradius_log): Opening additional connection (7), 1 of 25 pending slots used rlm_sql_mysql: Starting connect to MySQL server rlm_sql_mysql: Couldn't connect to MySQL server root@10.0.0.79:Fradius rlm_sql_mysql: MySQL error: Can't connect to MySQL server on '10.0.0.79' (111) rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Opening connection failed (7) rlm_sql (sql_Fradius_log): Closing expired connection (5) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Closing expired connection (4) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Closing expired connection (3) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket rlm_sql (sql_Fradius_log): Closing expired connection (0) - Hit idle_timeout limit rlm_sql_mysql: Socket destructor called, closing socket (1) [sql_Fradius_log] = fail (1) } # if ("%{User-Name}" =~ /@/) = fail (1) } # accounting = fail (1) Not sending reply to client. (1) Finished request (1) Cleaning up request packet ID 128 with timestamp +68 due to done Ready to process requests
On 13 Mar 2025, at 10:55 PM, Alan DeKok <aland@deployingradius.com> wrote:
On Mar 13, 2025, at 4:53 PM, (null) (null) via Freeradius-Users <freeradius-users@lists.freeradius.org> wrote:
Tried the following settings, but it still doesn't work.
If only there was some kind of debug output which could help.
The accounting log breaks when SQL fails to connect, and it only returns successfully when the SQL server is up. I want to ensure that accounting responds even if it fails to save the log to radutmp or SQL.
1) read the debug output to see what's going on
2) write a policy (e.g. using the "redundant" keyword ) which handles this situation.
This is documented extensively.
Alan DeKok.
Hi null?, On 13 Mar 2025 at 2:02:32 PM, (null) (null) via Freeradius-Users < freeradius-users@lists.freeradius.org> wrote:
I have the accounting {} setting in /etc/raddb/sites-available/default. How can I prevent this configuration from breaking the accounting response if an SQL connection error occurs or radutmp fails to write to the file? The accounting response should continue even if there are logging errors.
accounting { if ("%{User-Name}" =~ /@/) { radutmp sql_Fradius_log } exec attr_filter.accounting_response log_accounting }
FreeRADIUS Version 3.2.7
This is probably what you are looking for: https://wiki.freeradius.org/config/Fail-over#rewriting-results-for-single-mo... This means that if SQL fails, you still reply and the SQL is never done. You may also want to look at the buffered-sql example, where during a failure of SQL, you can write to a buffer file, and then respond to the accounting message. The messages in this file is then read in and processed as though the messages have been freshly received. In this way, you get the SQL work done when it starts working again. https://github.com/FreeRADIUS/freeradius-server/blob/release_3_2_7/raddb/sit... -- Nathan Ward
participants (5)
-
(null) (null) -
Alan DeKok -
Arran Cudbard-Bell -
Bjørn Mork -
Nathan Ward