]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add reference based query selection for accounting and post-auth
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 22 Jul 2012 22:08:12 +0000 (23:08 +0100)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 24 Jul 2012 13:46:33 +0000 (09:46 -0400)
Add per section query log for accounting and post-auth

Update dialup.conf files to use new format

raddb/mods-available/sql
raddb/sql/mssql/dialup.conf
raddb/sql/mysql/dialup.conf
raddb/sql/oracle/dialup.conf
raddb/sql/postgresql/dialup.conf
src/modules/rlm_sql/conf.h
src/modules/rlm_sql/rlm_sql.c
src/modules/rlm_sql/rlm_sql.h
src/modules/rlm_sql/sql.c

index a0f7d6aa94d6fa332bcff1c8707ee090442a4f77..fe01d27f1cd870f6b210db7366c850f4ff4e0670 100644 (file)
@@ -41,7 +41,7 @@ sql {
        # Database table configuration for everything except Oracle
        radius_db = "radius"
        # If you are using Oracle then use this instead
-        # radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))"
+       # radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))"
 
        # If you want both stop and start records logged to the
        # same SQL table, leave this as is.  If you want them in
index e8c1f7caf2c393550fbd8d64d56cfe32908f7262..6bedf69a99f441aba2c83e32cd455c4e2a336092 100644 (file)
           ORDER BY priority"
 
        #######################################################################
-       #  Accounting Queries
+       # Accounting and Post-Auth Queries
        #######################################################################
-       # accounting_onoff_query        - query for Accounting On/Off packets
-       # accounting_update_query       - query for Accounting update packets
-       # accounting_update_query_alt   - query for Accounting update packets
-       #                               (alternate in case first query fails)
-       # accounting_start_query        - query for Accounting start packets
-       # accounting_start_query_alt    - query for Accounting start packets
-       #                               (alternate in case first query fails)
-       # accounting_stop_query         - query for Accounting stop packets
-       # accounting_stop_query_alt     - query for Accounting start packets
-       #                               (alternate in case first query doesn't
-       #                                affect any existing rows in the table)
+       # These queries insert/update accounting and authentication records.
+       # The query to use is determined by the value of 'reference'.
+       # This value is used as a configuration path and should resolve to one
+       # or more 'query's. If reference points to multiple queries, and a query
+       # fails, the next query is executed.
+       #
+       # Behaviour is identical to the old 1.x/2.x module, except we can now
+       # fail between N queries, and query selection can be based on any
+       # combination of attributes, or custom 'Acct-Status-Type' values.
        #######################################################################
-       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime='%S', AcctSessionTime=unix_timestamp('%S') - unix_timestamp(AcctStartTime), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time:-0} WHERE AcctStopTime=0 AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= '%S'"
-
-       accounting_update_query = "UPDATE ${acct_table1} SET FramedIPAddress = '%{Framed-IP-Address}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStopTime = 0"
-
-        accounting_update_query_alt = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPort, NASPortType, AcctSessionTime, AcctAuthentic, ConnectInfo_start, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, XAscendSessionSvrKey)  \
- VALUES('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{X-Ascend-Session-Svr-Key}')"
-
-       # accounting_start_query: Inserting of RadAcctId and AcctStopTime was
-       # removed. These fields are processing by a database
-        accounting_start_query = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPort, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay, XAscendSessionSvrKey) \
- VALUES('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0', '%{X-Ascend-Session-Svr-Key}')"
-
-       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = '%S', AcctStartDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime = 0"
+       accounting {
+               reference = "%{tolower:type.%{Acct-Status-Type}.query}"
 
-       accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = '%S', AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime = 0"
+               type {
+                       accounting-on {
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               AcctStopTime='%S', \
+                                               AcctSessionTime=unix_timestamp('%S') - \
+                                                       unix_timestamp(AcctStartTime), \
+                                               AcctTerminateCause='%{Acct-Terminate-Cause}', \
+                                               AcctStopDelay = %{Acct-Delay-Time:-0} \
+                                       WHERE AcctStopTime = 0 \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStartTime <= '%S'"
+                       }
+                       
+                       accounting-off {
+                               query = "${..accounting-on.query}"
+                       }
 
-       # accounting_stop_query_alt: Inserting of RadAcctId and AcctStartTime was
-       # removed. These fields are processing by a database
-       accounting_stop_query_alt = "INSERT into ${acct_table2} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPort, NASPortType, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time:-0}')"
+                       start {
+                               query = "\
+                                       INSERT INTO ${....acct_table1} \
+                                               (AcctSessionId,         AcctUniqueId,           UserName, \
+                                               Realm,                  NASIPAddress,           NASPort, \
+                                               NASPortType,            AcctStartTime,          AcctSessionTime, \
+                                               AcctAuthentic,          ConnectInfo_start,      ConnectInfo_stop, \
+                                               AcctInputOctets,        AcctOutputOctets,       CalledStationId, \
+                                               CallingStationId,       AcctTerminateCause,     ServiceType, \
+                                               FramedProtocol,         FramedIPAddress,        AcctStartDelay, \
+                                               AcctStopDelay,          XAscendSessionSvrKey) \
+                                       VALUES(\
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port-Id}', \
+                                               '%{NAS-Port-Type}', \
+                                               '%S', \
+                                               '0', \
+                                               '%{Acct-Authentic}', \
+                                               '%{Connect-Info}', \
+                                               '', \
+                                               '0', \
+                                               '0', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}', \
+                                               '%{Acct-Delay-Time}', \
+                                               '0', \
+                                               '%{X-Ascend-Session-Svr-Key}')"
+                                       
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               AcctStartTime = '%S', \
+                                               AcctStartDelay = '%{Acct-Delay-Time:-0}', \
+                                               ConnectInfo_start = '%{Connect-Info}' \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStopTime = 0"
+                       }
 
+                       interim-update {
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               FramedIPAddress = '%{Framed-IP-Address}' \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress= '%{NAS-IP-Address}' \
+                                       AND AcctStopTime = 0"
+                                       
+                               query = "\
+                                       INSERT INTO ${....acct_table1} \
+                                               (AcctSessionId,         AcctUniqueId,           UserName, \
+                                               Realm,                  NASIPAddress,           NASPort, \
+                                               NASPortType,            AcctSessionTime,        AcctAuthentic, \
+                                               ConnectInfo_start,      AcctInputOctets,        AcctOutputOctets, \
+                                               CalledStationId,        CallingStationId,       ServiceType, \
+                                               FramedProtocol,         FramedIPAddress,        AcctStartDelay, \
+                                               XAscendSessionSvrKey) \
+                                       VALUES(\
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port-Id}', \
+                                               '%{NAS-Port-Type}', \
+                                               '%{Acct-Session-Time}', \
+                                               '%{Acct-Authentic}', \
+                                               '', \
+                                               '%{Acct-Input-Octets}', \
+                                               '%{Acct-Output-Octets}', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}', \
+                                               '0', \
+                                               '%{X-Ascend-Session-Svr-Key}')"
+                       }
+                       
+                       stop {
+                               query = "\
+                                       UPDATE ${....acct_table2} \
+                                       SET \
+                                               AcctStopTime = '%S', \
+                                               AcctSessionTime = '%{Acct-Session-Time}', \
+                                               AcctInputOctets = '%{Acct-Input-Octets}', \
+                                               AcctOutputOctets = '%{Acct-Output-Octets}', \
+                                               AcctTerminateCause = '%{Acct-Terminate-Cause}', \
+                                               AcctStopDelay = '%{Acct-Delay-Time:-0}', \
+                                               ConnectInfo_stop = '%{Connect-Info}' \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStopTime = 0"
+                                       
+                               query = "\
+                                       INSERT into ${....acct_table2} \
+                                               (AcctSessionId,         AcctUniqueId,           UserName, \
+                                               Realm,                  NASIPAddress,           NASPort, \
+                                               NASPortType,            AcctStopTime,           AcctSessionTime, \
+                                               AcctAuthentic,          ConnectInfo_start,      ConnectInfo_stop, \
+                                               AcctInputOctets,        AcctOutputOctets,       CalledStationId, \
+                                               CallingStationId,       AcctTerminateCause,     ServiceType, \
+                                               FramedProtocol,         FramedIPAddress,        AcctStartDelay, \
+                                               AcctStopDelay) \
+                                       VALUES(\
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port-Id}', \
+                                               '%{NAS-Port-Type}', \
+                                               '%S', \
+                                               '%{Acct-Session-Time}', \
+                                               '%{Acct-Authentic}', \
+                                               '', \
+                                               '%{Connect-Info}', \
+                                               '%{Acct-Input-Octets}', \
+                                               '%{Acct-Output-Octets}', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Acct-Terminate-Cause}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}', \
+                                               '0', \
+                                               '%{Acct-Delay-Time:-0}')"
+                       }
+               }
+       }
+       
+       post-auth {
+       
+       }
index 10b1463fce2dded7630ceb330679a5f8065090e4..e87e7d728a9d1da22c469f25fecd892ef7ee260c 100644 (file)
        WHERE groupname = '%{Sql-Group}' \
        ORDER BY id"
 
-       #######################################################################
-       # Accounting Queries
-       #######################################################################
-       # accounting_onoff_query        - query for Accounting On/Off packets
-       # accounting_update_query       - query for Accounting update packets
-       # accounting_update_query_alt   - query for Accounting update packets
-       #                               (alternate in case first query fails)
-       # accounting_start_query        - query for Accounting start packets
-       # accounting_start_query_alt    - query for Accounting start packets
-       #                               (alternate in case first query fails)
-       # accounting_stop_query         - query for Accounting stop packets
-       # accounting_stop_query_alt     - query for Accounting start packets
-       #                               (alternate in case first query doesn't
-       #                               affect any existing rows in the table)
-       #######################################################################
-       accounting_onoff_query = "\
-       UPDATE ${acct_table1} \
-       SET \
-               acctstoptime    = FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               acctsessiontime = '%{integer:Event-Timestamp}' \
-                       - UNIX_TIMESTAMP(acctstarttime), \
-               acctterminatecause = '%{Acct-Terminate-Cause}', \
-       WHERE acctstoptime IS NULL \
-       AND nasipaddress        = '%{NAS-IP-Address}' \
-       AND acctstarttime       <= '%S'"
-
-       accounting_update_query = "\
-       UPDATE ${acct_table1} \
-       SET \
-               acctupdatetime  = (@acctupdatetime_old:=acctupdatetime), \
-               acctupdatetime  = FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               acctinterval    = \
-                       %{integer:Event-Timestamp} - UNIX_TIMESTAMP(@acctupdatetime_old), \
-               framedipaddress = '%{Framed-IP-Address}', \
-               acctsessiontime = '%{Acct-Session-Time}', \
-               acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' << 32 | \
-                       '%{%{Acct-Input-Octets}:-0}', \
-               acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' << 32 | \
-                       '%{%{Acct-Output-Octets}:-0}' \
-       WHERE acctsessionid     = '%{Acct-Session-Id}' \
-       AND username            = '%{SQL-User-Name}' \
-       AND nasipaddress        = '%{NAS-IP-Address}'"
-
-       accounting_update_query_alt = "\
-       INSERT INTO ${acct_table1} \
-               (acctsessionid,         acctuniqueid,           username, \
-               realm,                  nasipaddress,           nasportid, \
-               nasporttype,            acctstarttime,          acctupdatetime, \
-               acctsessiontime,        acctauthentic,          connectinfo_start, \
-               acctinputoctets,        acctoutputoctets,       calledstationid, \
-               callingstationid,       servicetype,            framedprotocol, \
-               framedipaddress) \
-       VALUES \
-               ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', \
-               '%{SQL-User-Name}', \
-               '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', \
-               '%{NAS-Port-Type}', \
-               FROM_UNIXTIME(%{integer:Event-Timestamp} - \
-                       %{%{Acct-Session-Time}:-0}), \
-               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               '%{Acct-Session-Time}', \
-               '%{Acct-Authentic}', '', \
-               '%{%{Acct-Input-Gigawords}:-0}' << 32 | \
-               '%{%{Acct-Input-Octets}:-0}', \
-               '%{%{Acct-Output-Gigawords}:-0}' << 32 | \
-               '%{%{Acct-Output-Octets}:-0}', \
-               '%{Called-Station-Id}', '%{Calling-Station-Id}', \
-               '%{Service-Type}', '%{Framed-Protocol}', \
-               '%{Framed-IP-Address}')"
-
-       accounting_start_query = "\
-       INSERT INTO ${acct_table1} \
-               (acctsessionid,         acctuniqueid,           username, \
-               realm,                  nasipaddress,           nasportid, \
-               nasporttype,            acctstarttime,          acctupdatetime, \
-               acctstoptime,           acctsessiontime,        acctauthentic, \
-               connectinfo_start,      connectinfo_stop,       acctinputoctets, \
-               acctoutputoctets,       calledstationid,        callingstationid, \
-               acctterminatecause,     servicetype,            framedprotocol, \
-               framedipaddress) \
-       VALUES \
-               ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', \
-               '%{SQL-User-Name}', \
-               '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', \
-               '%{NAS-Port-Type}', \
-               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               NULL, '0', '%{Acct-Authentic}', \
-               '%{Connect-Info}', '', '0', \
-               '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', \
-               '', '%{Service-Type}', '%{Framed-Protocol}', \
-               '%{Framed-IP-Address}')"
-
-       accounting_start_query_alt = "\
-       UPDATE ${acct_table1} SET \
-               acctstarttime   = FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               acctupdatetime  = FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               connectinfo_start = '%{Connect-Info}' \
-       WHERE acctsessionid     = '%{Acct-Session-Id}' \
-       AND username            = '%{SQL-User-Name}' \
-       AND nasipaddress        = '%{NAS-IP-Address}'"
-
-       accounting_stop_query = "\
-       UPDATE ${acct_table2} SET \
-               acctstoptime    = FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               acctsessiontime = '%{Acct-Session-Time}', \
-               acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' << 32 | \
-                       '%{%{Acct-Input-Octets}:-0}', \
-               acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' << 32 | \
-                       '%{%{Acct-Output-Octets}:-0}', \
-               acctterminatecause = '%{Acct-Terminate-Cause}', \
-               connectinfo_stop = '%{Connect-Info}' \
-       WHERE acctsessionid     = '%{Acct-Session-Id}' \
-       AND username            = '%{SQL-User-Name}' \
-       AND nasipaddress        = '%{NAS-IP-Address}'"
-
-       accounting_stop_query_alt = "\
-       INSERT INTO ${acct_table2} \
-               (acctsessionid,         acctuniqueid,           username, \
-               realm,                  nasipaddress,           nasportid, \
-               nasporttype,            acctstarttime,          acctupdatetime, \
-               acctstoptime,           acctsessiontime,        acctauthentic,  \
-               connectinfo_start,      connectinfo_stop,       acctinputoctets, \
-               acctoutputoctets,       calledstationid,        callingstationid, \
-               acctterminatecause,     servicetype,            framedprotocol, \
-               framedipaddress) \
-       VALUES \
-               ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', \
-               '%{SQL-User-Name}', \
-               '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', \
-               '%{NAS-Port-Type}', \
-               FROM_UNIXTIME(%{integer:Event-Timestamp} - \
-                       %{%{Acct-Session-Time}:-0}), \
-               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
-               '%{Acct-Session-Time}', '%{Acct-Authentic}', '', \
-               '%{Connect-Info}', \
-               '%{%{Acct-Input-Gigawords}:-0}' << 32 | \
-               '%{%{Acct-Input-Octets}:-0}', \
-               '%{%{Acct-Output-Gigawords}:-0}' << 32 | \
-               '%{%{Acct-Output-Octets}:-0}', \
-               '%{Called-Station-Id}', '%{Calling-Station-Id}', \
-               '%{Acct-Terminate-Cause}', \
-               '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}')"
-
        #######################################################################
        # Simultaneous Use Checking Queries
        #######################################################################
        # simul_count_query     - query for the number of current connections
        #                       - If this is not defined, no simultaneouls use checking
        #                       - will be performed by this module instance
-       # simul_verify_query    - query to return details of current connections for verification
+       # simul_verify_query    - query to return details of current connections
+       #                               for verification
        #                       - Leave blank or commented out to disable verification step
        #                       - Note that the returned field order should not be changed.
        #######################################################################
        WHERE username = '%{SQL-User-Name}' \
        AND acctstoptime IS NULL"
 
+       #######################################################################
+       # Accounting and Post-Auth Queries
+       #######################################################################
+       # These queries insert/update accounting and authentication records.
+       # The query to use is determined by the value of 'reference'.
+       # This value is used as a configuration path and should resolve to one
+       # or more 'query's. If reference points to multiple queries, and a query
+       # fails, the next query is executed.
+       #
+       # Behaviour is identical to the old 1.x/2.x module, except we can now
+       # fail between N queries, and query selection can be based on any
+       # combination of attributes, or custom 'Acct-Status-Type' values.
+       #######################################################################
+       accounting {
+               reference = "%{tolower:type.%{Acct-Status-Type}.query}"
+
+               column_list = "\
+                       acctsessionid,          acctuniqueid,           username, \
+                       realm,                  nasipaddress,           nasportid, \
+                       nasporttype,            acctstarttime,          acctupdatetime, \
+                       acctstoptime,           acctsessiontime,        acctauthentic, \
+                       connectinfo_start,      connectinfo_stop,       acctinputoctets, \
+                       acctoutputoctets,       calledstationid,        callingstationid, \
+                       acctterminatecause,     servicetype,            framedprotocol, \
+                       framedipaddress"
+                       
+               type {
+                       accounting-on {
+                               #
+                               #  Bulk terminate all sessions associated with a given NAS
+                               #
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               acctstoptime = FROM_UNIXTIME(\
+                                                       %{integer:Event-Timestamp}), \
+                                               acctsessiontime = '%{integer:Event-Timestamp}' \
+                                                       - UNIX_TIMESTAMP(acctstarttime), \
+                                               acctterminatecause = '%{Acct-Terminate-Cause}' \
+                                       WHERE acctstoptime IS NULL \
+                                       AND nasipaddress   = '%{NAS-IP-Address}' \
+                                       AND acctstarttime <= FROM_UNIXTIME(\
+                                               %{integer:Event-Timestamp})"
+                       }
+                       
+                       accounting-off {
+                               query = "${..accounting-on.query}"
+                       }
+                       
+                       start {
+                               #
+                               #  Insert a new record into the sessions table
+                               #
+                               query = "\
+                                       INSERT INTO ${....acct_table1} \
+                                               (${...column_list}) \
+                                       VALUES \
+                                               ('%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port}', \
+                                               '%{NAS-Port-Type}', \
+                                               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
+                                               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
+                                               NULL, \
+                                               '0', \
+                                               '%{Acct-Authentic}', \
+                                               '%{Connect-Info}', \
+                                               '', \
+                                               '0', \
+                                               '0', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}')"
+                                               
+                               #
+                               #  Key constraints prevented us from inserting a new session,
+                               #  use the alternate query to update an existing session.
+                               #
+                               query = "\
+                                       UPDATE ${....acct_table1} SET \
+                                               acctstarttime   = FROM_UNIXTIME(\
+                                                       %{integer:Event-Timestamp}), \
+                                               acctupdatetime  = FROM_UNIXTIME(\
+                                                       %{integer:Event-Timestamp}), \
+                                               connectinfo_start = '%{Connect-Info}' \
+                                       WHERE acctsessionid = '%{Acct-Session-Id}' \
+                                       AND username            = '%{SQL-User-Name}' \
+                                       AND nasipaddress        = '%{NAS-IP-Address}'"
+                       }
+                       
+                       interim-update {
+                               #
+                               #  Update an existing session and calculate the interval
+                               #  between the last data we received for the session and this 
+                               #  update. This can be used to find stale sessions.
+                               #
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               acctupdatetime  = (\
+                                                       @acctupdatetime_old:=acctupdatetime), \
+                                               acctupdatetime  = FROM_UNIXTIME(\
+                                                       %{integer:Event-Timestamp}), \
+                                               acctinterval    = %{integer:Event-Timestamp} - \
+                                                       UNIX_TIMESTAMP(@acctupdatetime_old), \
+                                               framedipaddress = '%{Framed-IP-Address}', \
+                                               acctsessiontime = '%{Acct-Session-Time}', \
+                                               acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' \
+                                                       << 32 | '%{%{Acct-Input-Octets}:-0}', \
+                                               acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' \
+                                                       << 32 | '%{%{Acct-Output-Octets}:-0}' \
+                                       WHERE acctsessionid     = '%{Acct-Session-Id}' \
+                                       AND username            = '%{SQL-User-Name}' \
+                                       AND nasipaddress        = '%{NAS-IP-Address}'"
+                               
+                               #
+                               #  The update condition matched no existing sessions. Use
+                               #  the values provided in the update to create a new session.
+                               #
+                               query = "\
+                                       INSERT INTO ${....acct_table1} \
+                                               (${...column_list}) \
+                                       VALUES \
+                                               ('%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port}', \
+                                               '%{NAS-Port-Type}', \
+                                               FROM_UNIXTIME(%{integer:Event-Timestamp} - \
+                                                       %{%{Acct-Session-Time}:-0}), \
+                                               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
+                                               '%{Acct-Session-Time}', \
+                                               '%{Acct-Authentic}', '', \
+                                               '%{%{Acct-Input-Gigawords}:-0}' << 32 | \
+                                                       '%{%{Acct-Input-Octets}:-0}', \
+                                               '%{%{Acct-Output-Gigawords}:-0}' << 32 | \
+                                                       '%{%{Acct-Output-Octets}:-0}', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}')"
+                       }
+               
+                       stop {
+                               #
+                               #  Session has terminated, update the stop time and statistics.
+                               #
+                               query = "\
+                                       UPDATE ${....acct_table2} SET \
+                                               acctstoptime    = FROM_UNIXTIME(\
+                                                       %{integer:Event-Timestamp}), \
+                                               acctsessiontime = '%{Acct-Session-Time}', \
+                                               acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' \
+                                                       << 32 | '%{%{Acct-Input-Octets}:-0}', \
+                                               acctoutputoctets = '%{%{Acct-Output-Gigawords}:-0}' \
+                                                       << 32 | '%{%{Acct-Output-Octets}:-0}', \
+                                               acctterminatecause = '%{Acct-Terminate-Cause}', \
+                                               connectinfo_stop = '%{Connect-Info}' \
+                                       WHERE acctsessionid     = '%{Acct-Session-Id}' \
+                                       AND username            = '%{SQL-User-Name}' \
+                                       AND nasipaddress        = '%{NAS-IP-Address}'"
+                               
+                               #
+                               #  The update condition matched no existing sessions. Use
+                               #  the values provided in the update to create a new session.
+                               #
+                               query = "\
+                                       INSERT INTO ${....acct_table2} \
+                                               (${...column_list}) \
+                                       VALUES \
+                                               ('%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port}', \
+                                               '%{NAS-Port-Type}', \
+                                               FROM_UNIXTIME(%{integer:Event-Timestamp} - \
+                                                       %{%{Acct-Session-Time}:-0}), \
+                                               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
+                                               FROM_UNIXTIME(%{integer:Event-Timestamp}), \
+                                               '%{Acct-Session-Time}', \
+                                               '%{Acct-Authentic}', '', \
+                                               '%{Connect-Info}', \
+                                               '%{%{Acct-Input-Gigawords}:-0}' << 32 | \
+                                                       '%{%{Acct-Input-Octets}:-0}', \
+                                               '%{%{Acct-Output-Gigawords}:-0}' << 32 | \
+                                                       '%{%{Acct-Output-Octets}:-0}', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Acct-Terminate-Cause}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}')"
+                       }
+               }
+       }
+       
        #######################################################################
        # Authentication Logging Queries
        #######################################################################
        # postauth_query        - Insert some info after authentication
        #######################################################################
 
-       postauth_query = "\
-       INSERT INTO ${postauth_table} \
-       (username, pass, reply, authdate) \
-       VALUES ( \
-       '%{SQL-User-Name}', \
-       '%{%{User-Password}:-%{Chap-Password}}', \
-       '%{reply:Packet-Type}', '%S')"
-
+       post-auth { 
+               query = "\
+                       INSERT INTO ${..postauth_table} \
+                               (username, pass, reply, authdate) \
+                       VALUES ( \
+                               '%{SQL-User-Name}', \
+                               '%{%{User-Password}:-%{Chap-Password}}', \
+                               '%{reply:Packet-Type}', \
+                               '%S')"
+       }
index 5820cb493b8fbad1cbcdcd55dc8ddae6f4b02fb7..76fc6eccead27b010b3229db17bd7d9707612925 100644 (file)
        authorize_group_check_query = "SELECT ${groupcheck_table}.id,${groupcheck_table}.GroupName,${groupcheck_table}.Attribute,${groupcheck_table}.Value,${groupcheck_table}.op  FROM ${groupcheck_table},${usergroup_table} WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName ORDER BY ${groupcheck_table}.id"
        authorize_group_reply_query = "SELECT ${groupreply_table}.id,${groupreply_table}.GroupName,${groupreply_table}.Attribute,${groupreply_table}.Value,${groupreply_table}.op  FROM ${groupreply_table},${usergroup_table} WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName ORDER BY ${groupreply_table}.id"
 
-       #######################################################################
-       #  Accounting Queries
-       #######################################################################
-       # accounting_onoff_query        - query for Accounting On/Off packets 
-       # accounting_update_query       - query for Accounting update packets 
-       # accounting_update_query_alt   - query for Accounting update packets 
-       #                               (alternate in case first query fails)
-       # accounting_start_query        - query for Accounting start packets 
-       # accounting_start_query_alt    - query for Accounting start packets 
-       #                               (alternate in case first query fails)
-       # accounting_stop_query         - query for Accounting stop packets 
-       # accounting_stop_query_alt     - query for Accounting start packets 
-       #                               (alternate in case first query doesn't
-       #                                affect any existing rows in the table)
-       #######################################################################
-       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime=TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctSessionTime=round((TO_DATE('%S','yyyy-mm-dd hh24:mi:ss')-TO_DATE(TO_CHAR(acctstarttime, 'yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss'))*86400), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time:-0} WHERE AcctStopTime IS NULL AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStartTime <= TO_DATE('%S','yyyy-mm-dd hh24:mi:ss')"
-
-accounting_update_query = "UPDATE ${acct_table1} \
-    SET FramedIPAddress = NULLIF('%{Framed-IP-Address}', ''), \
-    AcctSessionTime = '%{Acct-Session-Time}', \
-    AcctInputOctets = '%{Acct-Input-Octets}' + ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
-    AcctOutputOctets = '%{Acct-Output-Octets}' +  ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296) \
-    WHERE \
-    AcctSessionId = '%{Acct-Session-Id}' AND \
-    UserName = '%{SQL-User-Name}' AND \
-    NASIPAddress= '%{NAS-IP-Address}' AND \
-    AcctStopTime IS NULL" 
-
-accounting_update_query_alt = "INSERT into ${acct_table1} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, XAscendSessionSvrKey) \
-    VALUES('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', \
-    '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', \
-    '%{NAS-Port-Type}', NULL, '%{Acct-Session-Time}', '%{Acct-Authentic}', '', \
-    '%{Acct-Input-Octets}' + ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
-    '%{Acct-Output-Octets}' +  ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296), \
-    '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', \
-    '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{X-Ascend-Session-Svr-Key}')"
-
-        accounting_start_query = "INSERT into ${acct_table1} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay, XAscendSessionSvrKey) \
- VALUES('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), NULL, '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0', '%{X-Ascend-Session-Svr-Key}')"
-
-       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctStartDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
-
-       accounting_stop_query = "UPDATE ${acct_table2} \
-    SET AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \
-    AcctSessionTime = '%{Acct-Session-Time}', \
-    AcctInputOctets = '%{Acct-Input-Octets}' + ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
-    AcctOutputOctets = '%{Acct-Output-Octets}' +  ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296), \
-    AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
-
-       # Optional Query - pnixon
-       #accounting_stop_query =3D "UPDATE ${acct_table2} SET AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctSessionTime = (substr((sysdate-acctstarttime),instr((sysdate-acctstarttime),' ')+7,2) + substr((sysdate-acctstarttime),instr((sysdate-acctstarttime),' ')+4,2)*60 + substr((sysdate-acctstarttime),instr((sysdate-acctstarttime),' ')+1,2)*3600 + trunc(to_number(substr((sysdate-acctstarttime),1,instr(sysdate-acctstarttime,' '))))*86400), AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId =3D '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL" 
-
-accounting_stop_query_alt = "INSERT into ${acct_table2} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) \
-    VALUES('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', \
-    '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', NULL, TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \
-    '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', \
-    '%{Acct-Input-Octets}' + ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
-    '%{Acct-Output-Octets}' +  ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296), \
-    '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', \
-    '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time:-0}')"
-
        #######################################################################
        # Simultaneous Use Checking Queries
        #######################################################################
@@ -179,14 +118,215 @@ accounting_stop_query_alt = "INSERT into ${acct_table2} (RadAcctId, AcctSessionI
 
        group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE UserName='%{SQL-User-Name}'"
 
-        # Authentication Logging Queries
-        #######################################################################
-        # postauth_query                - Insert some info after authentication
-        #######################################################################
+       #######################################################################
+       # Accounting and Post-Auth Queries
+       #######################################################################
+       # These queries insert/update accounting and authentication records.
+       # The query to use is determined by the value of 'reference'.
+       # This value is used as a configuration path and should resolve to one
+       # or more 'query's. If reference points to multiple queries, and a query
+       # fails, the next query is executed.
+       #
+       # Behaviour is identical to the old 1.x/2.x module, except we can now
+       # fail between N queries, and query selection can be based on any
+       # combination of attributes, or custom 'Acct-Status-Type' values.
+       #######################################################################
+       accounting {
+               reference = "%{tolower:type.%{Acct-Status-Type}.query}"
+               
+               type {
+                       accounting-on {
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \
+                                               AcctSessionTime = round((TO_DATE('%S','yyyy-mm-dd hh24:mi:ss') - \
+                                                       TO_DATE(TO_CHAR(acctstarttime, 'yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss'))*86400), \
+                                               AcctTerminateCause='%{Acct-Terminate-Cause}', \
+                                               AcctStopDelay = %{Acct-Delay-Time:-0} \
+                                       WHERE AcctStopTime IS NULL \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStartTime <= TO_DATE('%S','yyyy-mm-dd hh24:mi:ss')"
+                       }
+                       
+                       accounting-off {
+                               query = "${..accounting-on.query}"
+                       }
+                       
+                       start {
+                               query = "\
+                                       INSERT INTO ${....acct_table1} \
+                                               (RadAcctId,             AcctSessionId,          AcctUniqueId, \
+                                               UserName,               Realm,                  NASIPAddress, \
+                                               NASPortId,              NASPortType,            AcctStartTime, \
+                                               AcctStopTime,           AcctSessionTime,        AcctAuthentic, \
+                                               ConnectInfo_start,      ConnectInfo_stop,       AcctInputOctets, \
+                                               AcctOutputOctets,       CalledStationId,        CallingStationId, \
+                                               AcctTerminateCause,     ServiceType,            FramedProtocol, \
+                                               FramedIPAddress,        AcctStartDelay,         AcctStopDelay, \
+                                               XAscendSessionSvrKey) \
+                                       VALUES(\
+                                               '', \
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port-Id}', \
+                                               '%{NAS-Port-Type}', \
+                                               TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \
+                                               NULL, \
+                                               '0', \
+                                               '%{Acct-Authentic}', \
+                                               '%{Connect-Info}', \
+                                               '', \
+                                               '0', \
+                                               '0', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}', \
+                                               '%{Acct-Delay-Time}', \
+                                               '0', \
+                                               '%{X-Ascend-Session-Svr-Key}')"
+                                               
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               AcctStartTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \
+                                               AcctStartDelay = '%{Acct-Delay-Time:-0}', \
+                                               ConnectInfo_start = '%{Connect-Info}' \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStopTime IS NULL"
+                       }
+                       
+                       interim-update {
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               FramedIPAddress = NULLIF('%{Framed-IP-Address}', ''), \
+                                               AcctSessionTime = '%{Acct-Session-Time}', \
+                                               AcctInputOctets = '%{Acct-Input-Octets}' + \
+                                                       ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
+                                               AcctOutputOctets = '%{Acct-Output-Octets}' +  \
+                                                       ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296) \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress= '%{NAS-IP-Address}' \
+                                       AND AcctStopTime IS NULL" 
+                                       
+                               query = "\
+                                       INSERT into ${....acct_table1} \
+                                               (RadAcctId,             AcctSessionId,          AcctUniqueId, \
+                                               UserName,               Realm,                  NASIPAddress, \
+                                               NASPortId,              NASPortType,            AcctStartTime, \
+                                               AcctSessionTime,        AcctAuthentic,          ConnectInfo_start, \
+                                               AcctInputOctets,        AcctOutputOctets,       CalledStationId, \
+                                               CallingStationId,       ServiceType,            FramedProtocol, \
+                                               FramedIPAddress,        AcctStartDelay,         XAscendSessionSvrKey) \
+                                       VALUES(\
+                                               '', \
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port-Id}', \
+                                               '%{NAS-Port-Type}', \
+                                               NULL, \
+                                               '%{Acct-Session-Time}', \
+                                               '%{Acct-Authentic}', \
+                                               '', \
+                                               '%{Acct-Input-Octets}' + \
+                                                       ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
+                                               '%{Acct-Output-Octets}' +  \
+                                                       ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296), \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}', \
+                                               '0', \
+                                               '%{X-Ascend-Session-Svr-Key}')"
+                       }
+                       
+                       stop {
+                               query = "\
+                                       UPDATE ${....acct_table2} \
+                                       SET \
+                                               AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \
+                                               AcctSessionTime = '%{Acct-Session-Time}', \
+                                               AcctInputOctets = '%{Acct-Input-Octets}' + \
+                                                       ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
+                                               AcctOutputOctets = '%{Acct-Output-Octets}' +  \
+                                                       ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296), \
+                                               AcctTerminateCause = '%{Acct-Terminate-Cause}', \
+                                               AcctStopDelay = '%{Acct-Delay-Time:-0}', \
+                                               ConnectInfo_stop = '%{Connect-Info}' \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStopTime IS NULL"
+                                       
+                               query = "\
+                                       "INSERT into ${....acct_table2} \
+                                               (RadAcctId,             AcctSessionId,          AcctUniqueId, \
+                                                UserName,              Realm,                  NASIPAddress, \
+                                                NASPortId,             NASPortType,            AcctStartTime, \
+                                                AcctStopTime,          AcctSessionTime,        AcctAuthentic, \
+                                                ConnectInfo_start,     ConnectInfo_stop,       AcctInputOctets, \
+                                                AcctOutputOctets,      CalledStationId,        CallingStationId, \
+                                                AcctTerminateCause,    ServiceType,            FramedProtocol, \
+                                                FramedIPAddress,       AcctStartDelay,         AcctStopDelay) \
+                                       VALUES(\
+                                               '', \
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               '%{Realm}', \
+                                               '%{NAS-IP-Address}', \
+                                               '%{NAS-Port-Id}', \
+                                               '%{NAS-Port-Type}', \
+                                               NULL, \
+                                               TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \
+                                               '%{Acct-Session-Time}', \
+                                               '%{Acct-Authentic}', \
+                                               '', \
+                                               '%{Connect-Info}', \
+                                               '%{Acct-Input-Octets}' + \
+                                                       ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \
+                                               '%{Acct-Output-Octets}' + \
+                                                       ('%{%{Acct-Output-Gigawords}:-0}' * 4294967296), \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Acct-Terminate-Cause}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               '%{Framed-IP-Address}', \
+                                               '0', \
+                                               '%{Acct-Delay-Time:-0}')"
+
+                       }
+               }
+       }
+
+       #######################################################################
+       # Authentication Logging Queries
+       #######################################################################
+       # postauth_query                - Insert some info after authentication
+       #######################################################################
 
-        postauth_query = "INSERT INTO ${postauth_table} \
-                          (username, pass, reply, authdate) \
-                          VALUES ( \
-                          '%{User-Name}', \
-                          '%{%{User-Password}:-%{Chap-Password}}', \
-                          '%{reply:Packet-Type}', TO_TIMESTAMP('%S','YYYY-MM-DDHH24:MI:SS'))"
+       post-auth {
+        query = "\
+               INSERT INTO ${..postauth_table} \
+                       (username, pass, reply, authdate) \
+            VALUES (\
+                '%{User-Name}', \
+                '%{%{User-Password}:-%{Chap-Password}}', \
+                '%{reply:Packet-Type}', \
+                TO_TIMESTAMP('%S','YYYY-MM-DDHH24:MI:SS'))"
+       }
\ No newline at end of file
index aa1907f28862bb019bd8e8f5055a880169b9c5ce..446acb6c67bd857b90a55408f216f980f94067f6 100644 (file)
-# -*- text -*-
-##
-## dialup.conf -- PostgreSQL configuration for default schema (schema.sql)
-##
-##     $Id$
-
-# Safe characters list for sql queries. Everything else is replaced
-# with their mime-encoded equivalents.
-# The default list should be ok
-# safe-characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"
-
-#######################################################################
-#  Query config:  Username
-#######################################################################
-# This is the username that will get substituted, escaped, and added
-# as attribute 'SQL-User-Name'.  '%{SQL-User-Name}' should be used
-# below everywhere a username substitution is needed so you you can
-# be sure the username passed from the client is escaped properly.
-#
-# Uncomment the next line, if you want the sql_user_name to mean:
-#
-#    Use Stripped-User-Name, if it's there.
-#    Else use User-Name, if it's there,
-#    Else use hard-coded string "none" as the user name.
-#
-#sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-none}}"
-
-sql_user_name = "%{User-Name}"
-
-#######################################################################
-#  Default profile
-#######################################################################
-# This is the default profile. It is found in SQL by group membership.
-# That means that this profile must be a member of at least one group
-# which will contain the corresponding check and reply items.
-# This profile will be queried in the authorize section for every user.
-# The point is to assign all users a default profile without having to
-# manually add each one to a group that will contain the profile.
-# The SQL module will also honor the User-Profile attribute. This
-# attribute can be set anywhere in the authorize section (ie the users
-# file). It is found exactly as the default profile is found.
-# If it is set then it will *overwrite* the default profile setting.
-# The idea is to select profiles based on checks on the incoming
-# packets, not on user group membership. For example:
-# -- users file --
-# DEFAULT      Service-Type == Outbound-User, User-Profile := "outbound"
-# DEFAULT      Service-Type == Framed-User, User-Profile := "framed"
-#
-# By default the default_user_profile is not set
-#
-# default_user_profile = "DEFAULT"
-
-#######################################################################
-#  NAS Query
-#######################################################################
-#  This query retrieves the radius clients
-#
-#  0. Row ID (currently unused)
-#  1. Name (or IP address)
-#  2. Shortname
-#  3. Type
-#  4. Secret
-#  5. Server
-#######################################################################
-
-nas_query = "SELECT id, nasname, shortname, type, secret, server FROM ${nas_table}"
-
-#######################################################################
-#  Authorization Queries
-#######################################################################
-#  These queries compare the check items for the user
-#  in ${authcheck_table} and setup the reply items in
-#  ${authreply_table}.  You can use any query/tables
-#  you want, but the return data for each row MUST
-#  be in the  following order:
-#
-#  0. Row ID (currently unused)
-#  1. UserName/GroupName
-#  2. Item Attr Name
-#  3. Item Attr Value
-#  4. Item Attr Operation
-#######################################################################
-
-# Use these for case insensitive usernames. WARNING: Slower queries!
-# authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
-#   FROM ${authcheck_table} \
-#   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
-#   ORDER BY id"
-# authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
-#   FROM ${authreply_table} \
-#   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
-#   ORDER BY id"
-
-authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
-  FROM ${authcheck_table} \
-  WHERE Username = '%{SQL-User-Name}' \
-  ORDER BY id"
-
-authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
-  FROM ${authreply_table} \
-  WHERE Username = '%{SQL-User-Name}' \
-  ORDER BY id"
-
-# Use these for case insensitive usernames. WARNING: Slower queries!
-# authorize_group_check_query = "SELECT ${groupcheck_table}.id, ${groupcheck_table}.GroupName, \
-#   ${groupcheck_table}.Attribute, ${groupcheck_table}.Value, ${groupcheck_table}.Op \
-#   FROM ${groupcheck_table}, ${usergroup_table} \
-#   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName \
-#   ORDER BY ${groupcheck_table}.id"
-# authorize_group_reply_query = "SELECT ${groupreply_table}.id, ${groupreply_table}.GroupName, \
-#   ${groupreply_table}.Attribute, ${groupreply_table}.Value, ${groupreply_table}.Op \
-#   FROM ${groupreply_table}, ${usergroup_table} \
-#   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName \
-#   ORDER BY ${groupreply_table}.id"
-
-authorize_group_check_query = "SELECT id, GroupName, Attribute, Value, op \
-  FROM ${groupcheck_table} \
-  WHERE GroupName = '%{Sql-Group}' \
-  ORDER BY id"
-
-authorize_group_reply_query = "SELECT id, GroupName, Attribute, Value, op \
-  FROM ${groupreply_table} \
-  WHERE GroupName = '%{Sql-Group}' \
-  ORDER BY id"
-
-#######################################################################
-# Simultaneous Use Checking Queries
-#######################################################################
-# simul_count_query     - query for the number of current connections
-#                       - If this is not defined, no simultaneous use checking
-#                       - will be performed by this module instance
-# simul_verify_query    - query to return details of current connections for verification
-#                       - Leave blank or commented out to disable verification step
-#                       - Note that the returned field order should not be changed.
-#######################################################################
-
-# Uncomment simul_count_query to enable simultaneous use checking
-# simul_count_query = "SELECT COUNT(*) FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
-# simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
-
-
-
-#######################################################################
-#  Accounting Queries
-#######################################################################
-# accounting_onoff_query       - query for Accounting On/Off packets
-# accounting_update_query      - query for Accounting update packets
-# accounting_update_query_alt  - query for Accounting update packets
-#                               (alternate in case first query fails)
-# accounting_start_query       - query for Accounting start packets
-# accounting_start_query_alt   - query for Accounting start packets
-#                               (alternate in case first query fails)
-# accounting_stop_query                - query for Accounting stop packets
-# accounting_stop_query_alt    - query for Accounting start packets
-#                               (alternate in case first query doesn't
-#                                affect any existing rows in the table)
-#######################################################################
-
-accounting_onoff_query = "UPDATE ${acct_table1} \
-  SET AcctStopTime = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
-  AcctSessionTime = (EXTRACT(EPOCH FROM ('%S'::timestamp with time zone - AcctStartTime::timestamp with time zone \
-  - '%{%{Acct-Delay-Time}:-0}'::interval)))::BIGINT, \
-  AcctTerminateCause = '%{Acct-Terminate-Cause}', \
-  AcctStopDelay = 0 \
-  WHERE AcctStopTime IS NULL \
-  AND NASIPAddress= '%{NAS-IP-Address}' \
-  AND AcctStartTime <= '%S'::timestamp"
-
-accounting_update_query = "UPDATE ${acct_table1} \
-  SET FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
-  AcctSessionTime = '%{Acct-Session-Time}', \
-  AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
-  AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint) \
-  WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' \
-  AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
-
-accounting_update_query_alt = "INSERT INTO ${acct_table1} \
-  (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, \
-  NASPortId, NASPortType, AcctStartTime, \
-  AcctSessionTime, AcctAuthentic, AcctInputOctets, \
-  AcctOutputOctets, CalledStationId, CallingStationId, \
-  ServiceType, FramedProtocol, FramedIPAddress, XAscendSessionSvrKey) \
-  VALUES('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', \
-  '%{SQL-User-Name}', NULLIF('%{Realm}', ''), '%{NAS-IP-Address}', \
-  %{%{NAS-Port}:-NULL}, '%{NAS-Port-Type}', \
-  ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval - '%{%{Acct-Session-Time}:-0}'::interval), \
-  '%{Acct-Session-Time}', '%{Acct-Authentic}', \
-  (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
-  (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint), \
-  '%{Called-Station-Id}', \
-  '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', \
-  NULLIF('%{Framed-IP-Address}', '')::inet, '%{X-Ascend-Session-Svr-Key}')"
-
-accounting_start_query = "INSERT INTO ${acct_table1} \
-  (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, \
-   NASPortId, NASPortType, AcctStartTime, AcctAuthentic, \
-  ConnectInfo_start, CalledStationId, CallingStationId, ServiceType, \
-  FramedProtocol, FramedIPAddress, AcctStartDelay, XAscendSessionSvrKey) \
-  VALUES('%{Acct-Session-Id}', \
-  '%{Acct-Unique-Session-Id}', \
-  '%{SQL-User-Name}', \
-  NULLIF('%{Realm}', ''), \
-  '%{NAS-IP-Address}', \
-  %{%{NAS-Port}:-NULL}, \
-  '%{NAS-Port-Type}', \
-  ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
-  '%{Acct-Authentic}', \
-  '%{Connect-Info}', \
-  '%{Called-Station-Id}', \
-  '%{Calling-Station-Id}', \
-  '%{Service-Type}', \
-  '%{Framed-Protocol}', \
-  NULLIF('%{Framed-IP-Address}', '')::inet, \
-  0, \
-  '%{X-Ascend-Session-Svr-Key}')"
-
-accounting_start_query_alt  = "UPDATE ${acct_table1} \
-  SET AcctStartTime = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
-  AcctStartDelay = 0, \
-  ConnectInfo_start = '%{Connect-Info}' \
-  WHERE AcctSessionId = '%{Acct-Session-Id}' \
-  AND UserName = '%{SQL-User-Name}' \
-  AND NASIPAddress = '%{NAS-IP-Address}' \
-  AND AcctStopTime IS NULL"
-
-accounting_stop_query = "UPDATE ${acct_table2} \
-  SET AcctStopTime = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
-  AcctSessionTime = CASE WHEN '%{Acct-Session-Time}' = '' THEN \
-  (EXTRACT(EPOCH FROM ('%S'::TIMESTAMP WITH TIME ZONE - AcctStartTime::TIMESTAMP WITH TIME ZONE \
-  - '%{%{Acct-Delay-Time}:-0}'::INTERVAL)))::BIGINT \
-  ELSE NULLIF('%{Acct-Session-Time}','')::BIGINT END, \
-  AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
-  AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint), \
-  AcctTerminateCause = '%{Acct-Terminate-Cause}', \
-  AcctStopDelay = 0, \
-  FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
-  ConnectInfo_stop = '%{Connect-Info}' \
-  WHERE AcctSessionId = '%{Acct-Session-Id}' \
-  AND UserName = '%{SQL-User-Name}' \
-  AND NASIPAddress = '%{NAS-IP-Address}' \
-  AND AcctStopTime IS NULL"
-
-accounting_stop_query_alt = "INSERT INTO ${acct_table2} \
-  (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, \
-  AcctSessionTime, AcctAuthentic, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, \
-  CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStopDelay) \
-  values('%{Acct-Session-Id}', \
-  '%{Acct-Unique-Session-Id}', \
-  '%{SQL-User-Name}', \
-  NULLIF('%{Realm}', ''), \
-  '%{NAS-IP-Address}', \
-  %{%{NAS-Port}:-NULL}, \
-  '%{NAS-Port-Type}', \
-  ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval - '%{%{Acct-Session-Time}:-0}'::interval), \
-  ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
-  NULLIF('%{Acct-Session-Time}', '')::bigint, '%{Acct-Authentic}', \
-  '%{Connect-Info}', \
-  (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Input-Octets}:-0}'::bigint), \
-  (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + '%{%{Acct-Output-Octets}:-0}'::bigint), \
-  '%{Called-Station-Id}', \
-  '%{Calling-Station-Id}', \
-  '%{Acct-Terminate-Cause}', \
-  '%{Service-Type}', \
-  '%{Framed-Protocol}', \
-  NULLIF('%{Framed-IP-Address}', '')::inet, 0)"
-
-#######################################################################
-# Group Membership Queries
-#######################################################################
-# group_membership_query        - Check user group membership
-#######################################################################
-
-# Use these for case insensitive usernames. WARNING: Slower queries!
-# group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') ORDER BY priority"
-
-group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE UserName='%{SQL-User-Name}' ORDER BY priority"
-
-#######################################################################
-# Authentication Logging Queries
-#######################################################################
-# postauth_query                - Insert some info after authentication
-#######################################################################
-postauth_query = "INSERT INTO ${postauth_table} (username, pass, reply, authdate) \
-  VALUES ('%{User-Name}', '%{%{User-Password}:-Chap-Password}', '%{reply:Packet-Type}', NOW())"
-
+       # -*- text -*-
+       ##
+       ## dialup.conf -- PostgreSQL configuration for default schema (schema.sql)
+       ##
+       ##      $Id$
+       
+       # Safe characters list for sql queries. Everything else is replaced
+       # with their mime-encoded equivalents.
+       # The default list should be ok
+       # safe-characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"
+       
+       #######################################################################
+       #  Query config:  Username
+       #######################################################################
+       # This is the username that will get substituted, escaped, and added
+       # as attribute 'SQL-User-Name'.  '%{SQL-User-Name}' should be used
+       # below everywhere a username substitution is needed so you you can
+       # be sure the username passed from the client is escaped properly.
+       #
+       # Uncomment the next line, if you want the sql_user_name to mean:
+       #
+       #    Use Stripped-User-Name, if it's there.
+       #    Else use User-Name, if it's there,
+       #    Else use hard-coded string "none" as the user name.
+       #
+       #sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-none}}"
+       
+       sql_user_name = "%{User-Name}"
+       
+       #######################################################################
+       #  Default profile
+       #######################################################################
+       # This is the default profile. It is found in SQL by group membership.
+       # That means that this profile must be a member of at least one group
+       # which will contain the corresponding check and reply items.
+       # This profile will be queried in the authorize section for every user.
+       # The point is to assign all users a default profile without having to
+       # manually add each one to a group that will contain the profile.
+       # The SQL module will also honor the User-Profile attribute. This
+       # attribute can be set anywhere in the authorize section (ie the users
+       # file). It is found exactly as the default profile is found.
+       # If it is set then it will *overwrite* the default profile setting.
+       # The idea is to select profiles based on checks on the incoming
+       # packets, not on user group membership. For example:
+       # -- users file --
+       # DEFAULT       Service-Type == Outbound-User, User-Profile := "outbound"
+       # DEFAULT       Service-Type == Framed-User, User-Profile := "framed"
+       #
+       # By default the default_user_profile is not set
+       #
+       # default_user_profile = "DEFAULT"
+       
+       #######################################################################
+       #  NAS Query
+       #######################################################################
+       #  This query retrieves the radius clients
+       #
+       #  0. Row ID (currently unused)
+       #  1. Name (or IP address)
+       #  2. Shortname
+       #  3. Type
+       #  4. Secret
+       #  5. Server
+       #######################################################################
+       
+       nas_query = "SELECT id, nasname, shortname, type, secret, server FROM ${nas_table}"
+       
+       #######################################################################
+       #  Authorization Queries
+       #######################################################################
+       #  These queries compare the check items for the user
+       #  in ${authcheck_table} and setup the reply items in
+       #  ${authreply_table}.  You can use any query/tables
+       #  you want, but the return data for each row MUST
+       #  be in the  following order:
+       #
+       #  0. Row ID (currently unused)
+       #  1. UserName/GroupName
+       #  2. Item Attr Name
+       #  3. Item Attr Value
+       #  4. Item Attr Operation
+       #######################################################################
+       
+       # Use these for case insensitive usernames. WARNING: Slower queries!
+       # authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
+       #   FROM ${authcheck_table} \
+       #   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
+       #   ORDER BY id"
+       # authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
+       #   FROM ${authreply_table} \
+       #   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
+       #   ORDER BY id"
+       
+       authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
+         FROM ${authcheck_table} \
+         WHERE Username = '%{SQL-User-Name}' \
+         ORDER BY id"
+       
+       authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
+         FROM ${authreply_table} \
+         WHERE Username = '%{SQL-User-Name}' \
+         ORDER BY id"
+       
+       # Use these for case insensitive usernames. WARNING: Slower queries!
+       # authorize_group_check_query = "SELECT ${groupcheck_table}.id, ${groupcheck_table}.GroupName, \
+       #   ${groupcheck_table}.Attribute, ${groupcheck_table}.Value, ${groupcheck_table}.Op \
+       #   FROM ${groupcheck_table}, ${usergroup_table} \
+       #   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName \
+       #   ORDER BY ${groupcheck_table}.id"
+       # authorize_group_reply_query = "SELECT ${groupreply_table}.id, ${groupreply_table}.GroupName, \
+       #   ${groupreply_table}.Attribute, ${groupreply_table}.Value, ${groupreply_table}.Op \
+       #   FROM ${groupreply_table}, ${usergroup_table} \
+       #   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName \
+       #   ORDER BY ${groupreply_table}.id"
+       
+       authorize_group_check_query = "SELECT id, GroupName, Attribute, Value, op \
+         FROM ${groupcheck_table} \
+         WHERE GroupName = '%{Sql-Group}' \
+         ORDER BY id"
+       
+       authorize_group_reply_query = "SELECT id, GroupName, Attribute, Value, op \
+         FROM ${groupreply_table} \
+         WHERE GroupName = '%{Sql-Group}' \
+         ORDER BY id"
+       
+       #######################################################################
+       # Simultaneous Use Checking Queries
+       #######################################################################
+       # simul_count_query     - query for the number of current connections
+       #                       - If this is not defined, no simultaneous use checking
+       #                       - will be performed by this module instance
+       # simul_verify_query    - query to return details of current connections for verification
+       #                       - Leave blank or commented out to disable verification step
+       #                       - Note that the returned field order should not be changed.
+       #######################################################################
+       
+       # Uncomment simul_count_query to enable simultaneous use checking
+       # simul_count_query = "SELECT COUNT(*) FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
+       # simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
+       
+       #######################################################################
+       # Group Membership Queries
+       #######################################################################
+       # group_membership_query        - Check user group membership
+       #######################################################################
+       
+       # Use these for case insensitive usernames. WARNING: Slower queries!
+       # group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') ORDER BY priority"
+       
+       group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE UserName='%{SQL-User-Name}' ORDER BY priority"
+       
+       #######################################################################
+       # Accounting and Post-Auth Queries
+       #######################################################################
+       # These queries insert/update accounting and authentication records.
+       # The query to use is determined by the value of 'reference'.
+       # This value is used as a configuration path and should resolve to one
+       # or more 'query's. If reference points to multiple queries, and a query
+       # fails, the next query is executed.
+       #
+       # Behaviour is identical to the old 1.x/2.x module, except we can now
+       # fail between N queries, and query selection can be based on any
+       # combination of attributes, or custom 'Acct-Status-Type' values.
+       #######################################################################
+       accounting {
+               reference = "%{tolower:type.%{Acct-Status-Type}.query}"
+               
+               type {
+                       accounting-on {
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               AcctStopTime = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
+                                               AcctSessionTime = (EXTRACT(EPOCH FROM ('%S'::timestamp with time zone - AcctStartTime::timestamp with time zone \
+                                                       - '%{%{Acct-Delay-Time}:-0}'::interval)))::BIGINT, \
+                                               AcctTerminateCause = '%{Acct-Terminate-Cause}', \
+                                               AcctStopDelay = 0 \
+                                       WHERE AcctStopTime IS NULL \
+                                       AND NASIPAddress= '%{NAS-IP-Address}' \
+                                       AND AcctStartTime <= '%S'::timestamp"
+                       }
+                       
+                       accounting-off {
+                               query = "${..accounting-on.query}"
+                       }
+                               
+                       start {
+                               query = "\
+                                       INSERT INTO ${....acct_table1} \
+                                               (AcctSessionId,         AcctUniqueId,           UserName, \
+                                               Realm,                  NASIPAddress,           NASPortId, \
+                                               NASPortType,            AcctStartTime,          AcctAuthentic, \
+                                               ConnectInfo_start,      CalledStationId,        CallingStationId, \
+                                               ServiceType,            FramedProtocol,         FramedIPAddress, \
+                                               AcctStartDelay,         XAscendSessionSvrKey) \
+                                       VALUES(\
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               NULLIF('%{Realm}', ''), \
+                                               '%{NAS-IP-Address}', \
+                                               %{%{NAS-Port}:-NULL}, \
+                                               '%{NAS-Port-Type}', \
+                                               ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
+                                               '%{Acct-Authentic}', \
+                                               '%{Connect-Info}', \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               NULLIF('%{Framed-IP-Address}', '')::inet, \
+                                               0, \
+                                               '%{X-Ascend-Session-Svr-Key}')"
+                                       
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               AcctStartTime = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
+                                               AcctStartDelay = 0, \
+                                               ConnectInfo_start = '%{Connect-Info}' \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStopTime IS NULL"       
+                       }
+                       
+                       update {
+                               query = "\
+                                       UPDATE ${....acct_table1} \
+                                       SET \
+                                               FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
+                                               AcctSessionTime = '%{Acct-Session-Time}', \
+                                               AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
+                                                       '%{%{Acct-Input-Octets}:-0}'::bigint), \
+                                               AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
+                                                       '%{%{Acct-Output-Octets}:-0}'::bigint) \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress= '%{NAS-IP-Address}' \
+                                       AND AcctStopTime IS NULL"
+                               
+                               query = "\
+                                       INSERT INTO ${....acct_table1} \
+                                               (AcctSessionId,         AcctUniqueId,           UserName, \
+                                               Realm,                  NASIPAddress,           NASPortId, \
+                                               NASPortType,            AcctStartTime,          AcctSessionTime, \
+                                               AcctAuthentic,          AcctInputOctets,        AcctOutputOctets, \
+                                               CalledStationId,        CallingStationId,       ServiceType, \
+                                               FramedProtocol,         FramedIPAddress,        XAscendSessionSvrKey) \
+                                       VALUES(\
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               NULLIF('%{Realm}', ''), \
+                                               '%{NAS-IP-Address}', \
+                                               %{%{NAS-Port}:-NULL}, \
+                                               '%{NAS-Port-Type}', \
+                                               ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval - \
+                                                       '%{%{Acct-Session-Time}:-0}'::interval), \
+                                               '%{Acct-Session-Time}', \
+                                               '%{Acct-Authentic}', \
+                                               (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
+                                                       '%{%{Acct-Input-Octets}:-0}'::bigint), \
+                                               (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
+                                                       '%{%{Acct-Output-Octets}:-0}'::bigint), \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               NULLIF('%{Framed-IP-Address}', '')::inet, \
+                                               '%{X-Ascend-Session-Svr-Key}')"
+                       }
+               
+                       stop {
+                               query = "\
+                                       UPDATE ${....acct_table2} \
+                                       SET \
+                                               AcctStopTime = ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
+                                               AcctSessionTime = CASE WHEN '%{Acct-Session-Time}' = ''\
+                                                       THEN \
+                                                               (EXTRACT(EPOCH FROM ('%S'::TIMESTAMP WITH TIME ZONE - \
+                                                               AcctStartTime::TIMESTAMP WITH TIME ZONE - \
+                                                               '%{%{Acct-Delay-Time}:-0}'::INTERVAL)))::BIGINT \
+                                                       ELSE \
+                                                               NULLIF('%{Acct-Session-Time}','')::BIGINT END, \
+                                               AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
+                                                       '%{%{Acct-Input-Octets}:-0}'::bigint), \
+                                               AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
+                                               '%{%{Acct-Output-Octets}:-0}'::bigint), \
+                                               AcctTerminateCause = '%{Acct-Terminate-Cause}', \
+                                               AcctStopDelay = 0, \
+                                               FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
+                                               ConnectInfo_stop = '%{Connect-Info}' \
+                                       WHERE AcctSessionId = '%{Acct-Session-Id}' \
+                                       AND UserName = '%{SQL-User-Name}' \
+                                       AND NASIPAddress = '%{NAS-IP-Address}' \
+                                       AND AcctStopTime IS NULL"
+                                       
+                               query = "\
+                                       INSERT INTO ${....acct_table2} \
+                                               (AcctSessionId,         AcctUniqueId,           UserName, \
+                                               Realm,                  NASIPAddress,           NASPortId, \
+                                               NASPortType,            AcctStartTime,          AcctStopTime, \
+                                               AcctSessionTime,        AcctAuthentic,          ConnectInfo_stop, \
+                                               AcctInputOctets,        AcctOutputOctets,       CalledStationId, \
+                                               CallingStationId,       AcctTerminateCause,     ServiceType, \
+                                               FramedProtocol,         FramedIPAddress,        AcctStopDelay) \
+                                       VALUES(\
+                                               '%{Acct-Session-Id}', \
+                                               '%{Acct-Unique-Session-Id}', \
+                                               '%{SQL-User-Name}', \
+                                               NULLIF('%{Realm}', ''), \
+                                               '%{NAS-IP-Address}', \
+                                               %{%{NAS-Port}:-NULL}, \
+                                               '%{NAS-Port-Type}', \
+                                               ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval - \
+                                                       '%{%{Acct-Session-Time}:-0}'::interval), \
+                                               ('%S'::timestamp - '%{%{Acct-Delay-Time}:-0}'::interval), \
+                                               NULLIF('%{Acct-Session-Time}', '')::bigint, \
+                                               '%{Acct-Authentic}', \
+                                               '%{Connect-Info}', \
+                                               (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \
+                                                       '%{%{Acct-Input-Octets}:-0}'::bigint), \
+                                               (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \
+                                                       '%{%{Acct-Output-Octets}:-0}'::bigint), \
+                                               '%{Called-Station-Id}', \
+                                               '%{Calling-Station-Id}', \
+                                               '%{Acct-Terminate-Cause}', \
+                                               '%{Service-Type}', \
+                                               '%{Framed-Protocol}', \
+                                               NULLIF('%{Framed-IP-Address}', '')::inet, 0)"
+                       }
+               }
+       }
+       
+       
+       #######################################################################
+       # Authentication Logging Queries
+       #######################################################################
+       # postauth_query                - Insert some info after authentication
+       #######################################################################
+       
+       post-auth {
+               query = "\
+                       INSERT INTO ${postauth_table} \
+                               (username, pass, reply, authdate) \
+                       VALUES(\
+                               '%{User-Name}', \
+                               '%{%{User-Password}:-Chap-Password}', \
+                               '%{reply:Packet-Type}', \
+                               NOW())"
+       }
index 50fd1e383deaf3294a6f0ceb68b8e3690b5b3388..b8f35785cdf69768afc4e5cb2ec71f62adaa1fe3 100644 (file)
 #include <freeradius-devel/ident.h>
 RCSIDH(conf_h, "$Id$")
 
-typedef struct sql_config {
-       char   *sql_driver;
-       char   *sql_server;
-       char   *sql_port;
-       char   *sql_login;
-       char   *sql_password;
-       char   *sql_db;
-       char   *sql_file;       /* for sqlite */
-       char   *query_user;
-       char   *default_profile;
-       char   *nas_query;
-       char   *authorize_check_query;
-       char   *authorize_reply_query;
-       char   *authorize_group_check_query;
-       char   *authorize_group_reply_query;
-       char   *accounting_onoff_query;
-       char   *accounting_update_query;
-       char   *accounting_update_query_alt;
-       char   *accounting_start_query;
-       char   *accounting_start_query_alt;
-       char   *accounting_stop_query;
-       char   *accounting_stop_query_alt;
-       char   *simul_count_query;
-       char   *simul_verify_query;
-       char   *groupmemb_query;
-       int     sqltrace;
-       int     do_clients;
-       int     read_groups;
-       char   *tracefile;
-       char   *xlat_name;
-       int     deletestalesessions;
-       char   *postauth_query;
-       char   *allowed_chars;
-       int     query_timeout;
-
-       /* individual driver config */
-       void    *localcfg;
-
-} SQL_CONFIG;
-
-
 #define CHECKRAD1              "/usr/sbin/checkrad"
 #define CHECKRAD2              "/usr/local/sbin/checkrad"
 
@@ -74,7 +33,6 @@ typedef struct sql_config {
 
 #define ASCEND_PORT_HACK
 #define ASCEND_CHANNELS_PER_LINE        23
-#define CISCO_ACCOUNTING_HACK
 
 /* SQL defines */
 #define MAX_QUERY_LEN                  4096
index fafe4e8f9f61e1f4472f453c7056e00c1338d20f..9c330b979eaa78511f4d6f66a3a3a255d4e64157 100644 (file)
@@ -19,6 +19,7 @@
  *   along with this program; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
+ * Copyright 2012  Arran Cudbard-Bell <a.cudbardb@freeradius.org>
  * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Mike Machado <mike@innercite.com>
  * Copyright 2000  Alan DeKok <aland@ox.org>
 #include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
+#include <ctype.h>
+
 #include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/modules.h>
+#include <freeradius-devel/token.h>
 #include <freeradius-devel/rad_assert.h>
 
 #include <sys/stat.h>
@@ -37,6 +41,17 @@ RCSID("$Id$")
 
 static char *allowed_chars = NULL;
 
+static const CONF_PARSER section_config[] = {
+       { "reference",  PW_TYPE_STRING_PTR,
+         offsetof(rlm_sql_config_section_t, reference), NULL, ".query"},
+         
+       {"sqltrace", PW_TYPE_BOOLEAN,
+        offsetof(rlm_sql_config_section_t, sqltrace), NULL, "no"},
+       {"sqltracefile", PW_TYPE_STRING_PTR,
+        offsetof(rlm_sql_config_section_t, tracefile), NULL, NULL},
+       {NULL, -1, 0, NULL, NULL}
+};
+
 static const CONF_PARSER module_config[] = {
        {"driver",PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,sql_driver), NULL, "mysql"},
@@ -54,10 +69,6 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,sql_file), NULL, NULL},
        {"read_groups", PW_TYPE_BOOLEAN,
         offsetof(SQL_CONFIG,read_groups), NULL, "yes"},
-       {"sqltrace", PW_TYPE_BOOLEAN,
-        offsetof(SQL_CONFIG,sqltrace), NULL, "no"},
-       {"sqltracefile", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,tracefile), NULL, SQLTRACEFILE},
        {"readclients", PW_TYPE_BOOLEAN,
         offsetof(SQL_CONFIG,do_clients), NULL, "no"},
        {"deletestalesessions", PW_TYPE_BOOLEAN,
@@ -76,22 +87,6 @@ static const CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,authorize_group_check_query), NULL, ""},
        {"authorize_group_reply_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,authorize_group_reply_query), NULL, ""},
-#ifdef WITH_ACCOUNTING
-       {"accounting_onoff_query", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,accounting_onoff_query), NULL, ""},
-       {"accounting_update_query", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,accounting_update_query), NULL, ""},
-       {"accounting_update_query_alt", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,accounting_update_query_alt), NULL, ""},
-       {"accounting_start_query", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,accounting_start_query), NULL, ""},
-       {"accounting_start_query_alt", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,accounting_start_query_alt), NULL, ""},
-       {"accounting_stop_query", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,accounting_stop_query), NULL, ""},
-       {"accounting_stop_query_alt", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,accounting_stop_query_alt), NULL, ""},
-#endif
        {"group_membership_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,groupmemb_query), NULL, NULL},
 #ifdef WITH_SESSION_MGMT
@@ -100,8 +95,6 @@ static const CONF_PARSER module_config[] = {
        {"simul_verify_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,simul_verify_query), NULL, ""},
 #endif
-       {"postauth_query", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,postauth_query), NULL, ""},
        {"safe-characters", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,allowed_chars), NULL,
        "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},
@@ -135,11 +128,11 @@ static int generate_sql_clients(SQL_INST *inst);
 static size_t sql_escape_func(char *out, size_t outlen, const char *in);
 
 /*
- *     sql xlat function. Right now only SELECTs are supported. Only
- *     the first element of the SELECT result will be used.
+ *                     SQL xlat function
  *
- *     For other statements (insert, update, delete, etc.), the
- *     number of affected rows will be returned.
+ *  For selects the first value of the first column will be returned,
+ *  for inserts, updates and deletes the number of rows afftected will be
+ *  returned instead.
  */
 static int sql_xlat(void *instance, REQUEST *request,
                    char *fmt, char *out, size_t freespace,
@@ -169,7 +162,7 @@ static int sql_xlat(void *instance, REQUEST *request,
                return 0;
        }
 
-       query_log(request, inst,querystr);
+       query_log(inst, request, NULL, querystr);
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL)
                return 0;
@@ -245,7 +238,7 @@ static int sql_xlat(void *instance, REQUEST *request,
        }
 
        if (row[0] == NULL){
-               RDEBUG("row[0] returned NULL");
+               RDEBUG("Null value in first column");
                (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                sql_release_socket(inst,sqlsocket);
                return 0;
@@ -838,6 +831,37 @@ static int rlm_sql_detach(void *instance)
 
        return 0;
 }
+
+static int parse_sub_section(CONF_SECTION *parent, 
+                            UNUSED SQL_INST *instance,
+                            rlm_sql_config_section_t *config,
+                            rlm_components_t comp)
+{
+       CONF_SECTION *cs;
+
+       const char *name = section_type_value[comp].section;
+       
+       cs = cf_section_sub_find(parent, name);
+       if (!cs) {
+               /* TODO: Should really setup section with default values */
+               goto error;
+       }
+       
+       if (cf_section_parse(cs, config, section_config) < 0)
+               goto error;
+               
+       config->cs = cs;
+
+       return 1;
+       
+       error:
+       radlog(L_ERR, "Failed parsing configuration for section %s",
+              name);
+       
+       return -1;
+               
+}
+
 static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
 {
        SQL_INST *inst;
@@ -846,28 +870,44 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
        inst = rad_malloc(sizeof(SQL_INST));
        memset(inst, 0, sizeof(SQL_INST));
 
+       /*
+        *      Export these methods, too.  This avoids RTDL_GLOBAL.
+        */
+       inst->sql_set_user              = sql_set_user;
+       inst->sql_get_socket            = sql_get_socket;
+       inst->sql_release_socket        = sql_release_socket;
+       inst->sql_escape_func           = sql_escape_func;
+       inst->sql_query                 = rlm_sql_query;
+       inst->sql_select_query          = rlm_sql_select_query;
+       inst->sql_fetch_row             = rlm_sql_fetch_row;
+       
        inst->config = rad_malloc(sizeof(SQL_CONFIG));
        memset(inst->config, 0, sizeof(SQL_CONFIG));
        inst->cs = conf;
-
+               
        /*
-        *      Export these methods, too.  This avoids RTDL_GLOBAL.
+        *      If the configuration parameters can't be parsed, then fail.
         */
-       inst->sql_set_user = sql_set_user;
-       inst->sql_get_socket = sql_get_socket;
-       inst->sql_release_socket = sql_release_socket;
-       inst->sql_escape_func = sql_escape_func;
-       inst->sql_query = rlm_sql_query;
-       inst->sql_select_query = rlm_sql_select_query;
-       inst->sql_fetch_row = rlm_sql_fetch_row;
-
+       if (
+               (cf_section_parse(conf, inst->config, module_config) < 0) ||
+               (parse_sub_section(conf, inst,
+                                  &inst->config->accounting,
+                                  RLM_COMPONENT_ACCT) < 0) ||
+               (parse_sub_section(conf, inst,
+                                  &inst->config->postauth,
+                                  RLM_COMPONENT_POST_AUTH) < 0)
+       ) {
+               radlog(L_ERR, "Failed parsing configuration");
+                       
+               goto error;
+       }
        /*
-        * If the configuration parameters can't be parsed, then
-        * fail.
+        *      Sanity check for crazy people.
         */
-       if (cf_section_parse(conf, inst->config, module_config) < 0) {
-               rlm_sql_detach(inst);
-               return -1;
+       if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) {
+               radlog(L_ERR, "\"%s\" is NOT an SQL driver!",
+                      inst->config->sql_driver);       
+               goto error;
        }
 
        xlat_name = cf_section_name2(conf);
@@ -879,87 +919,92 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
                ATTR_FLAGS flags;
 
                /*
-                * Allocate room for <instance>-SQL-Group
+                *      Allocate room for <instance>-SQL-Group
                 */
                group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char));
-               sprintf(group_name,"%s-SQL-Group",xlat_name);
+               sprintf(group_name,"%s-SQL-Group", xlat_name);
                DEBUG("rlm_sql Creating new attribute %s",group_name);
 
                memset(&flags, 0, sizeof(flags));
                dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags);
                dattr = dict_attrbyname(group_name);
                if (dattr == NULL){
-                       radlog(L_ERR, "rlm_sql: Failed to create attribute %s",group_name);
+                       radlog(L_ERR, "rlm_sql: Failed to create attribute %s",
+                              group_name);
+                              
                        free(group_name);
-                       free(inst);     /* FIXME: detach */
-                       return -1;
+
+                       goto error;
                }
 
                if (inst->config->groupmemb_query && 
                    inst->config->groupmemb_query[0]) {
-                       DEBUG("rlm_sql: Registering sql_groupcmp for %s",group_name);
-                       paircompare_register(dattr->attr, PW_USER_NAME, sql_groupcmp, inst);
+                       DEBUG("rlm_sql: Registering sql_groupcmp for %s",
+                             group_name);
+                       paircompare_register(dattr->attr, PW_USER_NAME,
+                                            sql_groupcmp, inst);
                }
 
                free(group_name);
        }
-       if (xlat_name){
-               inst->config->xlat_name = strdup(xlat_name);
-               xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst);
-       }
+       
+       rad_assert(xlat_name);
 
        /*
-        *      Sanity check for crazy people.
+        *      Register the SQL xlat function
+        */
+       inst->config->xlat_name = strdup(xlat_name);
+       xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst);
+               
+       /*
+        *      Load the appropriate driver for our database
         */
-       if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) {
-               radlog(L_ERR, "\"%s\" is NOT an SQL driver!",
-                      inst->config->sql_driver);
-               rlm_sql_detach(inst);
-               return -1;
-       }
-
        inst->handle = lt_dlopenext(inst->config->sql_driver);
        if (inst->handle == NULL) {
                radlog(L_ERR, "Could not link driver %s: %s",
                       inst->config->sql_driver,
                       lt_dlerror());
-               radlog(L_ERR, "Make sure it (and all its dependent libraries!) are in the search path of your system's ld.");
-               rlm_sql_detach(inst);
-               return -1;
+               radlog(L_ERR, "Make sure it (and all its dependent libraries!)"
+                      "are in the search path of your system's ld.");
+
+               goto error;
        }
 
-       inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle, inst->config->sql_driver);
+       inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle,
+                                                    inst->config->sql_driver);
        if (!inst->module) {
                radlog(L_ERR, "Could not link symbol %s: %s",
                       inst->config->sql_driver,
                       lt_dlerror());
-               rlm_sql_detach(inst);
-               return -1;
+
+               goto error;
        }
 
        radlog(L_INFO, "rlm_sql (%s): Driver %s (module %s) loaded and linked",
               inst->config->xlat_name, inst->config->sql_driver,
               inst->module->name);
+
+       /*
+        *      Initialise the connection pool for this instance
+        */
        radlog(L_INFO, "rlm_sql (%s): Attempting to connect to %s@%s:%s/%s",
               inst->config->xlat_name, inst->config->sql_login,
               inst->config->sql_server, inst->config->sql_port,
               inst->config->sql_db);
-
-       if (sql_init_socketpool(inst) < 0) {
-               rlm_sql_detach(inst);
-               return -1;
-       }
+              
+       if (sql_init_socketpool(inst) < 0)
+               goto error;
 
        if (inst->config->groupmemb_query && 
            inst->config->groupmemb_query[0]) {
                paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst);
        }
 
-       if (inst->config->do_clients){
+       if (inst->config->do_clients) {
                if (generate_sql_clients(inst) == -1){
                        radlog(L_ERR, "Failed to load clients from SQL.");
-                       rlm_sql_detach(inst);
-                       return -1;
+                       
+                       goto error;
                }
        }
        allowed_chars = inst->config->allowed_chars;
@@ -967,6 +1012,11 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
        *instance = inst;
 
        return RLM_MODULE_OK;
+       
+       error:
+       rlm_sql_detach(inst);
+       
+       return -1;
 }
 
 
@@ -997,7 +1047,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
 
 
        /*
-        * reserve a socket
+        *  Reserve a socket
         */
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL) {
@@ -1058,6 +1108,7 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                                pairdelete(&request->packet->vps, PW_SQL_USER_NAME, 0);
                                pairfree(&check_tmp);
                                pairfree(&reply_tmp);
+                               
                                return RLM_MODULE_FAIL;
                        }
 
@@ -1148,258 +1199,146 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        }
 }
 
-#ifdef WITH_ACCOUNTING
 /*
- *     Accounting: save the account data to our sql table
+ *     Generic function for failing between a bunch of queries.
+ *
+ *     Uses the same principle as rlm_linelog, expanding the 'reference' config
+ *     item using xlat to figure out what query it should execute.
+ *
+ *     If the reference matches multiple config items, and a query fails or
+ *     doesn't update any rows, the next matching config item is used.
+ *  
  */
-static int rlm_sql_accounting(void *instance, REQUEST * request) {
-
-       SQLSOCK *sqlsocket = NULL;
-       VALUE_PAIR *pair;
-       SQL_INST *inst = instance;
-       int             sql_ret;
+static int rlm_sql_redundant(SQL_INST *inst, REQUEST *request, 
+                            rlm_sql_config_section_t *section)
+{
        int             ret = RLM_MODULE_OK;
-       int     numaffected = 0;
-       int     acctstatustype = 0;
-       char    querystr[MAX_QUERY_LEN];
-       char    logstr[MAX_QUERY_LEN];
-       char    sqlusername[MAX_STRING_LEN];
 
-#ifdef CISCO_ACCOUNTING_HACK
-       int     acctsessiontime = 0;
-#endif
+       SQLSOCK         *sqlsocket = NULL;
+       int             sql_ret;
+       int             numaffected = 0;
 
-       memset(querystr, 0, MAX_QUERY_LEN);
+       CONF_ITEM       *item;
+       CONF_PAIR       *pair;
+       CONF_SECTION    *base;
+       const char      *attr = NULL;
+       const char      *value;
 
-       /*
-        * Find the Acct Status Type
-        */
-       pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0);
-       if (pair == NULL) {
-               radius_xlat(logstr, sizeof(logstr), "Packet has no accounting status type. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
-               radlog_request(L_ERR, 0, request, "%s", logstr);
-               
-               return RLM_MODULE_INVALID;
-       }
+       char    path[MAX_STRING_LEN];
+       char    querystr[MAX_QUERY_LEN];
+       char    sqlusername[MAX_STRING_LEN];
        
-       acctstatustype = pair->vp_integer;
-
-       /*
-        *  Bulk update queries
-        */
-       if (acctstatustype == PW_STATUS_ACCOUNTING_ON ||
-           acctstatustype == PW_STATUS_ACCOUNTING_OFF) {
-               /*
-                * The NAS informed us that it was rebooted, close all sessions
-                * associated with it.
-                */
-               radius_xlat(logstr, sizeof(logstr), "Bulk closing sessions using 'accounting_onoff_query' - [nas '%{NAS-IP-Address}']", request, NULL);
-               radlog_request(L_DBG, 0, request, "%s", logstr);
-               
-               radius_xlat(querystr, sizeof(querystr), 
-                                       inst->config->accounting_onoff_query, request,
-                                       sql_escape_func);
-               if (!*querystr)
-                       goto null_query;
+       char    *p = path;
 
-               query_log(request, inst, querystr);
+       memset(querystr, 0, sizeof(querystr));
+       
+       sql_set_user(inst, request, sqlusername, NULL);
+       
+       if (section->reference[0] != '.')
+               *p++ = '.';
+       
+       if (radius_xlat(p, (sizeof(path) - (p - path)) - 1,
+                       section->reference, request, NULL) < 0)
+               return RLM_MODULE_FAIL;
 
-               sqlsocket = sql_get_socket(inst);
-               if (sqlsocket == NULL)
-                       return RLM_MODULE_FAIL;
+       item = cf_reference_item(NULL, section->cs, path);
+       if (!item)
+               return RLM_MODULE_FAIL;
 
-               sql_ret = rlm_sql_query(&sqlsocket, inst, querystr);
-               if (sql_ret)
-                       return RLM_MODULE_FAIL;
-                                                       
-               numaffected = (inst->module->sql_affected_rows)(sqlsocket,
-                                                                                                               inst->config);
-               radlog_request(L_DBG, 0, request, "Closed %i sessions", numaffected);
-               if (numaffected < 1)
-                       ret = RLM_MODULE_NOOP;
+       if (cf_item_is_section(item)){
+               radlog(L_ERR, "Sections are not supported as references");
                
-               goto cleanup;
+               return RLM_MODULE_FAIL;
        }
        
-       /*
-        *  Session specific queries
-        */
-       sql_set_user(inst, request, sqlusername, NULL);
+       pair = cf_itemtopair(item);
+       attr = cf_pair_attr(pair);
+       
+       RDEBUG2("Failing between pairs with name '%s'", attr);
        
-       /*
-        *  Setup the primary query for a given packet type
-        */
-       switch (acctstatustype) {
-               case PW_STATUS_ALIVE:
-                       radlog_request(L_DBG, 0, request, "Updating session using 'accounting_update_query'");
-                       
-                       radius_xlat(querystr, sizeof(querystr),
-                                               inst->config->accounting_update_query, request,
-                                               sql_escape_func);
-                       if (!*querystr)
-                               goto null_query;
-                               
-                       break;
-               
-               case PW_STATUS_START:
-                       radlog_request(L_DBG, 0, request, "Creating session using 'accounting_start_query'");
-               
-                       radius_xlat(querystr, sizeof(querystr),
-                                               inst->config->accounting_start_query, request,
-                                               sql_escape_func);
-                       if (!*querystr)
-                               goto null_query;
-                               
-                       break;
-               
-               case PW_STATUS_STOP:
-                       radlog_request(L_DBG, 0, request, "Closing session using 'accounting_stop_query'");
-                       
-                       radius_xlat(querystr, sizeof(querystr),
-                                               inst->config->accounting_stop_query, request,
-                                               sql_escape_func);
-                       if (!*querystr)
-                               goto null_query;
-                               
-                       break;
-               
-               default:
-                       RDEBUG("Unsupported Acct-Status-Type value (%d)", acctstatustype);
-                       
-                       return RLM_MODULE_NOOP;
-       }
-
-       /*
-        * Log the query. Maybe we should do this only if were not using the 
-        * alternate?
-        */
-       query_log(request, inst, querystr);
-
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL)
                return RLM_MODULE_FAIL;
 
-       sql_ret = rlm_sql_query(&sqlsocket, inst, querystr);    
-       if (sql_ret == SQL_DOWN)
-               return RLM_MODULE_FAIL;
-               
-       rad_assert(sqlsocket);
-
-       /* 
-        * Assume all other errors are incidental, and just meant our operation
-        * failed and its not a client or SQL syntax error.
-        */
-       if (sql_ret == 0) {
-               numaffected = (inst->module->sql_affected_rows)(sqlsocket,
-                                                                                                               inst->config);
-               if (numaffected > 0)
-                       goto cleanup;
-       }
-                                               
-       /*
-        * The primary query failed this may be because:
-        *              update - The session hasn't be created with a start record - 
-        *                               so create the session.
-        *              start  - The session was created from a stop or interim update
-        *                               packet so the insert failed (presumably on unique index 
-        *                               constraint) - so update the session.
-        *              stop   - The session does not already exist. We never received 
-        *                               a Start or Interim-Update packet for this session -
-        *                               so create the session.
-        */
-       (inst->module->sql_finish_query)(sqlsocket, inst->config);
-       
-       /*
-        *  Setup the alternate query for a given packet type
-        */
-       switch (acctstatustype) {
-               case PW_STATUS_ALIVE:
-                       radlog_request(L_DBG, 0, request, "Failed updating session, creating session using 'accounting_update_query_alt'");
-                       
-                       radius_xlat(querystr, sizeof(querystr),
-                                               inst->config->accounting_update_query_alt,
-                                               request, sql_escape_func);
-                       if (!*querystr)
-                               goto null_query;
-                               
-                       break;
+       while (TRUE) {
+               value = cf_pair_value(pair);
+               if (!value)
+                       goto null_query;
                
-               case PW_STATUS_START:
-                       radlog_request(L_DBG, 0, request, "Failed creating session, updating session using 'accounting_start_query_alt'");
+               radius_xlat(querystr, sizeof(querystr), value, request,
+                           sql_escape_func);
+               if (!*querystr)
+                       goto null_query;
                
-                       radius_xlat(querystr, sizeof(querystr),
-                                               inst->config->accounting_start_query_alt,
-                                               request, sql_escape_func);
-                       if (!*querystr)
-                               goto null_query;
-                               
-                       break;
+               query_log(inst, request, section, querystr);
                
-               case PW_STATUS_STOP:
-#ifdef CISCO_ACCOUNTING_HACK
-                       /*
-                        * If stop but zero session length AND no previous session found,
-                        * drop it as in invalid packet This is to fix CISCO's aaa from
-                        * filling our table with bogus crap
-                        */
-                       pair = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME, 0);
-                       if (pair != NULL)
-                               acctsessiontime = pair->vp_integer;
-       
-                       if (acctsessiontime <= 0) {
-                               radius_xlat(logstr, sizeof(logstr), "Stop packet with zero session length. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
-                               radlog_request(L_DBG, 0, request, "%s", logstr);
-
-                               goto release;
-                       }
-#endif
-
-                       radlog_request(L_DBG, 0, request, "Failed closing session, creating closed session using 'accounting_stop_query_alt'");
+               sql_ret = rlm_sql_query(&sqlsocket, inst, querystr);    
+               if (sql_ret == SQL_DOWN)
+                       return RLM_MODULE_FAIL;
                        
-                       radius_xlat(querystr, sizeof(querystr),
-                                               inst->config->accounting_stop_query_alt,
-                                               request, sql_escape_func);
-                       if (!*querystr)
-                               goto null_query;
+               rad_assert(sqlsocket);
+       
+               /* 
+                *  Assume all other errors are incidental, and just meant our
+                *  operation failed and its not a client or SQL syntax error.
+                */
+               if (sql_ret == 0) {
+                       numaffected = (inst->module->sql_affected_rows)
+                                       (sqlsocket, inst->config);
+                       if (numaffected > 0)
+                               break;
+                               
+                       RDEBUG("No records updated");
+               }
 
-                       break;
-               default:
-                       rad_assert(0);
-       }
+               (inst->module->sql_finish_query)(sqlsocket, inst->config);
                
-       query_log(request, inst, querystr);
-
-       if (rlm_sql_query(&sqlsocket, inst, querystr) == SQL_DOWN)
-               return RLM_MODULE_FAIL;
+               /*
+                *  We assume all entries with the same name form a redundant
+                *  set of queries.
+                */
+               pair = cf_pair_find_next(base, pair, attr);
                
-       rad_assert(sqlsocket);
+               if (!pair) {
+                       RDEBUG("No additional queries configured");
+                       
+                       ret = RLM_MODULE_NOOP;
+                       
+                       goto release;
+               }
 
-       /*
-        * This time we *know* this was some sort of error...
-        */
-       if (sql_ret) {
-               ret = RLM_MODULE_FAIL;
-               goto cleanup;
+               RDEBUG("Trying next query...");
        }
        
-       numaffected = (inst->module->sql_affected_rows)(sqlsocket, inst->config);
-       if (numaffected < 1)
-               ret = RLM_MODULE_NOOP;
-       
-       cleanup:
-               (inst->module->sql_finish_query)(sqlsocket, inst->config);
+       (inst->module->sql_finish_query)(sqlsocket, inst->config);
 
        release:
-               sql_release_socket(inst, sqlsocket);
+       
+       sql_release_socket(inst, sqlsocket);
 
        return ret;
        
        null_query:
+       
        radlog_request(L_DBG, 0, request, "Ignoring null query");
+       
+       sql_release_socket(inst, sqlsocket);
+
        return RLM_MODULE_NOOP;
 }
-#endif
 
+#ifdef WITH_ACCOUNTING
+
+/*
+ *     Accounting: Insert or update session data in our sql table
+ */
+static int rlm_sql_accounting(void *instance, REQUEST * request) {
+       SQL_INST *inst = instance;              
+
+       return rlm_sql_redundant(inst, request, &inst->config->accounting); 
+}
+
+#endif
 
 #ifdef WITH_SESSION_MGMT
 /*
@@ -1589,46 +1528,18 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
 #endif
 
 /*
- *     Execute postauth_query after authentication
+ *     Postauth: Write a record of the authentication attempt
  */
-static int rlm_sql_postauth(void *instance, REQUEST *request) {
-       SQLSOCK         *sqlsocket = NULL;
-       SQL_INST        *inst = instance;
-       char            querystr[MAX_QUERY_LEN];
-       char            sqlusername[MAX_STRING_LEN];
-
-       if(sql_set_user(inst, request, sqlusername, NULL) < 0)
-               return RLM_MODULE_FAIL;
-
-       /* If postauth_query is not defined, we stop here */
-       if (!inst->config->postauth_query ||
-           (inst->config->postauth_query[0] == '\0'))
-               return RLM_MODULE_NOOP;
-
-       /* Expand variables in the query */
-       memset(querystr, 0, MAX_QUERY_LEN);
-       radius_xlat(querystr, sizeof(querystr), inst->config->postauth_query,
-                   request, sql_escape_func);
-       query_log(request, inst, querystr);
-       DEBUG2("rlm_sql (%s) in sql_postauth: query is %s",
-              inst->config->xlat_name, querystr);
-
-       /* Initialize the sql socket */
-       sqlsocket = sql_get_socket(inst);
-       if (sqlsocket == NULL)
-               return RLM_MODULE_FAIL;
+static int rlm_sql_postauth(void *instance, REQUEST * request) {
+       SQL_INST *inst = instance;
+       
+       return rlm_sql_redundant(inst, request, &inst->config->postauth); 
+}
 
-       /* Process the query */
-       if (rlm_sql_query(&sqlsocket, inst, querystr)) {
-               sql_release_socket(inst, sqlsocket);
-               
-               return RLM_MODULE_FAIL;
-       }
-       (inst->module->sql_finish_query)(sqlsocket, inst->config);
+/*
+ *     Execute postauth_query after authentication
+ */
 
-       sql_release_socket(inst, sqlsocket);
-       return RLM_MODULE_OK;
-}
 
 /* globally exported name */
 module_t rlm_sql = {
index db375a07c5c50bad24eb5ec2c04b23390a805c68..1a6bbad15d0057a46b12659873394aa5c7dcbe1b 100644 (file)
@@ -16,14 +16,62 @@ RCSIDH(rlm_sql_h, "$Id$")
 
 #include "conf.h"
 
-#define SQLSOCK_LOCKED         0
-#define SQLSOCK_UNLOCKED       1
-
-#define PW_ITEM_CHECK                  0
-#define PW_ITEM_REPLY                  1
+#define PW_ITEM_CHECK          0
+#define PW_ITEM_REPLY          1
 
 typedef char** SQL_ROW;
 
+/*
+ *  Sections where we dynamically resolve the config entry to use,
+ *  by xlating reference.
+ */
+typedef struct rlm_sql_config_section {
+       CONF_SECTION    *cs;
+       
+       char    *reference;
+       
+       int             sqltrace;
+       char    *tracefile;
+} rlm_sql_config_section_t;
+
+typedef struct sql_config {
+       char   *sql_driver;
+       char   *sql_server;
+       char   *sql_port;
+       char   *sql_login;
+       char   *sql_password;
+       char   *sql_db;
+       char   *sql_file;       /* for sqlite */
+       char   *query_user;
+       char   *default_profile;
+       char   *nas_query;
+       char   *authorize_check_query;
+       char   *authorize_reply_query;
+       char   *authorize_group_check_query;
+       char   *authorize_group_reply_query;
+       char   *simul_count_query;
+       char   *simul_verify_query;
+       char   *groupmemb_query;
+       int     sqltrace;
+       int             do_clients;
+       int             read_groups;
+       char   *tracefile;
+       char   *xlat_name;
+       int     deletestalesessions;
+       char   *allowed_chars;
+       int     query_timeout;
+       void    *localcfg;                       /* individual driver config */
+       
+       /* 
+        * TODO: The rest of the queries should also be moved into their own
+        * sections.
+        */
+       
+       /* Section configurations */
+       rlm_sql_config_section_t        postauth;
+       rlm_sql_config_section_t        accounting;
+} SQL_CONFIG;
+
 typedef struct sql_socket {
        void    *conn;
        SQL_ROW row;
@@ -83,7 +131,8 @@ int     sql_getvpdata(SQL_INST * inst, SQLSOCK ** sqlsocket, VALUE_PAIR **pair,
 int     sql_read_naslist(SQLSOCK * sqlsocket);
 int     sql_read_clients(SQLSOCK * sqlsocket);
 int     sql_dict_init(SQLSOCK * sqlsocket);
-void    query_log(REQUEST *request, SQL_INST * inst, char *querystr);
+void   query_log(SQL_INST *inst, REQUEST *request,
+                         rlm_sql_config_section_t *section, char *querystr);
 int    rlm_sql_select_query(SQLSOCK **sqlsocket, SQL_INST *inst, char *query);
 int    rlm_sql_query(SQLSOCK **sqlsocket, SQL_INST *inst, char *query);
 int    rlm_sql_fetch_row(SQLSOCK **sqlsocket, SQL_INST *inst);
index 86e2b5fc21c48b3ec66f0940db835e5316894b4b..b45aa9f0fbd1ca45640ca35960bd5a5196e1b3a0 100644 (file)
@@ -314,10 +314,9 @@ int rlm_sql_query(SQLSOCK **sqlsocket, SQL_INST *inst, char *query)
                
                if (ret < 0) {
                        radlog(L_ERR,
-                                  "rlm_sql (%s): Database query error '%s' in query '%s'",
+                                  "rlm_sql (%s): Database query error '%s'",
                                   inst->config->xlat_name,
-                                  (inst->module->sql_error)(*sqlsocket, inst->config),
-                                  query);
+                                  (inst->module->sql_error)(*sqlsocket, inst->config));
                }
                
                return ret;
@@ -366,10 +365,9 @@ int rlm_sql_select_query(SQLSOCK **sqlsocket, SQL_INST *inst, char *query)
                
                if (ret < 0) {
                        radlog(L_ERR,
-                                  "rlm_sql (%s): Database query error '%s' in query '%s'",
+                                  "rlm_sql (%s): Database query error '%s'",
                                   inst->config->xlat_name,
-                                  (inst->module->sql_error)(*sqlsocket, inst->config),
-                                  query);
+                                  (inst->module->sql_error)(*sqlsocket, inst->config));
                }
                
                return ret;
@@ -409,31 +407,35 @@ int sql_getvpdata(SQL_INST * inst, SQLSOCK **sqlsocket, VALUE_PAIR **pair, char
        return rows;
 }
 
-void query_log(REQUEST *request, SQL_INST *inst, char *querystr)
+void query_log(SQL_INST *inst, REQUEST *request,
+              rlm_sql_config_section_t *section, char *querystr)
 {
-       FILE   *sqlfile = NULL;
-
-       if (inst->config->sqltrace) {
-               char buffer[8192];
+       FILE    *sqlfile = NULL;
+       
+       if (!inst->config->sqltrace && (!section || !section->sqltrace))
+               return;
+
+       char buffer[8192];
+
+       if (!radius_xlat(buffer, sizeof(buffer),
+                        section && section->tracefile ? section->tracefile :
+                               inst->config->tracefile,
+                        request, NULL)) {
+         radlog(L_ERR, "rlm_sql (%s): xlat failed.",
+                inst->config->xlat_name);
+         return;
+       }
 
-               if (!radius_xlat(buffer, sizeof(buffer),
-                                inst->config->tracefile, request, NULL)) {
-                 radlog(L_ERR, "rlm_sql (%s): xlat failed.",
-                        inst->config->xlat_name);
-                 return;
-               }
+       if ((sqlfile = fopen(buffer, "a")) == (FILE *) NULL) {
+               radlog(L_ERR, "rlm_sql (%s): Couldn't open file %s",
+                      inst->config->xlat_name,
+                      buffer);
+       } else {
+               int fd = fileno(sqlfile);
 
-               if ((sqlfile = fopen(buffer, "a")) == (FILE *) NULL) {
-                       radlog(L_ERR, "rlm_sql (%s): Couldn't open file %s",
-                              inst->config->xlat_name,
-                              buffer);
-               } else {
-                       int fd = fileno(sqlfile);
-
-                       rad_lockfd(fd, MAX_QUERY_LEN);
-                       fputs(querystr, sqlfile);
-                       fputs(";\n", sqlfile);
-                       fclose(sqlfile); /* and release the lock */
-               }
+               rad_lockfd(fd, MAX_QUERY_LEN);
+               fputs(querystr, sqlfile);
+               fputs(";\n", sqlfile);
+               fclose(sqlfile); /* and release the lock */
        }
 }