From a9a28c74b02f6bebb7dbc17317ccfaf4be4cc618 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sat, 27 Dec 2014 16:48:27 +0000 Subject: [PATCH] fix captive portal prune sessions, radius still needs work, old code copied back but not sure if this works --- src/etc/inc/captiveportal.inc | 438 +++++++----------- src/etc/inc/voucher.inc | 14 +- src/etc/rc.prunecaptiveportal | 13 +- .../mvc/app/models/Captiveportal/CPClient.php | 97 +++- 4 files changed, 245 insertions(+), 317 deletions(-) diff --git a/src/etc/inc/captiveportal.inc b/src/etc/inc/captiveportal.inc index bcafc981b..651e48434 100644 --- a/src/etc/inc/captiveportal.inc +++ b/src/etc/inc/captiveportal.inc @@ -645,292 +645,189 @@ function captiveportal_init_webgui_zone($cpcfg) { * (password is in Base64 and only saved when reauthentication is enabled) */ function captiveportal_prune_old() { + global $g, $config, $cpzone, $cpzoneid; if (empty($cpzone)) return; + $cpc = new Captiveportal\CPClient(); + $cpcfg = $config['captiveportal'][$cpzone]; - $vcpcfg = $config['voucher'][$cpzone]; + if ( !isset($cpcfg['radacct_enable'])) { + // cleanup session (default) + $cpc->portal_cleanup_sessions($cpzone); + }else{ + // cleanup sessions if radius accounting is enable + // TODO: this code needs a rewrite, probably the easiest thing todo is update the zone administration and run + // the normal cleanup (portal_cleanup_sessions) to detach both processes + // + $vcpcfg = $config['voucher'][$cpzone]; - /* check for expired entries */ - $idletimeout = 0; - $timeout = 0; - if (!empty($cpcfg['timeout']) && is_numeric($cpcfg['timeout'])) - $timeout = $cpcfg['timeout'] * 60; + /* check for expired entries */ + $idletimeout = 0; + $timeout = 0; + if (!empty($cpcfg['timeout']) && is_numeric($cpcfg['timeout'])) + $timeout = $cpcfg['timeout'] * 60; - if (!empty($cpcfg['idletimeout']) && is_numeric($cpcfg['idletimeout'])) - $idletimeout = $cpcfg['idletimeout'] * 60; + if (!empty($cpcfg['idletimeout']) && is_numeric($cpcfg['idletimeout'])) + $idletimeout = $cpcfg['idletimeout'] * 60; - /* Is there any job to do? */ - if (!$timeout && !$idletimeout && !isset($cpcfg['reauthenticate']) && - !isset($cpcfg['radiussession_timeout']) && !isset($vcpcfg['enable'])) - return; + /* Is there any job to do? */ + if (!$timeout && !$idletimeout && !isset($cpcfg['reauthenticate']) && + !isset($cpcfg['radiussession_timeout']) && !isset($vcpcfg['enable'])) + return; - $radiussrvs = captiveportal_get_radius_servers(); + $radiussrvs = captiveportal_get_radius_servers(); - /* Read database */ - /* NOTE: while this can be simplified in non radius case keep as is for now */ - $cpdb = captiveportal_read_db(); + /* Read database */ + /* NOTE: while this can be simplified in non radius case keep as is for now */ + $cpdb = captiveportal_read_db(); - $unsetindexes = array(); - $voucher_needs_sync = false; - /* - * Snapshot the time here to use for calculation to speed up the process. - * If something is missed next run will catch it! - */ - $pruning_time = time(); - $stop_time = $pruning_time; - foreach ($cpdb as $cpentry) { + $unsetindexes = array(); - $timedout = false; - $term_cause = 1; - if (empty($cpentry[11])) - $cpentry[11] = 'first'; - $radiusservers = $radiussrvs[$cpentry[11]]; + /* + * Snapshot the time here to use for calculation to speed up the process. + * If something is missed next run will catch it! + */ + $pruning_time = time(); + $stop_time = $pruning_time; + foreach ($cpdb as $cpentry) { - /* hard timeout? */ - if ($timeout) { - if (($pruning_time - $cpentry[0]) >= $timeout) { - $timedout = true; - $term_cause = 5; // Session-Timeout - } - } + $timedout = false; + $term_cause = 1; + if (empty($cpentry[11])) + $cpentry[11] = 'first'; + $radiusservers = $radiussrvs[$cpentry[11]]; - /* Session-Terminate-Time */ - if (!$timedout && !empty($cpentry[9])) { - if ($pruning_time >= $cpentry[9]) { - $timedout = true; - $term_cause = 5; // Session-Timeout - } - } - - /* check if the radius idle_timeout attribute has been set and if its set change the idletimeout to this value */ - $uidletimeout = (is_numeric($cpentry[8])) ? $cpentry[8] : $idletimeout; - /* if an idle timeout is specified, get last activity timestamp from ipfw */ - if (!$timedout && $uidletimeout > 0) { - $lastact = captiveportal_get_last_activity($cpentry[2], $cpentry[3]); - /* 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 : $cpentry[0]; - if ($lastact && (($pruning_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 */ - if (!$timedout && isset($vcpcfg['enable']) && !empty($cpentry[7])) { - if ($pruning_time >= ($cpentry[0] + $cpentry[7])) { - $timedout = true; - $term_cause = 5; // Session-Timeout - $voucher_needs_sync = true; - } - } - - /* if radius session_timeout is enabled and the session_timeout is not null, then check if the user should be logged out */ - if (!$timedout && isset($cpcfg['radiussession_timeout']) && !empty($cpentry[7])) { - if ($pruning_time >= ($cpentry[0] + $cpentry[7])) { - $timedout = true; - $term_cause = 5; // Session-Timeout - } - } - - if ($timedout) { - captiveportal_disconnect($cpentry, $radiusservers,$term_cause,$stop_time); - captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "TIMEOUT"); - $unsetindexes[] = $cpentry[5]; - } - - /* do periodic RADIUS reauthentication? */ - if (!$timedout && !empty($radiusservers)) { - if (isset($cpcfg['radacct_enable'])) { - if ($cpcfg['reauthenticateacct'] == "stopstart") { - /* stop and restart accounting */ - RADIUS_ACCOUNTING_STOP($cpentry[1], // ruleno - $cpentry[4], // username - $cpentry[5], // sessionid - $cpentry[0], // start time - $radiusservers, - $cpentry[2], // clientip - $cpentry[3], // clientmac - 10); // NAS Request - $_gb = @pfSense_ipfw_Tableaction($cpzoneid, IP_FW_TABLE_XZEROENTRY, 1, $cpentry[2], $cpentry[3]); - $_gb = @pfSense_ipfw_Tableaction($cpzoneid, IP_FW_TABLE_XZEROENTRY, 2, $cpentry[2], $cpentry[3]); - RADIUS_ACCOUNTING_START($cpentry[1], // ruleno - $cpentry[4], // username - $cpentry[5], // sessionid - $radiusservers, - $cpentry[2], // clientip - $cpentry[3]); // clientmac - } else if ($cpcfg['reauthenticateacct'] == "interimupdate") { - $session_time = $pruning_time - $cpentry[0]; - if (!empty($cpentry[10]) && $cpentry[10] > 60) - $interval = $cpentry[10]; - else - $interval = 0; - $past_interval_min = ($session_time > $interval); - if ($interval != 0) - $within_interval = ($session_time % $interval >= 0 && $session_time % $interval <= 59); - if ($interval === 0 || ($interval > 0 && $past_interval_min && $within_interval)) { - RADIUS_ACCOUNTING_STOP($cpentry[1], // ruleno - $cpentry[4], // username - $cpentry[5], // sessionid - $cpentry[0], // start time - $radiusservers, - $cpentry[2], // clientip - $cpentry[3], // clientmac - 10, // NAS Request - true); // Interim Updates - } + /* hard timeout? */ + if ($timeout) { + if (($pruning_time - $cpentry[0]) >= $timeout) { + $timedout = true; + $term_cause = 5; // Session-Timeout } } - /* check this user against RADIUS again */ - if (isset($cpcfg['reauthenticate'])) { - $auth_list = RADIUS_AUTHENTICATION($cpentry[4], // username - base64_decode($cpentry[6]), // password - $radiusservers, - $cpentry[2], // clientip - $cpentry[3], // clientmac - $cpentry[1]); // ruleno - if ($auth_list['auth_val'] == 3) { - captiveportal_disconnect($cpentry, $radiusservers, 17); - captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "RADIUS_DISCONNECT", $auth_list['reply_message']); - $unsetindexes[] = $cpentry[5]; - } else if ($auth_list['auth_val'] == 2) - captiveportal_reapply_attributes($cpentry, $auth_list); + /* Session-Terminate-Time */ + if (!$timedout && !empty($cpentry[9])) { + if ($pruning_time >= $cpentry[9]) { + $timedout = true; + $term_cause = 5; // Session-Timeout + } + } + + /* check if the radius idle_timeout attribute has been set and if its set change the idletimeout to this value */ + $uidletimeout = (is_numeric($cpentry[8])) ? $cpentry[8] : $idletimeout; + /* if an idle timeout is specified, get last activity timestamp from ipfw */ + if (!$timedout && $uidletimeout > 0) { + $lastact = captiveportal_get_last_activity($cpentry[2], $cpentry[3]); + /* 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 : $cpentry[0]; + if ($lastact && (($pruning_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 */ + if (!$timedout && isset($vcpcfg['enable']) && !empty($cpentry[7])) { + if ($pruning_time >= ($cpentry[0] + $cpentry[7])) { + $timedout = true; + $term_cause = 5; // Session-Timeout + $voucher_needs_sync = true; + } + } + + /* if radius session_timeout is enabled and the session_timeout is not null, then check if the user should be logged out */ + if (!$timedout && isset($cpcfg['radiussession_timeout']) && !empty($cpentry[7])) { + if ($pruning_time >= ($cpentry[0] + $cpentry[7])) { + $timedout = true; + $term_cause = 5; // Session-Timeout + } + } + + if ($timedout) { + captiveportal_disconnect($cpentry, $radiusservers,$term_cause,$stop_time); + captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "TIMEOUT"); + $unsetindexes[] = $cpentry[5]; + } + + /* do periodic RADIUS reauthentication? */ + if (!$timedout && !empty($radiusservers)) { + if (isset($cpcfg['radacct_enable'])) { + if ($cpcfg['reauthenticateacct'] == "stopstart") { + /* stop and restart accounting */ + RADIUS_ACCOUNTING_STOP($cpentry->pipeno_in, // ruleno + $cpentry->username, // username + $cpentry->sessionid, // sessionid + $cpentry->allow_time, // start time + $radiusservers, + $cpentry->ip, // clientip + $cpentry->mac, // clientmac + 10); // NAS Request + + // todo, zero counters + + RADIUS_ACCOUNTING_START($cpentry->pipeno_in, // ruleno + $cpentry->username, // username + $cpentry->sessionid, // sessionid + $radiusservers, + $cpentry->ip, // clientip + $cpentry->mac); // clientmac + } else if ($cpcfg['reauthenticateacct'] == "interimupdate") { + $session_time = $pruning_time - $cpentry[0]; + if (!empty($cpentry[10]) && $cpentry[10] > 60) + $interval = $cpentry[10]; + else + $interval = 0; + $past_interval_min = ($session_time > $interval); + if ($interval != 0) + $within_interval = ($session_time % $interval >= 0 && $session_time % $interval <= 59); + if ($interval === 0 || ($interval > 0 && $past_interval_min && $within_interval)) { + RADIUS_ACCOUNTING_STOP($cpentry->pipeno_in, // ruleno + $cpentry->username, // username + $cpentry->sessionid, // sessionid + $cpentry->allow_time, // start time + $radiusservers, + $cpentry->ip, // clientip + $cpentry->mac, // clientmac + 10, // NAS Request + true); // Interim Updates + } + } + } + + /* check this user against RADIUS again */ + if (isset($cpcfg['reauthenticate'])) { + $auth_list = RADIUS_AUTHENTICATION($cpentry[4], // username + base64_decode($cpentry->bpassword), // password + $radiusservers, + $cpentry->ip, // clientip + $cpentry->mac, // clientmac + $cpentry->pipeno_in); // ruleno + if ($auth_list['auth_val'] == 3) { + $cpc->disconnect($cpzone, $cpentry->sessionid); + captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "RADIUS_DISCONNECT", $auth_list['reply_message']); + $unsetindexes[] = $cpentry[5]; + } else if ($auth_list['auth_val'] == 2) + //captiveportal_reapply_attributes($cpentry, $auth_list); + null; + } } } + } + + + + + unset($cpdb); - captiveportal_prune_old_automac(); - if ($voucher_needs_sync == true) - /* Triger a sync of the vouchers on config */ - send_event("service sync vouchers"); - - /* write database */ - if (!empty($unsetindexes)) - captiveportal_remove_entries($unsetindexes); -} - -function captiveportal_prune_old_automac() { - global $g, $config, $cpzone, $cpzoneid; - - if (is_array($config['captiveportal'][$cpzone]['passthrumac']) && isset($config['captiveportal'][$cpzone]['passthrumacaddusername'])) { - $tmpvoucherdb = array(); - $macrules = ""; - $writecfg = false; - foreach ($config['captiveportal'][$cpzone]['passthrumac'] as $eid => $emac) { - if ($emac['logintype'] == "voucher") { - if (isset($config['captiveportal'][$cpzone]['noconcurrentlogins'])) { - if (isset($tmpvoucherdb[$emac['username']])) { - $temac = $config['captiveportal'][$cpzone]['passthrumac'][$tmpvoucherdb[$emac['username']]]; - $ruleno = captiveportal_get_ipfw_passthru_ruleno($temac['mac']); - $pipeno = captiveportal_get_dn_passthru_ruleno($temac['mac']); - if ($ruleno) { - captiveportal_free_ipfw_ruleno($ruleno); - $macrules .= "delete {$ruleno}"; - ++$ruleno; - $macrules .= "delete {$ruleno}"; - } - if ($pipeno) { - captiveportal_free_dn_ruleno($pipeno); - $macrules .= "pipe delete {$pipeno}\n"; - ++$pipeno; - $macrules .= "pipe delete {$pipeno}\n"; - } - $writecfg = true; - captiveportal_logportalauth($temac['username'], $temac['mac'], $temac['ip'], "DUPLICATE {$temac['username']} LOGIN - TERMINATING OLD SESSION"); - unset($config['captiveportal'][$cpzone]['passthrumac'][$tmpvoucherdb[$emac['username']]]); - } - $tmpvoucherdb[$emac['username']] = $eid; - } - if (voucher_auth($emac['username']) <= 0) { - $ruleno = captiveportal_get_ipfw_passthru_ruleno($emac['mac']); - $pipeno = captiveportal_get_dn_passthru_ruleno($emac['mac']); - if ($ruleno) { - captiveportal_free_ipfw_ruleno($ruleno); - $macrules .= "delete {$ruleno}"; - ++$ruleno; - $macrules .= "delete {$ruleno}"; - } - if ($pipeno) { - captiveportal_free_dn_ruleno($pipeno); - $macrules .= "pipe delete {$pipeno}\n"; - ++$pipeno; - $macrules .= "pipe delete {$pipeno}\n"; - } - $writecfg = true; - captiveportal_logportalauth($emac['username'], $emac['mac'], $emac['ip'], "EXPIRED {$emac['username']} LOGIN - TERMINATING SESSION"); - unset($config['captiveportal'][$cpzone]['passthrumac'][$eid]); - } - } - } - unset($tmpvoucherdb); - if (!empty($macrules)) { - @file_put_contents("{$g['tmp_path']}/macentry.prunerules.tmp", $macrules); - unset($macrules); - mwexec("/sbin/ipfw -x {$cpzoneid} -q {$g['tmp_path']}/macentry.prunerules.tmp"); - } - if ($writecfg === true) - write_config("Prune session for auto-added macs"); - } -} - -/* remove a single client according to the DB entry */ -function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_time = null) { - global $g, $config, $cpzone, $cpzoneid; - - $stop_time = (empty($stop_time)) ? time() : $stop_time; - - /* this client needs to be deleted - remove ipfw rules */ - if (isset($config['captiveportal'][$cpzone]['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); - } - - if (is_ipaddr($dbent[2])) { - /* Delete client's ip entry from tables 1 and 2. */ - $_gb = @pfSense_ipfw_Tableaction($cpzoneid, IP_FW_TABLE_XDEL, 1, $dbent[2], $dbent[3]); - $_gb = @pfSense_ipfw_Tableaction($cpzoneid, IP_FW_TABLE_XDEL, 2, $dbent[2], $dbent[3]); - /* XXX: Redundant?! Ensure all pf(4) states are killed. */ - $_gb = @pfSense_kill_states($dbent[2]); - $_gb = @pfSense_kill_srcstates($dbent[2]); - } - - /* - * These are the pipe numbers we use to control traffic shaping for each logged in user via captive portal - * We could get an error if the pipe doesn't exist but everything should still be fine - */ - if (!empty($dbent[1])) { - $_gb = @pfSense_pipe_action("pipe delete {$dbent[1]}"); - $_gb = @pfSense_pipe_action("pipe delete " . ($dbent[1]+1)); - - /* Release the ruleno so it can be reallocated to new clients. */ - captiveportal_free_dn_ruleno($dbent[1]); - } - - // XMLRPC Call over to the master Voucher node - if(!empty($config['voucher'][$cpzone]['vouchersyncdbip'])) { - $syncip = $config['voucher'][$cpzone]['vouchersyncdbip']; - $syncport = $config['voucher'][$cpzone]['vouchersyncport']; - $syncpass = $config['voucher'][$cpzone]['vouchersyncpass']; - $vouchersyncusername = $config['voucher'][$cpzone]['vouchersyncusername']; - $remote_status = xmlrpc_sync_voucher_disconnect($dbent, $syncip, $syncport, $syncpass, $vouchersyncusername, $term_cause, $stop_time); - } } @@ -1550,23 +1447,6 @@ function portal_mac_radius($clientmac,$clientip) { return FALSE; } -function captiveportal_reapply_attributes($cpentry, $attributes) { - global $config, $cpzone, $g; - - $dwfaultbw_up = isset($config['captiveportal'][$cpzone]['bwdefaultup']) ? $config['captiveportal'][$cpzone]['bwdefaultup'] : 0; - $dwfaultbw_down = isset($config['captiveportal'][$cpzone]['bwdefaultdn']) ? $config['captiveportal'][$cpzone]['bwdefaultdn'] : 0; - $bw_up = isset($attributes['bw_up']) ? round(intval($attributes['bw_up'])/1000, 2) : $dwfaultbw_up; - $bw_down = isset($attributes['bw_down']) ? round(intval($attributes['bw_down'])/1000, 2) : $dwfaultbw_down; - $bw_up_pipeno = $cpentry[1]; - $bw_down_pipeno = $cpentry[1]+1; - - $_gb = @pfSense_pipe_action("pipe {$bw_up_pipeno} config bw {$bw_up}Kbit/s queue 100 buckets 16"); - $_gb = @pfSense_pipe_action("pipe {$bw_down_pipeno} config bw {$bw_down}Kbit/s queue 100 buckets 16"); - //captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "RADIUS_BANDWIDTH_REAPPLY", "{$bw_up}/{$bw_down}"); - - unset($bw_up_pipeno, $bw_down_pipeno, $bw_up, $bw_down); -} - /* diff --git a/src/etc/inc/voucher.inc b/src/etc/inc/voucher.inc index d820dfb2a..e08f140f6 100644 --- a/src/etc/inc/voucher.inc +++ b/src/etc/inc/voucher.inc @@ -218,6 +218,9 @@ EOF; function voucher_expire($voucher_received) { global $g, $config, $cpzone; + $cpdb = new Captiveportal\DB($cpzone); + $cpc = new Captiveportal\CPClient(); + // XMLRPC Call over to the master Voucher node if(!empty($config['voucher'][$cpzone]['vouchersyncdbip'])) { $syncip = $config['voucher'][$cpzone]['vouchersyncdbip']; @@ -275,13 +278,11 @@ function voucher_expire($voucher_received) { captiveportal_syslog("{$voucher} ({$roll}/{$nr}) forced to expire"); /* Check if this voucher has any active sessions */ - $cpdb = new Captiveportal\DB($cpzone); - if ($db->countClients(array("username"=>$voucher)) > 0 ) { - captiveportal_disconnect(array("username"=>$voucher),null,13); - //TODO: fix logging (in disconnect?) captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"FORCLY TERMINATING VOUCHER {$voucher} SESSION"); + $clients = $cpdb->listClients(array("username"=>$voucher),null, null); + foreach($clients as $client ){ + $cpc->disconnect($cpzone,$client->sessionid); } - unset($cpdb); } else captiveportal_syslog("$voucher ($roll/$nr): not found on any registererd Roll"); } else @@ -312,6 +313,9 @@ function voucher_expire($voucher_received) { unset($bitstring); } + unset($cpdb); + unset($cpc); + unlock($voucherlck); return true; diff --git a/src/etc/rc.prunecaptiveportal b/src/etc/rc.prunecaptiveportal index 17667aece..87eb2337f 100755 --- a/src/etc/rc.prunecaptiveportal +++ b/src/etc/rc.prunecaptiveportal @@ -47,19 +47,16 @@ if (!is_array($config['captiveportal'][$cpzone])) { return; } $cpzoneid = $config['captiveportal'][$cpzone]['zoneid']; - -if (file_exists("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running")) { - $stat = stat("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running"); +if (file_exists("{$g['tmp_path']}/.rc.prunecaptiveportal.running")) { + $stat = stat("{$g['tmp_path']}/.rc.prunecaptiveportal.running"); if (time() - $stat['mtime'] >= 120) - @unlink("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running"); + @unlink("{$g['tmp_path']}/.rc.prunecaptiveportal.running"); else { log_error("Skipping CP prunning process because previous/another instance is already running"); return; } } - -@file_put_contents("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running", ""); +@file_put_contents("{$g['tmp_path']}/.rc.prunecaptiveportal.running", ""); captiveportal_prune_old(); -@unlink("{$g['tmp_path']}/.rc.prunecaptiveportal.{$cpzone}.running"); - +@unlink("{$g['tmp_path']}/.rc.prunecaptiveportal.running"); ?> diff --git a/src/opnsense/mvc/app/models/Captiveportal/CPClient.php b/src/opnsense/mvc/app/models/Captiveportal/CPClient.php index 82fd818d3..07bc8ce9b 100644 --- a/src/opnsense/mvc/app/models/Captiveportal/CPClient.php +++ b/src/opnsense/mvc/app/models/Captiveportal/CPClient.php @@ -60,6 +60,27 @@ class CPClient { */ private $shell = null; + /** + * send message to syslog + * + * @param $status + * @param $user + * @param $mac + * @param $ip + * @param string $message + */ + private function logportalauth($user,$mac,$ip,$status,$message=""){ + + $message = trim($message); + $message = "{$status}: {$user}, {$mac}, {$ip}, {$message}"; + + $logger = new \Phalcon\Logger\Adapter\Syslog("logportalauth", array( + 'option' => LOG_PID, + 'facility' => LOG_LOCAL4 + )); + $logger->info($message); + + } /** * Request new pipeno * @return int @@ -169,6 +190,7 @@ class CPClient { $parts = preg_split('/\s+/', $line); if (count($parts) > 8 && $parts[7] != 'any' and strlen($parts[7]) > 5) { $result[$parts[7]] = array( + "rulenum" => $parts[0], "last_accessed" => (int)$parts[3], "idle_time" => time() - (int)$parts[3], "out_packets" => (int)$parts[1], @@ -183,6 +205,21 @@ class CPClient { } + /** + * reset traffic counters + * + * @param null $rulenum + */ + public function zero_counters($rulenum=null){ + if ( $rulenum != null and is_numeric($rulenum) ){ + $this->shell->exec("/sbin/ipfw zero " . $rulenum ); + } + elseif ( $rulenum == null ){ + $this->shell->exec("/sbin/ipfw zero " ); + } + + } + /** * Constructor */ @@ -512,8 +549,8 @@ class CPClient { $this->reset_bandwidth($pipeno_in,$bw_up); $this->reset_bandwidth($pipeno_in,$bw_down); - - // TODO : Add logging, ( captiveportal_logportalauth($cpentry[4],$cpentry[3],$cpentry[2],"CONCURRENT LOGIN - TERMINATING OLD SESSION"); ) + // log + $this->logportalauth($username,$clientmac,$clientip,$status="LOGIN"); // cleanup unset($db); @@ -521,7 +558,6 @@ class CPClient { return $sessionid; } - /** * disconnect a session or a list of sessions depending on the parameter * @param string $cpzonename zone name or id @@ -538,6 +574,7 @@ class CPClient { } } + /** * flush zone (null flushes all zones) * @param null $zone @@ -576,38 +613,48 @@ class CPClient { /** * cleanup portal sessions */ - function portal_cleanup_sessions(){ + function portal_cleanup_sessions($cpzone=null){ $acc_list = $this->list_accounting(); foreach($this->config->object()->captiveportal->children() as $cpzonename => $zoneobj){ - $db = new DB($cpzonename); + if ( $cpzone == null || $cpzone == $cpzonename ) { + $db = new DB($cpzonename); - $clients = $db->listClients(array(),null, null); + $clients = $db->listClients(array(), null, null); - foreach($clients as $client ){ - $idle_time = 0; - if ( array_key_exists ( $client->ip ,$acc_list ) ){ - $idle_time = $acc_list[$client->ip]; - } + foreach ($clients as $client) { + $idle_time = 0; + if (array_key_exists($client->ip, $acc_list)) { + $idle_time = $acc_list[$client->ip]; + } - // if session timeout is reached, disconnect - if ( $client->session_timeout != "" ){ - if ( ((time() - $client->allow_time)/60) > $client->session_timeout ){ - $this->disconnect($cpzonename,$client->sessionid); + // if session timeout is reached, disconnect + if (is_numeric($client->session_timeout) && $client->session_timeout > 0 ) { + if (((time() - $client->allow_time) / 60) > $client->session_timeout) { + $this->disconnect($cpzonename, $client->sessionid); + $this->logportalauth($client->username,$client->mac,$client->ip,$status="SESSION TIMEOUT"); + continue; + } + } + + // disconnect session if idle timeout is reached + if (is_numeric($client->idle_timeout) && $client->idle_timeout > 0 && $idle_time > 0) { + if ($idle_time > $client->idle_timeout) { + $this->disconnect($cpzonename, $client->sessionid); + $this->logportalauth($client->username,$client->mac,$client->ip,$status="IDLE TIMEOUT"); + continue; + } + } + + // disconnect on session terminate time + if ($client->session_terminate_time != "" && $client->session_terminate_time < time()) { + $this->disconnect($cpzonename, $client->sessionid); + $this->logportalauth($client->username,$client->mac,$client->ip,$status="TERMINATE TIME REACHED"); continue; } } - // disconnect session if idle timeout is reached - if ( $client->idle_timeout != "" && $idle_time > 0 ){ - if ( $idle_time > $client->idle_timeout ){ - $this->disconnect($cpzonename,$client->sessionid); - continue; - } - } + unset($db); } - - unset($db); - } unset ($acc_list);