summaryrefslogtreecommitdiffstats
path: root/etc/inc/captiveportal.inc
diff options
context:
space:
mode:
Diffstat (limited to 'etc/inc/captiveportal.inc')
-rw-r--r--etc/inc/captiveportal.inc274
1 files changed, 131 insertions, 143 deletions
diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc
index e36a626..84c98b2 100644
--- a/etc/inc/captiveportal.inc
+++ b/etc/inc/captiveportal.inc
@@ -206,7 +206,7 @@ EOD;
function captiveportal_configure() {
global $config, $g;
- $captiveportallck = lock('captiveportal');
+ $captiveportallck = lock('captiveportal', LOCK_EX);
if (isset($config['captiveportal']['enable'])) {
@@ -233,13 +233,14 @@ function captiveportal_configure() {
captiveportal_init_rules(true);
/* stop accounting on all clients */
- captiveportal_radius_stop_all(true);
+ captiveportal_radius_stop_all();
/* initialize minicron interval value */
$croninterval = $config['captiveportal']['croninterval'] ? $config['captiveportal']['croninterval'] : 60;
/* double check if the $croninterval is numeric and at least 10 seconds. If not we set it to 60 to avoid problems */
- if ((!is_numeric($croninterval)) || ($croninterval < 10)) { $croninterval = 60; }
+ if ((!is_numeric($croninterval)) || ($croninterval < 10))
+ $croninterval = 60;
/* write portal page */
if ($config['captiveportal']['page']['htmltext'])
@@ -414,41 +415,7 @@ EOD;
"/etc/rc.prunecaptiveportal");
/* generate radius server database */
- if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) ||
- ($config['captiveportal']['auth_method'] == "radius"))) {
- $radiusip = $config['captiveportal']['radiusip'];
- $radiusip2 = ($config['captiveportal']['radiusip2']) ? $config['captiveportal']['radiusip2'] : null;
-
- if ($config['captiveportal']['radiusport'])
- $radiusport = $config['captiveportal']['radiusport'];
- else
- $radiusport = 1812;
-
- if ($config['captiveportal']['radiusacctport'])
- $radiusacctport = $config['captiveportal']['radiusacctport'];
- else
- $radiusacctport = 1813;
-
- if ($config['captiveportal']['radiusport2'])
- $radiusport2 = $config['captiveportal']['radiusport2'];
- else
- $radiusport2 = 1812;
-
- $radiuskey = $config['captiveportal']['radiuskey'];
- $radiuskey2 = ($config['captiveportal']['radiuskey2']) ? $config['captiveportal']['radiuskey2'] : null;
-
- $fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db", "w");
- if (!$fd) {
- printf("Error: cannot open radius DB file in captiveportal_configure().\n");
- return 1;
- } else if (isset($radiusip2, $radiuskey2)) {
- fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey . "\n"
- . $radiusip2 . "," . $radiusport2 . "," . $radiusacctport . "," . $radiuskey2);
- } else {
- fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey);
- }
- fclose($fd);
- }
+ captiveportal_init_radius_servers();
if ($g['booting'])
echo "done\n";
@@ -457,7 +424,7 @@ EOD;
killbypid("{$g['varrun_path']}/lighty-CaptivePortal.pid");
killbypid("{$g['varrun_path']}/minicron.pid");
- captiveportal_radius_stop_all(true);
+ captiveportal_radius_stop_all();
mwexec("/sbin/sysctl net.link.ether.ipfw=0");
@@ -706,32 +673,31 @@ EOD;
return $cprules;
}
-/* remove clients that have been around for longer than the specified amount of time */
-/* db file structure:
-timestamp,ipfw_rule_no,clientip,clientmac,username,sessionid,password,session_timeout,idle_timeout,session_terminate_time */
-
-/* (password is in Base64 and only saved when reauthentication is enabled) */
+/* remove clients that have been around for longer than the specified amount of time
+ * db file structure:
+ * timestamp,ipfw_rule_no,clientip,clientmac,username,sessionid,password,session_timeout,idle_timeout,session_terminate_time
+ * (password is in Base64 and only saved when reauthentication is enabled)
+ */
function captiveportal_prune_old() {
-
global $g, $config;
/* check for expired entries */
- if ($config['captiveportal']['timeout'])
- $timeout = $config['captiveportal']['timeout'] * 60;
- else
+ if (empty($config['captiveportal']['timeout']) ||
+ !is_numeric($config['captiveportal']['timeout']))
$timeout = 0;
-
- if ($config['captiveportal']['idletimeout'])
- $idletimeout = $config['captiveportal']['idletimeout'] * 60;
else
+ $timeout = $config['captiveportal']['timeout'] * 60;
+
+ if (empty($config['captiveportal']['idletimeout']) ||
+ !is_numeric($config['captiveportal']['idletimeout']))
$idletimeout = 0;
+ else
+ $idletimeout = $config['captiveportal']['idletimeout'] * 60;
if (!$timeout && !$idletimeout && !isset($config['captiveportal']['reauthenticate']) &&
- !isset($config['captiveportal']['radiussession_timeout']) && !isset($config['voucher']['enable']))
+ !isset($config['captiveportal']['radiussession_timeout']) && !isset($config['voucher']['enable']))
return;
- $captiveportallck = lock('captiveportal');
-
/* read database */
$cpdb = captiveportal_read_db();
@@ -766,19 +732,19 @@ function captiveportal_prune_old() {
}
/* check if the radius idle_timeout attribute has been set and if its set change the idletimeout to this value */
- $idletimeout = (is_numeric($cpdb[$i][8])) ? $cpdb[$i][8] : $idletimeout;
+ $uidletimeout = (is_numeric($cpdb[$i][8])) ? $cpdb[$i][8] : $idletimeout;
/* if an idle timeout is specified, get last activity timestamp from ipfw */
- if (!$timedout && $idletimeout) {
- $lastact = captiveportal_get_last_activity($cpdb[$i][2]);
- /* If the user has logged on but not sent any traffic they will never be logged out.
- * We "fix" this by setting lastact to the login timestamp.
- */
- $lastact = $lastact ? $lastact : $cpdb[$i][0];
- if ($lastact && ((time() - $lastact) >= $idletimeout)) {
- $timedout = true;
- $term_cause = 4; // Idle-Timeout
- $stop_time = $lastact; // Entry added to comply with WISPr
- }
+ if (!$timedout && $uidletimeout) {
+ $lastact = captiveportal_get_last_activity($cpdb[$i][2]);
+ /* If the user has logged on but not sent any traffic they will never be logged out.
+ * We "fix" this by setting lastact to the login timestamp.
+ */
+ $lastact = $lastact ? $lastact : $cpdb[$i][0];
+ if ($lastact && ((time() - $lastact) >= $uidletimeout)) {
+ $timedout = true;
+ $term_cause = 4; // Idle-Timeout
+ $stop_time = $lastact; // Entry added to comply with WISPr
+ }
}
/* if vouchers are configured, activate session timeouts */
@@ -804,9 +770,7 @@ function captiveportal_prune_old() {
}
/* do periodic RADIUS reauthentication? */
- if (!$timedout && isset($config['captiveportal']['reauthenticate']) &&
- !empty($radiusservers)) {
-
+ if (!$timedout && !empty($radiusservers)) {
if (isset($config['captiveportal']['radacct_enable'])) {
if ($config['captiveportal']['reauthenticateacct'] == "stopstart") {
/* stop and restart accounting */
@@ -840,18 +804,20 @@ function captiveportal_prune_old() {
}
/* check this user against RADIUS again */
- $auth_list = RADIUS_AUTHENTICATION($cpdb[$i][4], // username
- base64_decode($cpdb[$i][6]), // password
+ if (isset($config['captiveportal']['reauthenticate'])) {
+ $auth_list = RADIUS_AUTHENTICATION($cpdb[$i][4], // username
+ base64_decode($cpdb[$i][6]), // password
$radiusservers,
$cpdb[$i][2], // clientip
$cpdb[$i][3], // clientmac
$cpdb[$i][1]); // ruleno
- if ($auth_list['auth_val'] == 3) {
- captiveportal_disconnect($cpdb[$i], $radiusservers, 17);
- captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "RADIUS_DISCONNECT", $auth_list['reply_message']);
- $unsetindexes[$i] = $i;
- }
+ if ($auth_list['auth_val'] == 3) {
+ captiveportal_disconnect($cpdb[$i], $radiusservers, 17);
+ captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "RADIUS_DISCONNECT", $auth_list['reply_message']);
+ $unsetindexes[$i] = $i;
+ }
+ }
}
}
/* This is a kludge to overcome some php weirdness */
@@ -860,13 +826,10 @@ function captiveportal_prune_old() {
/* write database */
captiveportal_write_db($cpdb);
-
- unlock($captiveportallck);
}
/* remove a single client according to the DB entry */
function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_time = null) {
-
global $g, $config;
$stop_time = (empty($stop_time)) ? time() : $stop_time;
@@ -874,15 +837,15 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t
/* this client needs to be deleted - remove ipfw rules */
if (isset($config['captiveportal']['radacct_enable']) && !empty($radiusservers)) {
RADIUS_ACCOUNTING_STOP($dbent[1], // ruleno
- $dbent[4], // username
- $dbent[5], // sessionid
- $dbent[0], // start time
- $radiusservers,
- $dbent[2], // clientip
- $dbent[3], // clientmac
- $term_cause, // Acct-Terminate-Cause
- false,
- $stop_time);
+ $dbent[4], // username
+ $dbent[5], // sessionid
+ $dbent[0], // start time
+ $radiusservers,
+ $dbent[2], // clientip
+ $dbent[3], // clientmac
+ $term_cause, // Acct-Terminate-Cause
+ false,
+ $stop_time);
}
/* Delete client's ip entry from tables 3 and 4. */
mwexec("/sbin/ipfw table 1 delete {$dbent[2]}");
@@ -908,22 +871,17 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t
/* remove a single client by ipfw rule number */
function captiveportal_disconnect_client($id,$term_cause = 1) {
-
global $g, $config;
- $captiveportallck = lock('captiveportal');
-
/* read database */
$cpdb = captiveportal_read_db();
$radiusservers = captiveportal_get_radius_servers();
/* find entry */
- $tmpindex = 0;
- $cpdbcount = count($cpdb);
- for ($i = 0; $i < $cpdbcount; $i++) {
- if ($cpdb[$i][1] == $id) {
- captiveportal_disconnect($cpdb[$i], $radiusservers, $term_cause);
- captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "DISCONNECT");
+ foreach ($cpdb as $i => $cpentry) {
+ if ($cpentry[1] == $id) {
+ captiveportal_disconnect($cpentry, $radiusservers, $term_cause);
+ captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "DISCONNECT");
unset($cpdb[$i]);
break;
}
@@ -931,37 +889,29 @@ function captiveportal_disconnect_client($id,$term_cause = 1) {
/* write database */
captiveportal_write_db($cpdb);
-
- unlock($captiveportallck);
}
/* send RADIUS acct stop for all current clients */
-function captiveportal_radius_stop_all($lock = false) {
- global $g, $config;
+function captiveportal_radius_stop_all() {
+ global $config;
if (!isset($config['captiveportal']['radacct_enable']))
return;
- if (!$lock)
- $captiveportallck = lock('captiveportal');
-
- $cpdb = captiveportal_read_db();
-
$radiusservers = captiveportal_get_radius_servers();
if (!empty($radiusservers)) {
- for ($i = 0; $i < count($cpdb); $i++) {
- RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno
- $cpdb[$i][4], // username
- $cpdb[$i][5], // sessionid
- $cpdb[$i][0], // start time
- $radiusservers,
- $cpdb[$i][2], // clientip
- $cpdb[$i][3], // clientmac
- 7); // Admin Reboot
+ $cpdb = captiveportal_read_db();
+ foreach ($cpdb as $cpentry) {
+ RADIUS_ACCOUNTING_STOP($cpentry[1], // ruleno
+ $cpentry[4], // username
+ $cpentry[5], // sessionid
+ $cpentry[0], // start time
+ $radiusservers,
+ $cpentry[2], // clientip
+ $cpentry[3], // clientmac
+ 7); // Admin Reboot
}
}
- if (!$lock)
- unlock($captiveportallck);
}
function captiveportal_passthrumac_configure_entry($macent) {
@@ -1123,11 +1073,51 @@ function captiveportal_get_last_activity($ip) {
return 0;
}
+function captiveportal_init_radius_servers() {
+ global $config, $g;
+
+ /* generate radius server database */
+ if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) ||
+ ($config['captiveportal']['auth_method'] == "radius"))) {
+ $radiusip = $config['captiveportal']['radiusip'];
+ $radiusip2 = ($config['captiveportal']['radiusip2']) ? $config['captiveportal']['radiusip2'] : null;
+
+ if ($config['captiveportal']['radiusport'])
+ $radiusport = $config['captiveportal']['radiusport'];
+ else
+ $radiusport = 1812;
+ if ($config['captiveportal']['radiusacctport'])
+ $radiusacctport = $config['captiveportal']['radiusacctport'];
+ else
+ $radiusacctport = 1813;
+ if ($config['captiveportal']['radiusport2'])
+ $radiusport2 = $config['captiveportal']['radiusport2'];
+ else
+ $radiusport2 = 1812;
+ $radiuskey = $config['captiveportal']['radiuskey'];
+ $radiuskey2 = ($config['captiveportal']['radiuskey2']) ? $config['captiveportal']['radiuskey2'] : null;
+
+ $cprdsrvlck = lock('captiveportalradius', LOCK_EX);
+ $fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db", "w");
+ if (!$fd) {
+ captiveportal_syslog("Error: cannot open radius DB file in captiveportal_configure().\n");
+ unlock($cprdsrvlck);
+ return 1;
+ } else if (isset($radiusip2, $radiuskey2))
+ fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey . "\n"
+ . $radiusip2 . "," . $radiusport2 . "," . $radiusacctport . "," . $radiuskey2);
+ else
+ fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey);
+ fclose($fd);
+ unlock($cprdsrvlck);
+ }
+}
+
/* read RADIUS servers into array */
function captiveportal_get_radius_servers() {
-
global $g;
+ $cprdsrvlck = lock('captiveportalradius');
if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) {
$radiusservers = array();
$cpradiusdb = file("{$g['vardb_path']}/captiveportal_radius.db",
@@ -1142,23 +1132,25 @@ function captiveportal_get_radius_servers() {
}
}
+ unlock($cprdsrvlck);
return $radiusservers;
}
+ unlock($cprdsrvlck);
return false;
}
/* log successful captive portal authentication to syslog */
/* part of this code from php.net */
function captiveportal_logportalauth($user,$mac,$ip,$status, $message = null) {
- $message = trim($message);
// Log it
if (!$message)
$message = "$status: $user, $mac, $ip";
- else
+ else {
+ $message = trim($message);
$message = "$status: $user, $mac, $ip, $message";
+ }
captiveportal_syslog($message);
- closelog();
}
/* log simple messages to syslog */
@@ -1174,9 +1166,6 @@ function captiveportal_syslog($message) {
function radius($username,$password,$clientip,$clientmac,$type) {
global $g, $config;
- /* Start locking from the beginning of an authentication session */
- $captiveportallck = lock('captiveportal');
-
$ruleno = captiveportal_get_next_ipfw_ruleno();
/* If the pool is empty, return appropriate message and fail authentication */
@@ -1184,16 +1173,9 @@ function radius($username,$password,$clientip,$clientmac,$type) {
$auth_list = array();
$auth_list['auth_val'] = 1;
$auth_list['error'] = "System reached maximum login capacity";
- unlock($captiveportallck);
return $auth_list;
}
- /*
- * Drop the lock since radius takes some time to finish.
- * The implementation is reentrant so we gain speed with this.
- */
- unlock($captiveportallck);
-
$radiusservers = captiveportal_get_radius_servers();
$auth_list = RADIUS_AUTHENTICATION($username,
@@ -1203,8 +1185,6 @@ function radius($username,$password,$clientip,$clientmac,$type) {
$clientmac,
$ruleno);
- $captiveportallck = lock('captiveportal');
-
if ($auth_list['auth_val'] == 2) {
captiveportal_logportalauth($username,$clientmac,$clientip,$type);
$sessionid = portal_allow($clientip,
@@ -1215,18 +1195,16 @@ function radius($username,$password,$clientip,$clientmac,$type) {
$ruleno);
}
- unlock($captiveportallck);
-
return $auth_list;
-
}
/* read captive portal DB into array */
function captiveportal_read_db() {
-
global $g;
$cpdb = array();
+
+ $cpdblck = lock('captiveportaldb');
$fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r");
if ($fd) {
while (!feof($fd)) {
@@ -1237,21 +1215,23 @@ function captiveportal_read_db() {
}
fclose($fd);
}
+ unlock($cpdblck);
return $cpdb;
}
/* write captive portal DB */
function captiveportal_write_db($cpdb) {
-
global $g;
-
+
+ $cpdblck = lock('captiveportaldb', LOCK_EX);
$fd = @fopen("{$g['vardb_path']}/captiveportal.db", "w");
- if ($fd) {
+ if ($fd) {
foreach ($cpdb as $cpent) {
fwrite($fd, join(",", $cpent) . "\n");
- }
+ }
fclose($fd);
- }
+ }
+ unlock($cpdblck);
}
function captiveportal_write_elements() {
@@ -1308,6 +1288,7 @@ function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_rang
if(!isset($config['captiveportal']['enable']))
return NULL;
+ $cpruleslck = lock('captiveportalrules', LOCK_EX);
$ruleno = 0;
if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
$rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
@@ -1334,6 +1315,7 @@ function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_rang
$ruleno = 2;
}
file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules));
+ unlock($cpruleslck);
return $ruleno;
}
@@ -1343,6 +1325,7 @@ function captiveportal_free_ipfw_ruleno($ruleno, $usedbw = false) {
if(!isset($config['captiveportal']['enable']))
return NULL;
+ $cpruleslck = lock('captiveportalrules', LOCK_EX);
if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
$rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
$rules[$ruleno] = false;
@@ -1350,6 +1333,7 @@ function captiveportal_free_ipfw_ruleno($ruleno, $usedbw = false) {
$rules[++$ruleno] = false;
file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules));
}
+ unlock($cpruleslck);
}
function captiveportal_get_ipfw_passthru_ruleno($value) {
@@ -1358,13 +1342,17 @@ function captiveportal_get_ipfw_passthru_ruleno($value) {
if(!isset($config['captiveportal']['enable']))
return NULL;
+ $cpruleslck = lock('captiveportalrules', LOCK_EX);
if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
$rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
$ruleno = intval(`/sbin/ipfw show | /usr/bin/grep {$value} | /usr/bin/grep -v grep | /usr/bin/cut -d " " -f 1 | /usr/bin/head -n 1`);
- if ($rules[$ruleno])
+ if ($rules[$ruleno]) {
+ unlock($cpruleslck);
return $ruleno;
+ }
}
+ unlock($cpruleslck);
return NULL;
}
OpenPOWER on IntegriCloud