summaryrefslogtreecommitdiffstats
path: root/src/etc/inc/captiveportal.inc
diff options
context:
space:
mode:
authorplumbeo <plumbeo@users.noreply.github.com>2016-12-27 21:32:43 +0100
committerRenato Botelho <renato@netgate.com>2017-01-04 14:25:01 -0200
commit2795722bda1ec743badeb536c524442175adb931 (patch)
tree30b450c3a7e71ae4b79471733906fa52d362892d /src/etc/inc/captiveportal.inc
parent7f799b0b764c6c247c59f5a1d39378daee803f43 (diff)
downloadpfsense-2795722bda1ec743badeb536c524442175adb931.zip
pfsense-2795722bda1ec743badeb536c524442175adb931.tar.gz
Captive portal: work around race condition between captiveportal_disconnect_all() and captiveportal_prune_old()
Captiveportal_disconnect_all() loops through the active users and disconnects them immediately but doesn't remove them from the user database, only adding them to a list that is processed after the end of the loop. Since the loop can take several seconds if there are many users connected, captiveportal_prune_old() can be called after some users have been disconnected but before they're removed from the database. When this happens and the user has an idle timeout set, captiveportal_prune_old() tries to find the last activity time and gets an invalid value because the user has already been removed from the fw table, so it uses the login time as last activity time. Finally, if the login time is more than one idle timeout in the past, it tries to disconnect again the user and sends a RADIUS Accounting-Stop packet with termination-cause Idle-Timeout and zero Acct-Input-Octets/Acct-Output-Octets that overwrites the correct packet sent by captiveportal_disconnect_all(). To work around it, remove the users from the database before disconnecting them (this fixes only the case where captiveportal_disconnect_all() runs before captiveportal_prune_old()). (cherry picked from commit 025ec94a3285c129d2e14b00b629e811b83a9330)
Diffstat (limited to 'src/etc/inc/captiveportal.inc')
-rw-r--r--src/etc/inc/captiveportal.inc11
1 files changed, 5 insertions, 6 deletions
diff --git a/src/etc/inc/captiveportal.inc b/src/etc/inc/captiveportal.inc
index b35dc57..c404f47 100644
--- a/src/etc/inc/captiveportal.inc
+++ b/src/etc/inc/captiveportal.inc
@@ -1002,7 +1002,11 @@ function captiveportal_disconnect_all($term_cause = 6, $logoutReason = "DISCONNE
$radiussrvs = captiveportal_get_radius_servers();
$cpdb = captiveportal_read_db();
- $unsetindexes = array();
+ /* remove immediately the active users from the database to avoid races */
+ $unsetindexes = array_column($cpdb,5);
+ if (!empty($unsetindexes)) {
+ captiveportal_remove_entries($unsetindexes);
+ }
foreach ($cpdb as $cpentry) {
if (empty($cpentry[11])) {
@@ -1012,13 +1016,8 @@ function captiveportal_disconnect_all($term_cause = 6, $logoutReason = "DISCONNE
captiveportal_disconnect($cpentry, $radiusservers, $term_cause);
captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], $logoutReason);
- $unsetindexes[] = $cpentry[5];
}
unset($cpdb);
-
- if (!empty($unsetindexes)) {
- captiveportal_remove_entries($unsetindexes);
- }
}
/* send RADIUS acct stop for all current clients */
OpenPOWER on IntegriCloud