Commit ad276991 authored by Ad Schellevis's avatar Ad Schellevis

code styling fixes (PSR) for captive new captive portal code

parent 6e46796a
...@@ -172,7 +172,7 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut ...@@ -172,7 +172,7 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut
} }
$sessionid = $cpc->portal_allow($cpzone,$clientip,$clientmac,$username,$password,$bw_up,$bw_down,$radiusctx,$session_timeout,$idle_timeout,$session_terminate_time,$interim_interval); $sessionid = $cpc->portalAllow($cpzone,$clientip,$clientmac,$username,$password,$bw_up,$bw_down,$radiusctx,$session_timeout,$idle_timeout,$session_terminate_time,$interim_interval);
if (isset($config['captiveportal'][$cpzone]['radacct_enable']) && !empty($radiusservers[$radiusctx])) { if (isset($config['captiveportal'][$cpzone]['radacct_enable']) && !empty($radiusservers[$radiusctx])) {
$acct_val = RADIUS_ACCOUNTING_START($pipeno, $username, $sessionid, $radiusservers[$radiusctx], $clientip, $clientmac); $acct_val = RADIUS_ACCOUNTING_START($pipeno, $username, $sessionid, $radiusservers[$radiusctx], $clientip, $clientmac);
...@@ -699,11 +699,11 @@ function captiveportal_prune_old() { ...@@ -699,11 +699,11 @@ function captiveportal_prune_old() {
$cpcfg = $config['captiveportal'][$cpzone]; $cpcfg = $config['captiveportal'][$cpzone];
if ( !isset($cpcfg['radacct_enable'])) { if ( !isset($cpcfg['radacct_enable'])) {
// cleanup session (default) // cleanup session (default)
$cpc->portal_cleanup_sessions($cpzone); $cpc->portalCleanupSessions($cpzone);
}else{ }else{
// cleanup sessions if radius accounting is enable // 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 // 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 // the normal cleanup (portalCleanupSessions) to detach both processes
// //
$vcpcfg = $config['voucher'][$cpzone]; $vcpcfg = $config['voucher'][$cpzone];
......
...@@ -41,7 +41,7 @@ class ARP ...@@ -41,7 +41,7 @@ class ARP
* pointer to shell object * pointer to shell object
* @var \Core\Shell * @var \Core\Shell
*/ */
private $shell ; private $shell;
/** /**
* construct new ARP table handlers * construct new ARP table handlers
...@@ -59,11 +59,9 @@ class ARP ...@@ -59,11 +59,9 @@ class ARP
public function setStatic($ipaddress, $mac) public function setStatic($ipaddress, $mac)
{ {
// validate input, only set static entries for valid addresses // validate input, only set static entries for valid addresses
if (preg_match('/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/', trim($mac))) if (preg_match('/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/', trim($mac))) {
{ if (filter_var($ipaddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
if ( filter_var($ipaddress , FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_IPV6) ) $this->shell->exec("/usr/sbin/arp -s " . trim($ipaddress) . " " . trim($mac));
{
$this->shell->exec("/usr/sbin/arp -s ".trim($ipaddress)." ".trim($mac));
} }
} }
} }
...@@ -72,41 +70,46 @@ class ARP ...@@ -72,41 +70,46 @@ class ARP
* drop static arp entry * drop static arp entry
* @param $ipaddress hosts ipaddress * @param $ipaddress hosts ipaddress
*/ */
function dropStatic($ipaddress){ public function dropStatic($ipaddress)
{
// validate input, drop arp entry // validate input, drop arp entry
if ( filter_var($ipaddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_IPV6) ){ if (filter_var($ipaddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
$this->shell->exec("/usr/sbin/arp -d ".trim($ipaddress) ); $this->shell->exec("/usr/sbin/arp -d " . trim($ipaddress));
} }
} }
/** /**
* Return arp table hashed by mac address * Return arp table hashed by mac address
*/ */
function getMACs(){ public function getMACs()
{
$result = array(); $result = array();
$shell_output = array(); $shell_output = array();
// execute arp shell command and collect (only valid) info into named array // execute arp shell command and collect (only valid) info into named array
if ($this->shell->exec("arp -an",false,false,$shell_output) == 0 ){ if ($this->shell->exec("arp -an", false, false, $shell_output) == 0) {
foreach($shell_output as $line){ foreach ($shell_output as $line) {
$line_parts = explode(" ",$line) ; $line_parts = explode(" ", $line);
if ( sizeof($line_parts) >= 4 ) { if (sizeof($line_parts) >= 4) {
$ipaddress = substr($line_parts[1],1,strlen($line_parts[1])-2 ) ; $ipaddress = substr($line_parts[1], 1, strlen($line_parts[1]) - 2);
// reformat mac addresses, sometimes arp return segments without trailing zero's // reformat mac addresses, sometimes arp return segments without trailing zero's
$mac_raw = strtolower($line_parts[3]); $mac_raw = strtolower($line_parts[3]);
$mac = ""; $mac = "";
foreach(explode(":",$mac_raw) as $segment ){ foreach (explode(":", $mac_raw) as $segment) {
if ( $mac != "") $mac .= ":"; if ($mac != "") {
if (strlen($segment) == 1) $mac .= "0".$segment; $mac .= ":";
else $mac .= $segment ;
} }
if (preg_match('/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/', trim($mac))){ if (strlen($segment) == 1) {
$result[$mac]= array('ip'=>$ipaddress); $mac .= "0" . $segment;
} else {
$mac .= $segment;
}
}
if (preg_match('/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/', trim($mac))) {
$result[$mac] = array('ip' => $ipaddress);
} }
} }
} }
} }
return $result; return $result;
} }
} }
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
namespace OPNsense\CaptivePortal; namespace OPNsense\CaptivePortal;
use \Phalcon\Logger\Adapter\Syslog;
use \Phalcon\DI\FactoryDefault;
use \OPNsense\Core; use \OPNsense\Core;
/** /**
...@@ -41,9 +43,8 @@ use \OPNsense\Core; ...@@ -41,9 +43,8 @@ use \OPNsense\Core;
* // TODO: CARP interfaces are probably not handled correctly * // TODO: CARP interfaces are probably not handled correctly
* @package CaptivePortal * @package CaptivePortal
*/ */
class CPClient { class CPClient
{
/** /**
* config handle * config handle
* @var Core_Config * @var Core_Config
...@@ -63,92 +64,53 @@ class CPClient { ...@@ -63,92 +64,53 @@ class CPClient {
private $shell = null; private $shell = null;
/** /**
* send message to syslog * Constructor
*
* @param $status
* @param $user
* @param $mac
* @param $ip
* @param string $message
*/ */
private function logportalauth($cpzonename, $user, $mac, $ip, $status, $message=""){ public function __construct()
{
$message = trim($message); // Request handle to configuration
$message = "Zone : {$cpzonename} {$status}: {$user}, {$mac}, {$ip}, {$message}"; $this->config = Core\Config::getInstance();
// generate new ruleset
$logger = new \Phalcon\Logger\Adapter\Syslog("logportalauth", array( $this->rules = new Rules();
'option' => LOG_PID, // keep a link to the shell object
'facility' => LOG_LOCAL4 $this->shell = new Core\Shell();
));
$logger->info($message);
} }
/** /**
* Request new pipeno * reset traffic counters
* @return int *
* @param null $rulenum
*/ */
private function new_ipfw_pipeno(){ public function zeroCounters($rulenum = null)
// TODO: implement global pipe number assigment {
return 999; if ($rulenum != null and is_numeric($rulenum)) {
$this->shell->exec("/sbin/ipfw zero " . $rulenum);
} elseif ($rulenum == null) {
$this->shell->exec("/sbin/ipfw zero ");
} }
/**
* reset bandwidth, if the current bandwidth is unchanged, do nothing
*
* @param int $pipeno system pipeno
* @param int $bw bandwidth in Kbit/s
*/
private function reset_bandwidth($pipeno,$bw){
//TODO : setup bandwidth for sessions ( check changed )
//#pipe 2000 config bw 2000Kbit/s
return;
} }
/** /**
* @param $cpzonename zone name * Reconfigure zones ( generate and load ruleset )
* @param $sessionid session id
*/ */
private function _disconnect($cpzonename,$sessionid){ public function reconfigure()
{
$zoneid = -1; if ($this->isEnabled()) {
foreach($this->config->object()->captiveportal->children() as $zone => $zoneobj){ $ruleset_filename = FactoryDefault::getDefault()->get('config')->globals->temp_path."/ipfw.rules";
if ($zone == $cpzonename) $zoneid = $zoneobj->zoneid; $this->rules->generate($ruleset_filename);
}
if ($zoneid == -1) return; // not a valid zone
$db = new DB($cpzonename); // load ruleset
$db_clients = $db->listClients(array("sessionid"=>$sessionid)); $this->shell->exec("/sbin/ipfw -f ".$ruleset_filename);
$ipfw_tables = $this->rules->getAuthUsersTables($zoneid); // update tables
if ( sizeof($db_clients) > 0 ){ $this->update();
if ($db_clients[0]->ip != null ) {
// only handle disconnect if we can find a client in our database
$exec_commands[] = "/sbin/ipfw table " . $ipfw_tables["in"] . " delete " . $db_clients[0]->ip;
$exec_commands[] = "/sbin/ipfw table " . $ipfw_tables["out"] . " delete " . $db_clients[0]->ip;
$this->shell->exec($exec_commands, false, false);
// TODO: cleanup dummynet pipes $db_clients[0]->pipeno_in/out
// TODO: log removal ( was : captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "DISCONNECT");)
}
$db->remove_session($sessionid);
}
}
/** // after reinit all accounting rules are vanished, reapply them for active sessions
* load accounting rules into ruleset, used for reinitialisation of the ruleset. $this->loadAccounting();
* triggers add_accounting() for all active clients in all zones } else {
*/ // captiveportal is disabled, flush all rules to be sure
private function loadAccounting() $this->shell->exec("/sbin/ipfw -f flush");
{
foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zone)
{
$db = new DB($cpzonename);
foreach ($db->listClients(array()) as $client)
{
$this->add_accounting($zone->zoneid, $client->ip) ;
}
unset($db);
} }
} }
...@@ -172,154 +134,31 @@ class CPClient { ...@@ -172,154 +134,31 @@ class CPClient {
} }
} }
/**
*
* @param $zoneid
* @param $ip
*/
public function add_accounting($zoneid,$ip){
// TODO: check processing speed, this might need some improvement
// check if our ip is already in the list and collect first free rule number to place it there if necessary
$shell_output=array();
$this->shell->exec("/sbin/ipfw show",false,false,$shell_output);
$prev_id = 0;
$new_id = null;
foreach($shell_output as $line){
// only trigger on counter rules and last item in the list
if ( strpos($line," count " ) !== false || strpos($line,"65535 " )!== false ) {
if ( strpos($line," ".$ip." " ) !== false ) {
// already in table... exit
return;
}
$this_line_id = (int) (explode(" ",$line)[0]) ;
if ( $this_line_id > 30000 and ($this_line_id -1) > $prev_id and $new_id == null) {
// new id found
if ( $this_line_id == 65535 ) $new_id = $prev_id+1;
else $new_id = $this_line_id-1;
}
$prev_id = $this_line_id;
}
}
if ( $new_id != null ) {
$exec_commands = array(
"/sbin/ipfw add " . $new_id . " set " . $zoneid . " count ip from " . $ip . " to any ",
"/sbin/ipfw add " . $new_id . " set " . $zoneid . " count ip from any to " . $ip,
);
// execute all ipfw actions
$this->shell->exec($exec_commands, false, false);
}
}
/**
* list (ipfw) accounting information
* @return array (key = hosts ip)
*/
public function list_accounting($ipaddr=null){
$filter_cmd = "";
$result = array();
$shell_output = array();
if ( $ipaddr != null ) $filter_cmd =" | /usr/bin/grep ' " . $ipaddr ." '" ;
if ( $this->shell->exec("/sbin/ipfw -aT list ".$filter_cmd,false,false,$shell_output) == 0 ){
foreach( $shell_output as $line) {
if (strpos($line, ' count ip from') !== false) {
$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],
"in_packets" => (int)$parts[2]
);
}
}
}
}
return $result;
}
/**
* 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
*/
function __construct() {
// Request handle to configuration
$this->config = Core\Config::getInstance();
// generate new ruleset
$this->rules = new Rules();
// keep a link to the shell object
$this->shell = new Core\Shell();
}
/**
* Reconfigure zones ( generate and load ruleset )
*/
public function reconfigure()
{
if ( $this->isEnabled() ) {
$ruleset_filename = \Phalcon\DI\FactoryDefault::getDefault()->get('config')->globals->temp_path."/ipfw.rules";
$this->rules->generate($ruleset_filename);
// load ruleset
$this->shell->exec("/sbin/ipfw -f ".$ruleset_filename);
// update tables
$this->update();
// after reinit all accounting rules are vanished, reapply them for active sessions
$this->loadAccounting();
} else {
// captiveportal is disabled, flush all rules to be sure
$this->shell->exec("/sbin/ipfw -f flush" );
}
}
/** /**
* update zone(s) with new configuration data * update zone(s) with new configuration data
* @param string $zone * @param string $zone
*/ */
public function update($zone=null){ public function update($zone = null)
$this->refresh_allowed_ips($zone); {
$this->refresh_allowed_mac($zone); $this->refreshAllowedIPs($zone);
$this->refreshAllowedMACs($zone);
} }
/** /**
* refresh allowed ip's for defined zone ( null for all zones ) * refresh allowed ip's for defined zone ( null for all zones )
* @param string $zone * @param string $cpzone
*/ */
public function refresh_allowed_ips($cpzone=null){ public function refreshAllowedIPs($cpzone = null)
{
$handled_addresses = array(); $handled_addresses = array();
foreach( $this->config->object()->captiveportal->children() as $cpzonename => $zone ) { foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zone) {
// search requested zone (id) // search requested zone (id)
if ( $cpzonename == $cpzone || $zone->zoneid == $cpzone || $cpzone == null ) { if ($cpzonename == $cpzone || $zone->zoneid == $cpzone || $cpzone == null) {
$db = new DB($cpzonename); $db = new DB($cpzonename);
$db_iplist = $db->listFixedIPs(); $db_iplist = $db->listFixedIPs();
// calculate table numbers for this zone // calculate table numbers for this zone
$ipfw_tables = $this->rules->getAuthIPTables($zone->zoneid ); $ipfw_tables = $this->rules->getAuthIPTables($zone->zoneid);
foreach ($zone->children() as $tagname => $tagcontent) { foreach ($zone->children() as $tagname => $tagcontent) {
$ip = $tagcontent->ip->__toString(); $ip = $tagcontent->ip->__toString();
...@@ -328,25 +167,27 @@ class CPClient { ...@@ -328,25 +167,27 @@ class CPClient {
$handled_addresses[$ip]["bw_up"] = $tagcontent->bw_up->__toString() ; $handled_addresses[$ip]["bw_up"] = $tagcontent->bw_up->__toString() ;
$handled_addresses[$ip]["bw_down"] = $tagcontent->bw_down->__toString() ; $handled_addresses[$ip]["bw_down"] = $tagcontent->bw_down->__toString() ;
if ( !array_key_exists($ip,$db_iplist) ){ if (!array_key_exists($ip, $db_iplist)) {
// only insert new values // only insert new values
$pipeno_in = $this->new_ipfw_pipeno() ; $pipeno_in = $this->newIPFWpipeno() ;
$pipeno_out = $this->new_ipfw_pipeno() ; $pipeno_out = $this->newIPFWpipeno() ;
$exec_commands = array( $exec_commands = array(
# insert new ip address # insert new ip address
"/sbin/ipfw table ". $ipfw_tables["in"] ." add " . $ip . "/" . $tagcontent->sn->__toString() . " " . $pipeno_in, "/sbin/ipfw table ". $ipfw_tables["in"] ." add " .
"/sbin/ipfw table ". $ipfw_tables["out"] ." add " . $ip . "/" . $tagcontent->sn->__toString() . " " . $pipeno_out, $ip . "/" . $tagcontent->sn->__toString() . " " . $pipeno_in,
"/sbin/ipfw table ". $ipfw_tables["out"] ." add " .
$ip . "/" . $tagcontent->sn->__toString() . " " . $pipeno_out,
); );
// execute all ipfw actions // execute all ipfw actions
$this->shell->exec($exec_commands, false,false); $this->shell->exec($exec_commands, false, false);
// update administration // update administration
$db->upsertFixedIP($ip,$pipeno_in,$pipeno_out); $db->upsertFixedIP($ip, $pipeno_in, $pipeno_out);
// save bandwidth data // save bandwidth data
$handled_addresses[$ip]["pipeno_in"] = $pipeno_in ; $handled_addresses[$ip]["pipeno_in"] = $pipeno_in ;
$handled_addresses[$ip]["pipeno_out"] = $pipeno_out ; $handled_addresses[$ip]["pipeno_out"] = $pipeno_out ;
}else{ } else {
// //
$handled_addresses[$ip]["pipeno_in"] = $db_iplist[$ip]->pipeno_in ; $handled_addresses[$ip]["pipeno_in"] = $db_iplist[$ip]->pipeno_in ;
$handled_addresses[$ip]["pipeno_out"] = $db_iplist[$ip]->pipeno_out ; $handled_addresses[$ip]["pipeno_out"] = $db_iplist[$ip]->pipeno_out ;
...@@ -357,26 +198,28 @@ class CPClient { ...@@ -357,26 +198,28 @@ class CPClient {
// Cleanup deleted addresses // Cleanup deleted addresses
foreach($db_iplist as $ip => $record){ foreach ($db_iplist as $ip => $record) {
if (!array_key_exists($ip,$handled_addresses)){ if (!array_key_exists($ip, $handled_addresses)) {
$exec_commands = array( $exec_commands = array(
# insert new ip address # insert new ip address
"/sbin/ipfw table ". $ipfw_tables["in"] ." del " . $ip . "/" . $tagcontent->sn->__toString() , "/sbin/ipfw table ". $ipfw_tables["in"] .
"/sbin/ipfw table ". $ipfw_tables["out"] ." del " . $ip . "/" . $tagcontent->sn->__toString() , " del " . $ip . "/" . $tagcontent->sn->__toString() ,
"/sbin/ipfw table ". $ipfw_tables["out"] .
" del " . $ip . "/" . $tagcontent->sn->__toString() ,
); );
// execute all ipfw actions // execute all ipfw actions
$this->shell->exec($exec_commands, false,false); $this->shell->exec($exec_commands, false, false);
// TODO : cleanup $record->pipeno_in, $record->pipeno_out ; // TODO : cleanup $record->pipeno_in, $record->pipeno_out ;
$db->dropFixedIP($ip); $db->dropFixedIP($ip);
} }
} }
// reset bandwidth, // reset bandwidth,
foreach($handled_addresses as $mac => $record){ foreach ($handled_addresses as $mac => $record) {
if (array_key_exists("pipeno_in",$record) ){ if (array_key_exists("pipeno_in", $record)) {
$this->reset_bandwidth($record["pipeno_in"],$record["bw_down"]); $this->resetBandwidth($record["pipeno_in"], $record["bw_down"]);
$this->reset_bandwidth($record["pipeno_out"],$record["bw_up"]); $this->resetBandwidth($record["pipeno_out"], $record["bw_up"]);
} }
} }
...@@ -386,13 +229,37 @@ class CPClient { ...@@ -386,13 +229,37 @@ class CPClient {
} }
/**
* Request new pipeno
* @return int
*/
private function newIPFWpipeno()
{
// TODO: implement global pipe number assigment
return 999;
}
/**
* reset bandwidth, if the current bandwidth is unchanged, do nothing
* @param int $pipeno system pipeno
* @param int $bw bandwidth in Kbit/s
* @return status
*/
private function resetBandwidth($pipeno, $bw)
{
//TODO : setup bandwidth for sessions ( check changed )
//#pipe 2000 config bw 2000Kbit/s
return false;
}
/** /**
* To be able to grant access to physical pc's, we need to do some administration. * To be able to grant access to physical pc's, we need to do some administration.
* Our captive portal database keeps a list of every used address and last know mac address * Our captive portal database keeps a list of every used address and last know mac address
* *
* @param String $zone zone name or number * @param string $cpzone zone name or number
*/ */
public function refresh_allowed_mac($cpzone=null){ public function refreshAllowedMACs($cpzone = null)
{
// read ARP table // read ARP table
$arp= new ARP(); $arp= new ARP();
...@@ -400,8 +267,8 @@ class CPClient { ...@@ -400,8 +267,8 @@ class CPClient {
// keep a list of handled addresses, so we can cleanup the rest and keep track of needed bandwidth restrictions // keep a list of handled addresses, so we can cleanup the rest and keep track of needed bandwidth restrictions
$handled_mac_addresses = array(); $handled_mac_addresses = array();
foreach( $this->config->object()->captiveportal->children() as $cpzonename => $zone ) { foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zone) {
if ( $cpzonename == $cpzone || $zone->zoneid == $cpzone || $cpzone == null ) { if ($cpzonename == $cpzone || $zone->zoneid == $cpzone || $cpzone == null) {
// open administrative database for this zone // open administrative database for this zone
$db = new DB($cpzonename); $db = new DB($cpzonename);
$db_maclist = $db->listPassthruMacs(); $db_maclist = $db->listPassthruMacs();
...@@ -420,44 +287,59 @@ class CPClient { ...@@ -420,44 +287,59 @@ class CPClient {
// only handle addresses we know of // only handle addresses we know of
if (array_key_exists($mac, $arp_maclist)) { if (array_key_exists($mac, $arp_maclist)) {
// if the address is already in our database, check if it has changed // if the address is already in our database, check if it has changed
if ( array_key_exists($mac,$db_maclist) ) { if (array_key_exists($mac, $db_maclist)) {
// save pipe numbers for bandwidth restriction // save pipe numbers for bandwidth restriction
$handled_mac_addresses[$mac]["pipeno_in"] = $db_maclist[$mac]->pipeno_in ; $handled_mac_addresses[$mac]["pipeno_in"] = $db_maclist[$mac]->pipeno_in ;
$handled_mac_addresses[$mac]["pipeno_out"] = $db_maclist[$mac]->pipeno_out ; $handled_mac_addresses[$mac]["pipeno_out"] = $db_maclist[$mac]->pipeno_out ;
if ($db_maclist[$mac]->ip != $arp_maclist[$mac]['ip'] ) { if ($db_maclist[$mac]->ip != $arp_maclist[$mac]['ip']) {
// handle changed ip, // handle changed ip,
$handled_mac_addresses[$mac]["action"] = "changed ip"; $handled_mac_addresses[$mac]["action"] = "changed ip";
$exec_commands = array( $exec_commands = array(
# delete old ip address # delete old ip address
"/sbin/ipfw table ". $ipfw_tables["in"] ." delete ". $db_maclist[$mac]->ip, "/sbin/ipfw table ". $ipfw_tables["in"] .
"/sbin/ipfw table ". $ipfw_tables["out"] ." delete ". $db_maclist[$mac]->ip, " delete ". $db_maclist[$mac]->ip,
"/sbin/ipfw table ". $ipfw_tables["out"] .
" delete ". $db_maclist[$mac]->ip,
# insert new ip address # insert new ip address
"/sbin/ipfw table ". $ipfw_tables["in"] ." add " . $arp_maclist[$mac]['ip']. " " . $db_maclist[$mac]->pipeno_in, "/sbin/ipfw table ". $ipfw_tables["in"] .
"/sbin/ipfw table ". $ipfw_tables["out"] ." add " . $arp_maclist[$mac]['ip']. " " . $db_maclist[$mac]->pipeno_out, " add " . $arp_maclist[$mac]['ip']. " " . $db_maclist[$mac]->pipeno_in,
"/sbin/ipfw table ". $ipfw_tables["out"] .
" add " . $arp_maclist[$mac]['ip']. " " . $db_maclist[$mac]->pipeno_out,
); );
// execute all ipfw actions // execute all ipfw actions
$this->shell->exec($exec_commands, false,false); $this->shell->exec($exec_commands, false, false);
// update administration // update administration
$db->upsertPassthruMAC($tagcontent->mac,$arp_maclist[$mac]['ip'],$db_maclist[$mac]->pipeno_in,$db_maclist[$mac]->pipeno_out); // new ip according to arp table $db->upsertPassthruMAC(
$tagcontent->mac,
$arp_maclist[$mac]['ip'],
$db_maclist[$mac]->pipeno_in,
$db_maclist[$mac]->pipeno_out
); // new ip according to arp table
} }
} } else {
else {
// new host, not seen it yet // new host, not seen it yet
$handled_mac_addresses[$mac]["action"] = "new"; $handled_mac_addresses[$mac]["action"] = "new";
$pipeno_in = $this->new_ipfw_pipeno() ; $pipeno_in = $this->newIPFWpipeno() ;
$pipeno_out = $this->new_ipfw_pipeno() ; $pipeno_out = $this->newIPFWpipeno() ;
// execute all ipfw actions // execute all ipfw actions
$exec_commands = array( $exec_commands = array(
# insert new ip address # insert new ip address
"/sbin/ipfw table ". $ipfw_tables["in"] ." add " . $arp_maclist[$mac]['ip']. " " . $pipeno_in, "/sbin/ipfw table ". $ipfw_tables["in"] .
"/sbin/ipfw table ". $ipfw_tables["out"] ." add " . $arp_maclist[$mac]['ip']. " " . $pipeno_out, " add " . $arp_maclist[$mac]['ip']. " " . $pipeno_in,
"/sbin/ipfw table ". $ipfw_tables["out"] .
" add " . $arp_maclist[$mac]['ip']. " " . $pipeno_out,
); );
$this->shell->exec($exec_commands, false,false); $this->shell->exec($exec_commands, false, false);
$db->upsertPassthruMAC($tagcontent->mac,$arp_maclist[$mac]['ip'],$pipeno_in,$pipeno_out); $db->upsertPassthruMAC(
$tagcontent->mac,
$arp_maclist[$mac]['ip'],
$pipeno_in,
$pipeno_out
);
// save pipe numbers for bandwidth restriction // save pipe numbers for bandwidth restriction
$handled_mac_addresses[$mac]["pipeno_in"] = $pipeno_in ; $handled_mac_addresses[$mac]["pipeno_in"] = $pipeno_in ;
$handled_mac_addresses[$mac]["pipeno_out"] = $pipeno_out ; $handled_mac_addresses[$mac]["pipeno_out"] = $pipeno_out ;
...@@ -471,24 +353,26 @@ class CPClient { ...@@ -471,24 +353,26 @@ class CPClient {
// //
// cleanup old addresses // cleanup old addresses
// //
foreach($db_maclist as $mac => $record){ foreach ($db_maclist as $mac => $record) {
if ( !array_key_exists($mac,$handled_mac_addresses) ){ if (!array_key_exists($mac, $handled_mac_addresses)) {
# delete old ip address, execute all actions # delete old ip address, execute all actions
$exec_commands = array( $exec_commands = array(
"/sbin/ipfw table ". $ipfw_tables["in"] ." delete ". $db_maclist[$mac]->ip, "/sbin/ipfw table ". $ipfw_tables["in"] .
"/sbin/ipfw table ". $ipfw_tables["out"] ." delete ". $db_maclist[$mac]->ip, " delete ". $db_maclist[$mac]->ip,
"/sbin/ipfw table ". $ipfw_tables["out"] .
" delete ". $db_maclist[$mac]->ip,
); );
$this->shell->exec($exec_commands, false,false); $this->shell->exec($exec_commands, false, false);
// TODO : cleanup $record->pipeno_in, $record->pipeno_out ; // TODO : cleanup $record->pipeno_in, $record->pipeno_out ;
$db->dropPassthruMAC($mac); $db->dropPassthruMAC($mac);
} }
} }
// reset bandwidth // reset bandwidth
foreach($handled_mac_addresses as $mac => $record){ foreach ($handled_mac_addresses as $mac => $record) {
if (array_key_exists("pipeno_in",$record) ){ if (array_key_exists("pipeno_in", $record)) {
$this->reset_bandwidth($record["pipeno_in"],$record["bw_down"]); $this->resetBandwidth($record["pipeno_in"], $record["bw_down"]);
$this->reset_bandwidth($record["pipeno_out"],$record["bw_up"]); $this->resetBandwidth($record["pipeno_out"], $record["bw_up"]);
} }
} }
...@@ -499,18 +383,97 @@ class CPClient { ...@@ -499,18 +383,97 @@ class CPClient {
} }
/**
* load accounting rules into ruleset, used for reinitialisation of the ruleset.
* triggers addAccounting() for all active clients in all zones
*/
private function loadAccounting()
{
foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zone) {
$db = new DB($cpzonename);
foreach ($db->listClients(array()) as $client) {
$this->addAccounting($zone->zoneid, $client->ip) ;
}
unset($db);
}
}
/**
* add accounting rules for ip
* @param int $zoneid zone
* @param string $ip ip address
*/
public function addAccounting($zoneid, $ip)
{
// TODO: check processing speed, this might need some improvement
// check if our ip is already in the list and collect first free rule number to place it there if necessary
$shell_output=array();
$this->shell->exec("/sbin/ipfw show", false, false, $shell_output);
$prev_id = 0;
$new_id = null;
foreach ($shell_output as $line) {
// only trigger on counter rules and last item in the list
if (strpos($line, " count ") !== false || strpos($line, "65535 ") !== false) {
if (strpos($line, " ".$ip." ") !== false) {
// already in table... exit
return;
}
$this_line_id = (int)(explode(" ", $line)[0]) ;
if ($this_line_id > 30000 and ($this_line_id -1) > $prev_id and $new_id == null) {
// new id found
if ($this_line_id == 65535) {
$new_id = $prev_id+1;
} else {
$new_id = $this_line_id-1;
}
}
$prev_id = $this_line_id;
}
}
if ($new_id != null) {
$exec_commands = array(
"/sbin/ipfw add " . $new_id . " set " . $zoneid . " count ip from " . $ip . " to any ",
"/sbin/ipfw add " . $new_id . " set " . $zoneid . " count ip from any to " . $ip,
);
// execute all ipfw actions
$this->shell->exec($exec_commands, false, false);
}
}
/** /**
* unlock host for captiveportal use * unlock host for captiveportal use
*
* @param string $cpzonename * @param string $cpzonename
* @param string $clientip * @param string $clientip
* @param string $clientmac * @param string $clientmac
* @param string $username * @param string $username
* @param string $password * @param string $password
* @param string $attributes * @param string $bw_up
* @param string $bw_down
* @param string $radiusctx * @param string $radiusctx
* @param int $session_timeout
* @param int $idle_timeout
* @param int $session_terminate_time
* @param int $interim_interval
* @return bool|string
*/ */
public function portal_allow($cpzonename,$clientip,$clientmac,$username,$password = null,$bw_up=null,$bw_down=null, $radiusctx = null,$session_timeout=null,$idle_timeout=null,$session_terminate_time=null,$interim_interval=null){ public function portalAllow(
$cpzonename,
$clientip,
$clientmac,
$username,
$password = null,
$bw_up = null,
$bw_down = null,
$radiusctx = null,
$session_timeout = null,
$idle_timeout = null,
$session_terminate_time = null,
$interim_interval = null
) {
// defines // defines
$exec_commands = array() ; $exec_commands = array() ;
$db = new DB($cpzonename); $db = new DB($cpzonename);
...@@ -518,27 +481,35 @@ class CPClient { ...@@ -518,27 +481,35 @@ class CPClient {
// find zoneid for this named zone // find zoneid for this named zone
$zoneid = -1; $zoneid = -1;
foreach($this->config->object()->captiveportal->children() as $zone => $zoneobj){ foreach ($this->config->object()->captiveportal->children() as $zone => $zoneobj) {
if ($zone == $cpzonename) $zoneid = $zoneobj->zoneid; if ($zone == $cpzonename) {
$zoneid = $zoneobj->zoneid;
}
} }
if ($zoneid == -1) return; // not a valid zone, bailout if ($zoneid == -1) {
return false; // not a valid zone, bailout
}
// grap needed data to generate our rules // grap needed data to generate our rules
$ipfw_tables = $this->rules->getAuthUsersTables($zoneid); $ipfw_tables = $this->rules->getAuthUsersTables($zoneid);
$cp_table = $db->listClients(array("mac"=>$clientmac,"ip"=>$clientip),"or"); $cp_table = $db->listClients(array("mac"=>$clientmac, "ip"=>$clientip), "or");
if ( sizeof($cp_table) > 0 && ($cp_table[0]->ip == $clientip && $cp_table[0]->mac == $clientmac ) ){ if (sizeof($cp_table) > 0 && ($cp_table[0]->ip == $clientip && $cp_table[0]->mac == $clientmac)) {
// nothing (important) changed here... move on // nothing (important) changed here... move on
return $cp_table[0]->sessionid; return $cp_table[0]->sessionid;
} elseif ( sizeof($cp_table) > 0) { } elseif (sizeof($cp_table) > 0) {
// something changed... // something changed...
// prevent additional sessions to popup, one MAC should have only one active session, remove the rest (if any) // prevent additional sessions to popup,
// one MAC should have only one active session, remove the rest (if any)
$cnt = 0; $cnt = 0;
$remove_sessions = array(); $remove_sessions = array();
foreach($cp_table as $record){ foreach ($cp_table as $record) {
if ( $cnt >0) $remove_sessions[] = $record->sessionid; if ($cnt >0) {
else $current_session = $record; $remove_sessions[] = $record->sessionid;
} else {
$current_session = $record;
}
$cnt++; $cnt++;
// prepare removal for all ip addresses belonging to this host // prepare removal for all ip addresses belonging to this host
$exec_commands[] = "/sbin/ipfw table ". $ipfw_tables["in"] ." delete ". $record->ip; $exec_commands[] = "/sbin/ipfw table ". $ipfw_tables["in"] ." delete ". $record->ip;
...@@ -546,26 +517,25 @@ class CPClient { ...@@ -546,26 +517,25 @@ class CPClient {
// TODO: if for some strange reason there is more than one session, we are failing to drop the pipes // TODO: if for some strange reason there is more than one session, we are failing to drop the pipes
$exec_commands[] = "/usr/sbin/arp -d ".trim($record->ip); // drop static arp entry (prevent MAC change) $exec_commands[] = "/usr/sbin/arp -d ".trim($record->ip); // drop static arp entry (prevent MAC change)
} }
if (sizeof($remove_sessions)){ if (sizeof($remove_sessions)) {
$db->remove_session($remove_sessions); $db->removeSession($remove_sessions);
} }
// collect pipe numbers for dummynet // collect pipe numbers for dummynet
$pipeno_in = $current_session->pipeno_in; $pipeno_in = $current_session->pipeno_in;
$pipeno_out = $current_session->pipeno_out; $pipeno_out = $current_session->pipeno_out;
$db->update_session($current_session->sessionid,array("ip"=>$clientip,"mac"=>$clientmac)); $db->updateSession($current_session->sessionid, array("ip"=>$clientip, "mac"=>$clientmac));
// preserve session for response // preserve session for response
$sessionid = $current_session->sessionid; $sessionid = $current_session->sessionid;
} else } else {
{
// new session, allocate new dummynet pipes and generate a unique id // new session, allocate new dummynet pipes and generate a unique id
$pipeno_in = $this->new_ipfw_pipeno(); $pipeno_in = $this->newIPFWpipeno();
$pipeno_out = $this->new_ipfw_pipeno(); $pipeno_out = $this->newIPFWpipeno();
// construct session data // construct session data
$session_data=Array(); $session_data=array();
$session_data["ip"]=$clientip; $session_data["ip"]=$clientip;
$session_data["mac"]=$clientmac; $session_data["mac"]=$clientmac;
$session_data["pipeno_in"] = $pipeno_in; $session_data["pipeno_in"] = $pipeno_in;
...@@ -580,27 +550,27 @@ class CPClient { ...@@ -580,27 +550,27 @@ class CPClient {
$session_data["allow_time"] = time(); // allow time is actual starting time of this session $session_data["allow_time"] = time(); // allow time is actual starting time of this session
$sessionid = uniqid() ; $sessionid = uniqid() ;
$db->insert_session($sessionid, $session_data ); $db->insertSession($sessionid, $session_data);
} }
// add commands for access tables, and execute all collected // add commands for access tables, and execute all collected
$exec_commands[] = "/sbin/ipfw table ". $ipfw_tables["in"] ." add ". $clientip . " ".$pipeno_in; $exec_commands[] = "/sbin/ipfw table ". $ipfw_tables["in"] ." add ". $clientip . " ".$pipeno_in;
$exec_commands[] = "/sbin/ipfw table ". $ipfw_tables["out"] ." add ". $clientip . " ".$pipeno_out; $exec_commands[] = "/sbin/ipfw table ". $ipfw_tables["out"] ." add ". $clientip . " ".$pipeno_out;
$this->shell->exec($exec_commands, false,false); $this->shell->exec($exec_commands, false, false);
// lock the user/ip to it's MAC address using arp // lock the user/ip to it's MAC address using arp
$arp->setStatic($clientip,$clientmac); $arp->setStatic($clientip, $clientmac);
// add accounting rule // add accounting rule
$this->add_accounting($zoneid,$clientip); $this->addAccounting($zoneid, $clientip);
// set bandwidth restrictions // set bandwidth restrictions
$this->reset_bandwidth($pipeno_in,$bw_up); $this->resetBandwidth($pipeno_in, $bw_up);
$this->reset_bandwidth($pipeno_in,$bw_down); $this->resetBandwidth($pipeno_in, $bw_down);
// log // log
$this->logportalauth($cpzonename, $username, $clientmac, $clientip, $status="LOGIN"); $this->logportalauth($cpzonename, $username, $clientmac, $clientip, $status = "LOGIN");
// cleanup // cleanup
unset($db); unset($db);
...@@ -609,42 +579,49 @@ class CPClient { ...@@ -609,42 +579,49 @@ class CPClient {
} }
/** /**
* disconnect a session or a list of sessions depending on the parameter * send message to syslog
* @param string $cpzonename zone name or id * @param string $cpzonename
* @param $sessionid * @param string $user
* @param string $mac
* @param string $ip
* @param string $status
* @param string $message
*/ */
public function disconnect($cpzonename,$sessionid){ private function logportalauth($cpzonename, $user, $mac, $ip, $status, $message = "")
if ( is_array($sessionid)){ {
foreach($sessionid as $sessid ){ $message = trim($message);
$this->_disconnect($cpzonename,$sessid); $message = "Zone : {$cpzonename} {$status}: {$user}, {$mac}, {$ip}, {$message}";
}
} $logger = new Syslog("logportalauth", array(
else{ 'option' => LOG_PID,
$this->_disconnect($cpzonename,$sessionid); 'facility' => LOG_LOCAL4
} ));
$logger->info($message);
} }
/** /**
* flush zone (null flushes all zones) * flush zone (null flushes all zones)
* @param null $zone * @param string $zone zone name or id
*/ */
function flush($zone=null){ public function flush($zone = null)
if ( $zone == null ) { {
if ($zone == null) {
$shell = new Core\Shell(); $shell = new Core\Shell();
$shell->exec("/sbin/ipfw -f table all flush"); $shell->exec("/sbin/ipfw -f table all flush");
} } else {
else{
// find zoneid for this named zone // find zoneid for this named zone
if (preg_match("/^[0-9]{1,2}$/", trim($zone)) ) { if (preg_match("/^[0-9]{1,2}$/", trim($zone))) {
$zoneid = $zone; $zoneid = $zone;
}else { } else {
$zoneid = -1; $zoneid = -1;
foreach ($this->config->object()->captiveportal->children() as $zonenm => $zoneobj) { foreach ($this->config->object()->captiveportal->children() as $zonenm => $zoneobj) {
if ($zonenm == $zone) $zoneid = $zoneobj->zoneid; if ($zonenm == $zone) {
$zoneid = $zoneobj->zoneid;
}
} }
} }
if ( $zoneid != -1 ){ if ($zoneid != -1) {
$exec_commands= array( $exec_commands= array(
"/sbin/ipfw -f table ".$this->rules->getAuthUsersTables($zoneid)["in"]." flush", "/sbin/ipfw -f table ".$this->rules->getAuthUsersTables($zoneid)["in"]." flush",
"/sbin/ipfw -f table ".$this->rules->getAuthUsersTables($zoneid)["out"]." flush", "/sbin/ipfw -f table ".$this->rules->getAuthUsersTables($zoneid)["out"]." flush",
...@@ -654,18 +631,20 @@ class CPClient { ...@@ -654,18 +631,20 @@ class CPClient {
"/sbin/ipfw -f table ".$this->rules->getAuthMACTables($zoneid)["out"]." flush", "/sbin/ipfw -f table ".$this->rules->getAuthMACTables($zoneid)["out"]." flush",
"/sbin/ipfw delete set ".$zoneid, "/sbin/ipfw delete set ".$zoneid,
); );
$this->shell->exec($exec_commands, false,false); $this->shell->exec($exec_commands, false, false);
} }
} }
} }
/** /**
* cleanup portal sessions * cleanup portal sessions
* @param $cpzone zone name
*/ */
function portal_cleanup_sessions($cpzone=null){ public function portalCleanupSessions($cpzone = null)
$acc_list = $this->list_accounting(); {
foreach($this->config->object()->captiveportal->children() as $cpzonename => $zoneobj){ $acc_list = $this->listAccounting();
if ( $cpzone == null || $cpzone == $cpzonename ) { foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zoneobj) {
if ($cpzone == null || $cpzone == $cpzonename) {
$db = new DB($cpzonename); $db = new DB($cpzonename);
$clients = $db->listClients(array(), null, null); $clients = $db->listClients(array(), null, null);
...@@ -677,10 +656,16 @@ class CPClient { ...@@ -677,10 +656,16 @@ class CPClient {
} }
// if session timeout is reached, disconnect // if session timeout is reached, disconnect
if (is_numeric($client->session_timeout) && $client->session_timeout > 0 ) { if (is_numeric($client->session_timeout) && $client->session_timeout > 0) {
if (((time() - $client->allow_time) ) > $client->session_timeout) { if (((time() - $client->allow_time) ) > $client->session_timeout) {
$this->disconnect($cpzonename, $client->sessionid); $this->disconnect($cpzonename, $client->sessionid);
$this->logportalauth($cpzonename, $client->username, $client->mac, $client->ip, $status="SESSION TIMEOUT"); $this->logportalauth(
$cpzonename,
$client->username,
$client->mac,
$client->ip,
$status = "SESSION TIMEOUT"
);
continue; continue;
} }
} }
...@@ -689,15 +674,29 @@ class CPClient { ...@@ -689,15 +674,29 @@ class CPClient {
if (is_numeric($client->idle_timeout) && $client->idle_timeout > 0 && $idle_time > 0) { if (is_numeric($client->idle_timeout) && $client->idle_timeout > 0 && $idle_time > 0) {
if ($idle_time > $client->idle_timeout) { if ($idle_time > $client->idle_timeout) {
$this->disconnect($cpzonename, $client->sessionid); $this->disconnect($cpzonename, $client->sessionid);
$this->logportalauth($cpzonename, $client->username, $client->mac, $client->ip, $status="IDLE TIMEOUT"); $this->logportalauth(
$cpzonename,
$client->username,
$client->mac,
$client->ip,
$status = "IDLE TIMEOUT"
);
continue; continue;
} }
} }
// disconnect on session terminate time // disconnect on session terminate time
if ( is_numeric($client->session_terminate_time) && $client->session_terminate_time > 0 && $client->session_terminate_time < time()) { if (is_numeric($client->session_terminate_time) &&
$client->session_terminate_time > 0 &&
$client->session_terminate_time < time()) {
$this->disconnect($cpzonename, $client->sessionid); $this->disconnect($cpzonename, $client->sessionid);
$this->logportalauth($cpzonename, $client->username, $client->mac, $client->ip, $status="TERMINATE TIME REACHED"); $this->logportalauth(
$cpzonename,
$client->username,
$client->mac,
$client->ip,
$status = "TERMINATE TIME REACHED"
);
continue; continue;
} }
} }
...@@ -710,5 +709,92 @@ class CPClient { ...@@ -710,5 +709,92 @@ class CPClient {
} }
/**
* list (ipfw) accounting information
* @param string $ipaddr ip address
* @return array (key = hosts ip)
*/
public function listAccounting($ipaddr = null)
{
$filter_cmd = "";
$result = array();
$shell_output = array();
if ($ipaddr != null) {
$filter_cmd =" | /usr/bin/grep ' " . $ipaddr ." '" ;
}
if ($this->shell->exec("/sbin/ipfw -aT list ".$filter_cmd, false, false, $shell_output) == 0) {
foreach ($shell_output as $line) {
if (strpos($line, ' count ip from') !== false) {
$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],
"in_packets" => (int)$parts[2]
);
}
}
}
}
return $result;
}
/**
* disconnect a session or a list of sessions depending on the parameter
* @param string $cpzonename zone name or id
* @param string $sessionid
*/
public function disconnect($cpzonename, $sessionid)
{
if (is_array($sessionid)) {
foreach ($sessionid as $sessid) {
$this->disconnectSession($cpzonename, $sessid);
}
} else {
$this->disconnectSession($cpzonename, $sessionid);
}
}
/**
* @param string $cpzonename zone name
* @param string $sessionid session id
* @return boolean false for invalid request
*/
private function disconnectSession($cpzonename, $sessionid)
{
$zoneid = -1;
foreach ($this->config->object()->captiveportal->children() as $zone => $zoneobj) {
if ($zone == $cpzonename) {
$zoneid = $zoneobj->zoneid;
}
}
if ($zoneid == -1) {
// not a valid zone
return false;
}
$db = new DB($cpzonename);
$db_clients = $db->listClients(array("sessionid"=>$sessionid));
$ipfw_tables = $this->rules->getAuthUsersTables($zoneid);
if (sizeof($db_clients) > 0) {
if ($db_clients[0]->ip != null) {
// only handle disconnect if we can find a client in our database
$exec_commands[] = "/sbin/ipfw table " . $ipfw_tables["in"] . " delete " . $db_clients[0]->ip;
$exec_commands[] = "/sbin/ipfw table " . $ipfw_tables["out"] . " delete " . $db_clients[0]->ip;
$this->shell->exec($exec_commands, false, false);
// TODO: cleanup dummynet pipes $db_clients[0]->pipeno_in/out
// TODO: log removal
// ( was : captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "DISCONNECT");)
}
$db->removeSession($sessionid);
}
return true;
}
} }
...@@ -33,23 +33,28 @@ ...@@ -33,23 +33,28 @@
namespace OPNsense\CaptivePortal; namespace OPNsense\CaptivePortal;
use \Phalcon\DI\FactoryDefault;
use \Phalcon\Db\Adapter\Pdo\Sqlite;
use \Phalcon\Logger\Adapter\Syslog;
/** /**
* Class DB, handles captive portal zone's adminstration * Class DB, handles captive portal zone's adminstration
* @package CaptivePortal * @package CaptivePortal
*/ */
class DB { class DB
{
/** /**
* zone name * zone name
* @var string * @var string
*/ */
private $zone = null ; private $zone = null;
/** /**
* database handle * database handle
* @var SQLite3 * @var SQLite3
*/ */
private $handle = null ; private $handle = null;
/** /**
* datatypes for captive portal table * datatypes for captive portal table
...@@ -68,44 +73,48 @@ class DB { ...@@ -68,44 +73,48 @@ class DB {
"idle_timeout" => \PDO::PARAM_INT, "idle_timeout" => \PDO::PARAM_INT,
"session_terminate_time" => \PDO::PARAM_INT, "session_terminate_time" => \PDO::PARAM_INT,
"interim_interval" => \PDO::PARAM_INT, "interim_interval" => \PDO::PARAM_INT,
"radiusctx" => \PDO::PARAM_STR); "radiusctx" => \PDO::PARAM_STR
);
/** /**
* datatypes for captive portal mac table * datatypes for captive portal mac table
* @var array * @var array
*/ */
private $captiveportal_mac_types=array( private $captiveportal_mac_types = array(
"mac" => \PDO::PARAM_STR, "mac" => \PDO::PARAM_STR,
"ip" => \PDO::PARAM_STR, "ip" => \PDO::PARAM_STR,
"pipeno_in" => \PDO::PARAM_INT, "pipeno_in" => \PDO::PARAM_INT,
"pipeno_out" => \PDO::PARAM_INT, "pipeno_out" => \PDO::PARAM_INT,
"last_checked" => \PDO::PARAM_INT); "last_checked" => \PDO::PARAM_INT
);
/** /**
* datatypes for captive portal ip table * datatypes for captive portal ip table
* @var array * @var array
*/ */
private $captiveportal_ip_types=array( private $captiveportal_ip_types = array(
"ip" => \PDO::PARAM_STR, "ip" => \PDO::PARAM_STR,
"pipeno_in" => \PDO::PARAM_INT, "pipeno_in" => \PDO::PARAM_INT,
"pipeno_out" => \PDO::PARAM_INT, "pipeno_out" => \PDO::PARAM_INT,
"last_checked" => \PDO::PARAM_INT); "last_checked" => \PDO::PARAM_INT
);
/** /**
* open / create new captive portal database for zone * open / create new captive portal database for zone
* @param $zone zone name * @param $zone zone name
*/ */
function __construct($zone) public function __construct($zone)
{ {
$this->zone = $zone ; $this->zone = $zone;
$this->open(); $this->open();
} }
/** /**
* destruct, close sessions * destruct, close sessions
*/ */
function __destruct() { public function __destruct()
if ( $this->handle != null){ {
if ($this->handle != null) {
$this->handle->close(); $this->handle->close();
} }
} }
...@@ -115,46 +124,49 @@ class DB { ...@@ -115,46 +124,49 @@ class DB {
* creates structure needed for this captiveportal zone * creates structure needed for this captiveportal zone
* @return SQLite3 * @return SQLite3
*/ */
function open(){ public function open()
{
// open database // open database
$db_path = \Phalcon\DI\FactoryDefault::getDefault()->get('config')->globals->vardb_path ."/captiveportal".$this->zone.".db" ; $db_path = FactoryDefault::getDefault()->get('config')->globals->vardb_path .
"/captiveportal" . $this->zone . ".db";
try { try {
$this->handle = new \Phalcon\Db\Adapter\Pdo\Sqlite(array("dbname" => $db_path)); $this->handle = new Sqlite(array("dbname" => $db_path));
// create structure on new database // create structure on new database
if (!$this->handle->execute("CREATE TABLE IF NOT EXISTS captiveportal (" . # table used for authenticated users $sql = "CREATE TABLE IF NOT EXISTS captiveportal (" .# table used for authenticated users
"allow_time INTEGER, pipeno_in INTEGER, pipeno_out INTEGER, ip TEXT, mac TEXT, username TEXT, " . "allow_time INTEGER, pipeno_in INTEGER, pipeno_out INTEGER, ip TEXT, mac TEXT, username TEXT, " .
"sessionid TEXT, bpassword TEXT, session_timeout INTEGER, idle_timeout INTEGER, " . "sessionid TEXT, bpassword TEXT, session_timeout INTEGER, idle_timeout INTEGER, " .
"session_terminate_time INTEGER, interim_interval INTEGER, radiusctx TEXT); " . "session_terminate_time INTEGER, interim_interval INTEGER, radiusctx TEXT); " .
"CREATE UNIQUE INDEX IF NOT EXISTS idx_active ON captiveportal (sessionid, username); " . "CREATE UNIQUE INDEX IF NOT EXISTS idx_active ON captiveportal (sessionid, username); " .
"CREATE INDEX IF NOT EXISTS user ON captiveportal (username); " . "CREATE INDEX IF NOT EXISTS user ON captiveportal (username); " .
"CREATE INDEX IF NOT EXISTS ip ON captiveportal (ip); " . "CREATE INDEX IF NOT EXISTS ip ON captiveportal (ip); " .
"CREATE INDEX IF NOT EXISTS starttime ON captiveportal (allow_time);". "CREATE INDEX IF NOT EXISTS starttime ON captiveportal (allow_time);" .
"CREATE TABLE IF NOT EXISTS captiveportal_mac (" . # table used for static mac's "CREATE TABLE IF NOT EXISTS captiveportal_mac (" . # table used for static mac's
"mac TEXT, ip TEXT,pipeno_in INTEGER, pipeno_out INTEGER, last_checked INTEGER );" . "mac TEXT, ip TEXT,pipeno_in INTEGER, pipeno_out INTEGER, last_checked INTEGER );" .
"CREATE UNIQUE INDEX IF NOT EXISTS idx_mac ON captiveportal_mac (mac) ;". "CREATE UNIQUE INDEX IF NOT EXISTS idx_mac ON captiveportal_mac (mac) ;" .
"CREATE TABLE IF NOT EXISTS captiveportal_ip (" . # table used for static ip's "CREATE TABLE IF NOT EXISTS captiveportal_ip (" . # table used for static ip's
"ip TEXT,pipeno_in INTEGER, pipeno_out INTEGER, last_checked INTEGER );" . "ip TEXT,pipeno_in INTEGER, pipeno_out INTEGER, last_checked INTEGER );" .
"CREATE UNIQUE INDEX IF NOT EXISTS idx_ip ON captiveportal_ip (ip) " "CREATE UNIQUE INDEX IF NOT EXISTS idx_ip ON captiveportal_ip (ip) " ;
)
) {
$logger = new \Phalcon\Logger\Adapter\Syslog("logportalauth", array( if (! $this->handle->execute($sql)) {
$logger = new Syslog("logportalauth", array(
'option' => LOG_PID, 'option' => LOG_PID,
'facility' => LOG_LOCAL4 'facility' => LOG_LOCAL4
)); ));
$logger->error("Error during table {$this->zone} creation. Error message: {$this->handle->lastErrorMsg()}"); $msg = "Error during table {$this->zone} creation. Error message: {$this->handle->lastErrorMsg()}";
$this->handle = null ; $logger->error($msg);
$this->handle = null;
} }
}catch (\Exception $e) { } catch (\Exception $e) {
$logger = new \Phalcon\Logger\Adapter\Syslog("logportalauth", array( $logger = new Syslog("logportalauth", array(
'option' => LOG_PID, 'option' => LOG_PID,
'facility' => LOG_LOCAL4 'facility' => LOG_LOCAL4
)); ));
$logger->error("Error opening database for zone " . $this->zone . " : ".$e->getMessage()." "); $logger->error("Error opening database for zone " . $this->zone . " : " . $e->getMessage() . " ");
$this->handle = null ; $this->handle = null;
} }
return $this->handle; return $this->handle;
...@@ -165,18 +177,26 @@ class DB { ...@@ -165,18 +177,26 @@ class DB {
* remove session(s) from database * remove session(s) from database
* @param $sessionids session ids ( or id ) * @param $sessionids session ids ( or id )
*/ */
function remove_session($sessionids){ public function removeSession($sessionids)
if ( $this->handle != null ){ {
if ( is_array($sessionids) ) $tmpids = $sessionids; if ($this->handle != null) {
else $tmpids = array($sessionids); if (is_array($sessionids)) {
$tmpids = $sessionids;
} else {
$tmpids = array($sessionids);
}
$this->handle->begin() ; $this->handle->begin();
$stmt = $this->handle->prepare('DELETE FROM captiveportal WHERE sessionid = :sessionid'); $stmt = $this->handle->prepare('DELETE FROM captiveportal WHERE sessionid = :sessionid');
foreach( $tmpids as $session ) { foreach ($tmpids as $session) {
$this->handle->executePrepared($stmt, array('sessionid' => $session),array("sessionid"=>\PDO::PARAM_STR)); $this->handle->executePrepared(
$stmt,
array('sessionid' => $session),
array("sessionid" => \PDO::PARAM_STR)
);
$stmt->execute(); $stmt->execute();
} }
$this->handle->commit() ; $this->handle->commit();
} }
} }
...@@ -186,15 +206,18 @@ class DB { ...@@ -186,15 +206,18 @@ class DB {
* @param string $sessionid session id * @param string $sessionid session id
* @param Array() $content data to alter ( fields from "captiveportal") * @param Array() $content data to alter ( fields from "captiveportal")
*/ */
function update_session($sessionid,$content){ public function updateSession($sessionid, $content)
if ( $this->handle != null ) { {
if ($this->handle != null) {
$query = "update captiveportal set "; $query = "update captiveportal set ";
$bind_values = Array("sessionid" => $sessionid); $bind_values = array("sessionid" => $sessionid);
foreach ($content as $fieldname => $fieldvalue) { foreach ($content as $fieldname => $fieldvalue) {
// you may not alter data not described in $this->captiveportal_types // you may not alter data not described in $this->captiveportal_types
if (array_key_exists($fieldname, $this->captiveportal_types)) { if (array_key_exists($fieldname, $this->captiveportal_types)) {
if (sizeof($bind_values) > 1) $query .= " , "; if (sizeof($bind_values) > 1) {
$query .= $fieldname." = "." :".$fieldname." "; $query .= " , ";
}
$query .= $fieldname . " = " . " :" . $fieldname . " ";
$bind_values[$fieldname] = $fieldvalue; $bind_values[$fieldname] = $fieldvalue;
} }
} }
...@@ -202,11 +225,12 @@ class DB { ...@@ -202,11 +225,12 @@ class DB {
try { try {
$this->handle->execute($query, $bind_values, $this->captiveportal_types); $this->handle->execute($query, $bind_values, $this->captiveportal_types);
} catch (\Exception $e) { } catch (\Exception $e) {
$logger = new \Phalcon\Logger\Adapter\Syslog("logportalauth", array( $logger = new Syslog("logportalauth", array(
'option' => LOG_PID, 'option' => LOG_PID,
'facility' => LOG_LOCAL4 'facility' => LOG_LOCAL4
)); ));
$logger->error("Trying to modify DB returned error (zone = " . $this->zone . " ) : " . $e->getMessage() . " "); $msg = "Trying to modify DB returned error (zone = " . $this->zone . " ) : " . $e->getMessage() . " ";
$logger->error($msg);
} }
} }
} }
...@@ -217,10 +241,11 @@ class DB { ...@@ -217,10 +241,11 @@ class DB {
* @param string $sessionid unique session id * @param string $sessionid unique session id
* @param Array() field content ( defined fields in "captiveportal") * @param Array() field content ( defined fields in "captiveportal")
*/ */
function insert_session($sessionid,$content){ public function insertSession($sessionid, $content)
if ( $this->handle != null ) { {
if ($this->handle != null) {
// construct insert query, using placeholders for bind variables // construct insert query, using placeholders for bind variables
$bind_values = Array("sessionid" => $sessionid); $bind_values = array("sessionid" => $sessionid);
$query = "insert into captiveportal (sessionid "; $query = "insert into captiveportal (sessionid ";
$query_values = "values (:sessionid "; $query_values = "values (:sessionid ";
foreach ($content as $fieldname => $fieldvalue) { foreach ($content as $fieldname => $fieldvalue) {
...@@ -235,35 +260,39 @@ class DB { ...@@ -235,35 +260,39 @@ class DB {
try { try {
$this->handle->execute($query, $bind_values, $this->captiveportal_types); $this->handle->execute($query, $bind_values, $this->captiveportal_types);
} catch (\Exception $e) { } catch (\Exception $e) {
$logger = new \Phalcon\Logger\Adapter\Syslog("logportalauth", array( $logger = new Syslog("logportalauth", array(
'option' => LOG_PID, 'option' => LOG_PID,
'facility' => LOG_LOCAL4 'facility' => LOG_LOCAL4
)); ));
$logger->error("Trying to modify DB returned error (zone = " . $this->zone . " ) : " . $e->getMessage() . " "); $msg = "Trying to modify DB returned error (zone = " . $this->zone . " ) : " . $e->getMessage() . " ";
$logger->error($msg);
} }
} }
} }
/** /**
* get captive portal clients * get captive portal clients
* @param Array() $args * @param array() $qryargs query filters (named array)
* @param string $operator choose and/or
* @param string $order_by sort order
*/ */
function listClients($qryargs,$operator="and",$order_by=null){ public function listClients($qryargs, $operator = "and", $order_by = null)
{
// construct query, only parse fields defined by $this->captiveportal_types // construct query, only parse fields defined by $this->captiveportal_types
$qry_tag = "where " ; $qry_tag = "where ";
$query = "select * from captiveportal "; $query = "select * from captiveportal ";
$query_order_by = "" ; $query_order_by = "";
foreach ( $qryargs as $fieldname => $fieldvalue ){ foreach ($qryargs as $fieldname => $fieldvalue) {
if ( array_key_exists($fieldname,$this->captiveportal_types) ){ if (array_key_exists($fieldname, $this->captiveportal_types)) {
$query .= $qry_tag . $fieldname." = "." :".$fieldname." "; $query .= $qry_tag . $fieldname . " = " . " :" . $fieldname . " ";
$qry_tag = " ".$operator." "; $qry_tag = " " . $operator . " ";
} }
} }
// apply ordering to result, validate fields // apply ordering to result, validate fields
if (is_array($order_by)){ if (is_array($order_by)) {
foreach ( $order_by as $fieldname ){ foreach ($order_by as $fieldname) {
if ( is_array($order_by) && in_array($fieldname,$order_by) ) { if (is_array($order_by) && in_array($fieldname, $order_by)) {
if ($query_order_by != "") { if ($query_order_by != "") {
$query_order_by .= " , "; $query_order_by .= " , ";
} }
...@@ -272,7 +301,9 @@ class DB { ...@@ -272,7 +301,9 @@ class DB {
} }
} }
if ( $query_order_by != "" ) $query .= " order by " . $query_order_by; if ($query_order_by != "") {
$query .= " order by " . $query_order_by;
}
$resultset = $this->handle->query($query, $qryargs, $this->captiveportal_types); $resultset = $this->handle->query($query, $qryargs, $this->captiveportal_types);
...@@ -281,17 +312,20 @@ class DB { ...@@ -281,17 +312,20 @@ class DB {
return $resultset->fetchAll(); return $resultset->fetchAll();
} }
/** /**
* * @param array $qryargs query filters (named array)
* @param string $operator and/or
* @return mixed number of connected users/clients * @return mixed number of connected users/clients
*/ */
function countClients($qryargs=array(),$operator="and"){ public function countClients($qryargs = array(), $operator = "and")
{
$query = "select count(*) cnt from captiveportal "; $query = "select count(*) cnt from captiveportal ";
$qry_tag = "where " ; $qry_tag = "where ";
foreach ( $qryargs as $fieldname => $fieldvalue ){ foreach ($qryargs as $fieldname => $fieldvalue) {
if ( array_key_exists($fieldname,$this->captiveportal_types) ){ if (array_key_exists($fieldname, $this->captiveportal_types)) {
$query .= $qry_tag . $fieldname." = "." :".$fieldname." "; $query .= $qry_tag . $fieldname . " = " . " :" . $fieldname . " ";
$qry_tag = " ".$operator." "; $qry_tag = " " . $operator . " ";
} }
} }
...@@ -307,9 +341,10 @@ class DB { ...@@ -307,9 +341,10 @@ class DB {
* *
* @return Array() * @return Array()
*/ */
function listFixedIPs(){ public function listFixedIPs()
{
$result = array(); $result = array();
if ($this->handle != null ) { if ($this->handle != null) {
$resultset = $this->handle->query("select ip,pipeno_in,pipeno_out,last_checked from captiveportal_ip"); $resultset = $this->handle->query("select ip,pipeno_in,pipeno_out,last_checked from captiveportal_ip");
$resultset->setFetchMode(\Phalcon\Db::FETCH_OBJ); $resultset->setFetchMode(\Phalcon\Db::FETCH_OBJ);
...@@ -324,21 +359,35 @@ class DB { ...@@ -324,21 +359,35 @@ class DB {
/** /**
* insert new passthru mac address * insert new passthru mac address
* @param $ip hosts ip address * @param $ip hosts ip address
* @param int $pipeno_in
* @param int $pipeno_out
*/ */
function upsertFixedIP($ip,$pipeno_in=null,$pipeno_out=null){ public function upsertFixedIP($ip, $pipeno_in = null, $pipeno_out = null)
{
// perform an upsert to update the data for this physical host. // perform an upsert to update the data for this physical host.
// unfortunately this costs an extra write io for the first record, but provides cleaner code // unfortunately this costs an extra write io for the first record, but provides cleaner code
$params = array("ip"=>$ip,"pipeno_in"=>$pipeno_in,"pipeno_out"=>$pipeno_out,"last_checked"=>time()); $params = array("ip" => $ip, "pipeno_in" => $pipeno_in, "pipeno_out" => $pipeno_out, "last_checked" => time());
$this->handle->execute("insert or ignore into captiveportal_ip(ip) values (:ip)", array("ip"=>$ip),$this->captiveportal_ip_types); $this->handle->execute(
$this->handle->execute("update captiveportal_ip set ip=:ip, last_checked=:last_checked, pipeno_in = :pipeno_in, pipeno_out = :pipeno_out where ip =:ip ", $params,$this->captiveportal_ip_types); "insert or ignore into captiveportal_ip(ip) values (:ip)",
array("ip" => $ip),
$this->captiveportal_ip_types
);
$sql ="update captiveportal_ip set ip=:ip, last_checked=:last_checked, ".
"pipeno_in = :pipeno_in, pipeno_out = :pipeno_out where ip =:ip ";
$this->handle->execute($sql, $params, $this->captiveportal_ip_types);
} }
/** /**
* drop address from administration (captiveportal_ip) * drop address from administration (captiveportal_ip)
* @param $mac physical address * @param $ip ip address
*/ */
function dropFixedIP($ip){ public function dropFixedIP($ip)
$this->handle->execute("delete from captiveportal_ip where ip =:ip ", array("ip"=>$ip),$this->captiveportal_ip_types); {
$this->handle->execute(
"delete from captiveportal_ip where ip =:ip ",
array("ip" => $ip),
$this->captiveportal_ip_types
);
} }
/** /**
...@@ -346,9 +395,10 @@ class DB { ...@@ -346,9 +395,10 @@ class DB {
* *
* @return Array() * @return Array()
*/ */
function listPassthruMacs(){ public function listPassthruMacs()
{
$result = array(); $result = array();
if ($this->handle != null ) { if ($this->handle != null) {
$resultset = $this->handle->query("select mac,ip,last_checked,pipeno_in,pipeno_out from captiveportal_mac"); $resultset = $this->handle->query("select mac,ip,last_checked,pipeno_in,pipeno_out from captiveportal_mac");
$resultset->setFetchMode(\Phalcon\Db::FETCH_OBJ); $resultset->setFetchMode(\Phalcon\Db::FETCH_OBJ);
...@@ -364,24 +414,41 @@ class DB { ...@@ -364,24 +414,41 @@ class DB {
* insert new passthru mac address * insert new passthru mac address
* @param $mac physical address * @param $mac physical address
* @param $ip hosts ip address * @param $ip hosts ip address
* @param null $pipeno_in
* @param null $pipeno_out
*/ */
function upsertPassthruMAC($mac,$ip,$pipeno_in=null,$pipeno_out=null){ public function upsertPassthruMAC($mac, $ip, $pipeno_in = null, $pipeno_out = null)
{
// perform an upsert to update the data for this physical host. // perform an upsert to update the data for this physical host.
// unfortunately this costs an extra write io for the first record, but provides cleaner code // unfortunately this costs an extra write io for the first record, but provides cleaner code
$params = array("mac"=>$mac,"ip"=>$ip,"pipeno_in"=>$pipeno_in,"pipeno_out"=>$pipeno_out,"last_checked"=>time()); $params = array(
$this->handle->execute("insert or ignore into captiveportal_mac(mac) values (:mac)", array("mac"=>$mac),$this->captiveportal_mac_types); "mac" => $mac,
$this->handle->execute("update captiveportal_mac set ip=:ip, last_checked=:last_checked, pipeno_in = :pipeno_in, pipeno_out = :pipeno_out where mac =:mac ", $params,$this->captiveportal_mac_types); "ip" => $ip,
"pipeno_in" => $pipeno_in,
"pipeno_out" => $pipeno_out,
"last_checked" => time()
);
$this->handle->execute(
"insert or ignore into captiveportal_mac(mac) values (:mac)",
array("mac" => $mac),
$this->captiveportal_mac_types
);
$sql = "update captiveportal_mac set ip=:ip, last_checked=:last_checked, ".
"pipeno_in = :pipeno_in, pipeno_out = :pipeno_out where mac =:mac " ;
$this->handle->execute($sql, $params, $this->captiveportal_mac_types);
} }
/** /**
* drop address from administration (captiveportal_mac) * drop address from administration (captiveportal_mac)
* @param $mac physical address * @param $mac physical address
*/ */
function dropPassthruMAC($mac){ public function dropPassthruMAC($mac)
$this->handle->execute("delete from captiveportal_mac where mac =:mac ", array("mac"=>$mac),$this->captiveportal_mac_types); {
$this->handle->execute(
"delete from captiveportal_mac where mac =:mac ",
array("mac" => $mac),
$this->captiveportal_mac_types
);
} }
} }
...@@ -39,11 +39,11 @@ use OPNsense\Core; ...@@ -39,11 +39,11 @@ use OPNsense\Core;
* Class Rules * Class Rules
* @package CaptivePortal * @package CaptivePortal
*/ */
class Rules { class Rules
{
/** /**
* config handle * config handle
* @var Core_Config * @var Core\Config
*/ */
private $config = null; private $config = null;
...@@ -57,7 +57,7 @@ class Rules { ...@@ -57,7 +57,7 @@ class Rules {
/** /**
* *
*/ */
function __construct() public function __construct()
{ {
// Request handle to configuration // Request handle to configuration
$this->config = Core\Config::getInstance(); $this->config = Core\Config::getInstance();
...@@ -66,28 +66,31 @@ class Rules { ...@@ -66,28 +66,31 @@ class Rules {
/** /**
* get ipfw tables for authenticated users ( in/out ) * get ipfw tables for authenticated users ( in/out )
* @param $zoneid zoneid (number) * @param int $zoneid zoneid (number)
* @return array * @return array
*/ */
function getAuthUsersTables($zoneid){ public function getAuthUsersTables($zoneid)
{
return array("in"=>(6*($zoneid-1) )+1,"out"=>(6*($zoneid-1) )+2); return array("in"=>(6*($zoneid-1) )+1,"out"=>(6*($zoneid-1) )+2);
} }
/** /**
* get ipfw tables for authenticated hosts ( in/out ) * get ipfw tables for authenticated hosts ( in/out )
* @param $zoneid zoneid (number) * @param int $zoneid zoneid (number)
* @return array * @return array
*/ */
function getAuthIPTables($zoneid){ public function getAuthIPTables($zoneid)
{
return array("in"=>(6*($zoneid-1) )+3,"out"=>(6*($zoneid-1) )+4); return array("in"=>(6*($zoneid-1) )+3,"out"=>(6*($zoneid-1) )+4);
} }
/** /**
* get ipfw tables used for authenticated physical addresses * get ipfw tables used for authenticated physical addresses
* @param $zoneid zoneid (number) * @param int $zoneid zoneid (number)
* @return array * @return array
*/ */
function getAuthMACTables($zoneid){ public function getAuthMACTables($zoneid)
{
return array("in"=>(6*($zoneid-1) )+5,"out"=>(6*($zoneid-1) )+6); return array("in"=>(6*($zoneid-1) )+5,"out"=>(6*($zoneid-1) )+6);
} }
...@@ -96,16 +99,17 @@ class Rules { ...@@ -96,16 +99,17 @@ class Rules {
* default rules * default rules
* rule number range 1..1000 * rule number range 1..1000
*/ */
private function generate_default_rules(){ private function generateDefaultRules()
{
// define general purpose rules, rule number 1 .... 1000 // define general purpose rules, rule number 1 .... 1000
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "# flush ruleset "; $this->rules[] = "# flush ruleset ";
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "flush" ; $this->rules[] = "flush" ;
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "# general purpose rules 1...1000 "; $this->rules[] = "# general purpose rules 1...1000 ";
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "add 100 allow pfsync from any to any"; $this->rules[] = "add 100 allow pfsync from any to any";
$this->rules[] = "add 110 allow carp from any to any"; $this->rules[] = "add 110 allow carp from any to any";
$this->rules[] = "# layer 2: pass ARP"; $this->rules[] = "# layer 2: pass ARP";
...@@ -123,20 +127,26 @@ class Rules { ...@@ -123,20 +127,26 @@ class Rules {
* Always allow traffic to our own host ( all static addresses from configuration ) * Always allow traffic to our own host ( all static addresses from configuration )
* rule number range 1001..1999 * rule number range 1001..1999
*/ */
private function generate_this_host_rules(){ private function generateThisHostRules()
{
// search all static / non wan addresses and add rules to $this->rules // search all static / non wan addresses and add rules to $this->rules
$rulenum = 1001 ; $rulenum = 1001 ;
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "# Allow traffic to this hosts static ip's ( 1001..1999 ) "; $this->rules[] = "# Allow traffic to this hosts static ip's ( 1001..1999 ) ";
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
foreach( $this->config->object()->interfaces->children() as $interface => $content ){ foreach ($this->config->object()->interfaces->children() as $interface => $content) {
if ( $interface != "wan" && $content->ipaddr != "dhcp" ){ if ($interface != "wan" && $content->ipaddr != "dhcp") {
// only keep state of dns traffic to prevent dns resolver failures // only keep state of dns traffic to prevent dns resolver failures
$this->rules[] = "add ".$rulenum++." allow udp from any to ".$content->ipaddr." dst-port 53 keep-state in"; $this->rules[] = "add ".$rulenum++." allow udp from any to ".
$this->rules[] = "add ".$rulenum++." allow ip from any to { 255.255.255.255 or ".$content->ipaddr." } in"; $content->ipaddr." dst-port 53 keep-state in";
$this->rules[] = "add ".$rulenum++." allow ip from { 255.255.255.255 or ".$content->ipaddr." } to any out"; $this->rules[] = "add ".$rulenum++." allow ip from any to { 255.255.255.255 or ".
$this->rules[] = "add ".$rulenum++." allow icmp from { 255.255.255.255 or ".$content->ipaddr." } to any out icmptypes 0"; $content->ipaddr." } in";
$this->rules[] = "add ".$rulenum++." allow icmp from any to { 255.255.255.255 or ".$content->ipaddr." } in icmptypes 8"; $this->rules[] = "add ".$rulenum++." allow ip from { 255.255.255.255 or ".
$content->ipaddr." } to any out";
$this->rules[] = "add ".$rulenum++." allow icmp from { 255.255.255.255 or ".
$content->ipaddr." } to any out icmptypes 0";
$this->rules[] = "add ".$rulenum++." allow icmp from any to { 255.255.255.255 or ".
$content->ipaddr." } in icmptypes 8";
} }
} }
} }
...@@ -159,55 +169,80 @@ class Rules { ...@@ -159,55 +169,80 @@ class Rules {
* *
* rule number ranges 3001..3999, 10000...50000 * rule number ranges 3001..3999, 10000...50000
*/ */
private function generate_zones(){ private function generateZones()
foreach( $this->config->object()->captiveportal->children() as $cpzonename => $zone ) { {
if ( isset( $zone->enable) ) { foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zone) {
if (isset($zone->enable)) {
// search interface // search interface
$interface = $zone->interface->xpath("//" . $zone->interface); $interface = $zone->interface->xpath("//" . $zone->interface);
// allocate tables for captive portal // allocate tables for captive portal
$table_id = (6 * ($zone->zoneid - 1)); $this->rules[] = "#===================================================================================";
$this->rules[] = "#=========================================================================================================";
$this->rules[] = "# zone " . $cpzonename . " (" . $zone->zoneid . ") configuration"; $this->rules[] = "# zone " . $cpzonename . " (" . $zone->zoneid . ") configuration";
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#===================================================================================";
if (count($interface) > 0) { if (count($interface) > 0) {
$interface = $interface[0]; $interface = $interface[0];
// authenticated users ( table 1 + 2 ) // authenticated users ( table 1 + 2 )
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 1) . " skipto " . ((($zone->zoneid * 1000) + 10000) + 1) . " ip from table(" . $this->getAuthUsersTables($zone->zoneid)["in"] . ") to any via " . $interface->if; $this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 1) . " skipto " .
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 2) . " skipto " . ((($zone->zoneid * 1000) + 10000) + 1) . " ip from any to table(" . $this->getAuthUsersTables($zone->zoneid)["in"] . ") via " . $interface->if; ((($zone->zoneid * 1000) + 10000) + 1) . " ip from table(" .
$this->getAuthUsersTables($zone->zoneid)["in"] . ") to any via " . $interface->if;
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 2) . " skipto " .
((($zone->zoneid * 1000) + 10000) + 1) . " ip from any to table(" .
$this->getAuthUsersTables($zone->zoneid)["in"] . ") via " . $interface->if;
// authenticated hosts ( table 3 + 4 ) // authenticated hosts ( table 3 + 4 )
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 3) . " skipto " . ((($zone->zoneid * 1000) + 10000) + 1) . " ip from table(" . $this->getAuthIPTables($zone->zoneid)["in"] . ") to any via " . $interface->if; $this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 3) . " skipto " .
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 4) . " skipto " . ((($zone->zoneid * 1000) + 10000) + 1) . " ip from any to table(" . $this->getAuthIPTables($zone->zoneid)["in"] . ") via " . $interface->if; ((($zone->zoneid * 1000) + 10000) + 1) . " ip from table(" .
$this->getAuthIPTables($zone->zoneid)["in"] . ") to any via " . $interface->if;
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 4) . " skipto " .
((($zone->zoneid * 1000) + 10000) + 1) . " ip from any to table(" .
$this->getAuthIPTables($zone->zoneid)["in"] . ") via " . $interface->if;
// authenticated mac addresses ( table 5 + 6 ) // authenticated mac addresses ( table 5 + 6 )
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 5) . " skipto " . ((($zone->zoneid * 1000) + 10000) + 1) . " ip from table(" . $this->getAuthMACTables($zone->zoneid)["in"] . ") to any via " . $interface->if; $this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 5) . " skipto " .
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 6) . " skipto " . ((($zone->zoneid * 1000) + 10000) + 1) . " ip from any to table(" . $this->getAuthMACTables($zone->zoneid)["in"] . ") via " . $interface->if; ((($zone->zoneid * 1000) + 10000) + 1) . " ip from table(" .
$this->getAuthMACTables($zone->zoneid)["in"] . ") to any via " . $interface->if;
$this->rules[] = "add " . (3000 + ($zone->zoneid * 10) + 6) . " skipto " .
((($zone->zoneid * 1000) + 10000) + 1) . " ip from any to table(" .
$this->getAuthMACTables($zone->zoneid)["in"] . ") via " . $interface->if;
// TODO: solve dummynet kernel issue on outgoing traffic // TODO: solve dummynet kernel issue on outgoing traffic
// // dummynet 1,2 // // dummynet 1,2
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+1)." pipe tablearg ip from table(".($table_id+1).") to any in via ".$interface->if ; // $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+1) .
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+2)." pipe tablearg ip from any to table(".($table_id+2).") out via ".$interface->if ; // " pipe tablearg ip from table(".($table_id+1).") to any in via ".$interface->if ;
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+2) .
//" pipe tablearg ip from any to table(".($table_id+2).") out via ".$interface->if ;
// //
// // dummynet 3,4 // // dummynet 3,4
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+3)." pipe tablearg ip from table(".($table_id+3).") to any in via ".$interface->if ; // $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+3) .
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+4)." pipe tablearg ip from table(".($table_id+3).") to any out via ".$interface->if ; //" pipe tablearg ip from table(".($table_id+3).") to any in via ".$interface->if ;
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+5)." pipe tablearg ip from any to table(".($table_id+4).") in via ".$interface->if ; // $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+4) .
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+6)." pipe tablearg ip from any to table(".($table_id+4).") out via ".$interface->if ; //" pipe tablearg ip from table(".($table_id+3).") to any out via ".$interface->if ;
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+5) .
//" pipe tablearg ip from any to table(".($table_id+4).") in via ".$interface->if ;
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+6) .
//" pipe tablearg ip from any to table(".($table_id+4).") out via ".$interface->if ;
// // dummynet 5,6 // // dummynet 5,6
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+7)." pipe tablearg ip from table(".($table_id+5).") to any in via ".$interface->if ; // $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+7) .
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+8)." pipe tablearg ip from table(".($table_id+5).") to any out via ".$interface->if ; //" pipe tablearg ip from table(".($table_id+5).") to any in via ".$interface->if ;
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+9)." pipe tablearg ip from any to table(".($table_id+6).") in via ".$interface->if ; // $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+8) .
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+10)." pipe tablearg ip from any to table(".($table_id+6).") out via ".$interface->if ; //" pipe tablearg ip from table(".($table_id+5).") to any out via ".$interface->if ;
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+9) .
//" pipe tablearg ip from any to table(".($table_id+6).") in via ".$interface->if ;
// $this->rules[] = "add ".((($zone->zoneid*1000)+10000)+10) .
//" pipe tablearg ip from any to table(".($table_id+6).") out via ".$interface->if ;
// statistics for this zone, placeholder to jump to // statistics for this zone, placeholder to jump to
$this->rules[] = "add " . ((($zone->zoneid * 1000) + 10000) + 1) . " count ip from any to any via " . $interface->if; $this->rules[] = "add " . ((($zone->zoneid * 1000) + 10000) + 1) .
" count ip from any to any via " . $interface->if;
// jump to accounting section // jump to accounting section
$this->rules[] = "add " . ((($zone->zoneid * 1000) + 10000) + 998) . " skipto 30000 all from any to any via " . $interface->if; $this->rules[] = "add " . ((($zone->zoneid * 1000) + 10000) + 998) .
$this->rules[] = "add " . ((($zone->zoneid * 1000) + 10000) + 999) . " deny all from any to any not via " . $interface->if; " skipto 30000 all from any to any via " . $interface->if;
$this->rules[] = "add " . ((($zone->zoneid * 1000) + 10000) + 999) .
" deny all from any to any not via " . $interface->if;
} }
} }
...@@ -219,20 +254,23 @@ class Rules { ...@@ -219,20 +254,23 @@ class Rules {
* Forward all non authenticated traffic from captive portal zones * Forward all non authenticated traffic from captive portal zones
* rule number range 5001..5999 * rule number range 5001..5999
*/ */
private function generate_reflect_rules(){ private function generateReflectRules()
{
$forward_port = 8000 ; $forward_port = 8000 ;
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "# redirect non-authenticated clients to captive portal @ local port ".$forward_port." + zoneid "; $this->rules[] = "# redirect non-authenticated clients to captive portal @ local port " .
$this->rules[] = "#========================================================================================================="; $forward_port." + zoneid ";
foreach( $this->config->object()->captiveportal->children() as $cpzonename => $zone ){ $this->rules[] = "#======================================================================================";
foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zone) {
if (isset($zone->enable)) { if (isset($zone->enable)) {
// search interface // search interface
$interface = $zone->interface->xpath("//".$zone->interface); $interface = $zone->interface->xpath("//".$zone->interface);
if (count($interface) > 0){ if (count($interface) > 0) {
$interface = $interface[0] ; $interface = $interface[0] ;
if ($interface->ipaddr != null){ if ($interface->ipaddr != null) {
// add forward rule to this zone's http instance @ $forward_port + $zone->zoneid // add forward rule to this zone's http instance @ $forward_port + $zone->zoneid
$this->rules[] ="add ".(5000+$zone->zoneid)." fwd 127.0.0.1,".($forward_port + $zone->zoneid )." tcp from any to any dst-port 80 in via ".$interface->if; $this->rules[] ="add ".(5000+$zone->zoneid)." fwd 127.0.0.1,".($forward_port + $zone->zoneid ).
" tcp from any to any dst-port 80 in via ".$interface->if;
} }
} }
...@@ -244,11 +282,12 @@ class Rules { ...@@ -244,11 +282,12 @@ class Rules {
* for accounting statistics we setup a separate section in our config * for accounting statistics we setup a separate section in our config
* rule number range 30000..65500 * rule number range 30000..65500
*/ */
private function generate_accounting_section(){ private function generateAccountingSection()
$this->rules[] = "#========================================================================================================="; {
$this->rules[] = "#======================================================================================";
$this->rules[] = "# setup accounting section, first rule is counting all CP traffic "; $this->rules[] = "# setup accounting section, first rule is counting all CP traffic ";
$this->rules[] = "# rule 65500 unlocks the traffic already authorized from a CP zone"; $this->rules[] = "# rule 65500 unlocks the traffic already authorized from a CP zone";
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "add 30000 set 0 count ip from any to any "; $this->rules[] = "add 30000 set 0 count ip from any to any ";
$this->rules[] = "add 65500 pass ip from any to any "; $this->rules[] = "add 65500 pass ip from any to any ";
} }
...@@ -257,10 +296,11 @@ class Rules { ...@@ -257,10 +296,11 @@ class Rules {
* generate closure tag, block all traffic coming from captiveportal interfaces * generate closure tag, block all traffic coming from captiveportal interfaces
* rule number range 6001..6999 * rule number range 6001..6999
*/ */
private function generate_closure(){ private function generateClosure()
{
$cpinterfaces = []; $cpinterfaces = [];
# find all cp interfaces # find all cp interfaces
foreach( $this->config->object()->captiveportal->children() as $cpzonename => $zone ) { foreach ($this->config->object()->captiveportal->children() as $cpzonename => $zone) {
if (isset($zone->enable)) { if (isset($zone->enable)) {
// search interface // search interface
$interface = $zone->interface->xpath("//" . $zone->interface); $interface = $zone->interface->xpath("//" . $zone->interface);
...@@ -274,11 +314,11 @@ class Rules { ...@@ -274,11 +314,11 @@ class Rules {
// generate accept rules for every interface not in captive portal // generate accept rules for every interface not in captive portal
$ruleid = 6001 ; $ruleid = 6001 ;
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
$this->rules[] = "# accept traffic from all interfaces not used by captive portal (5001..5999) "; $this->rules[] = "# accept traffic from all interfaces not used by captive portal (5001..5999) ";
$this->rules[] = "#========================================================================================================="; $this->rules[] = "#======================================================================================";
foreach( $this->config->object()->interfaces->children() as $interface => $content ){ foreach ($this->config->object()->interfaces->children() as $interface => $content) {
if ( !isset($cpinterfaces[$content->if->__toString()])){ if (!isset($cpinterfaces[$content->if->__toString()])) {
$this->rules[] = "add ".($ruleid++)." allow all from any to any via ".$content->if ; $this->rules[] = "add ".($ruleid++)." allow all from any to any via ".$content->if ;
} }
} }
...@@ -296,8 +336,10 @@ class Rules { ...@@ -296,8 +336,10 @@ class Rules {
/** /**
* load ruleset * load ruleset
* @param string $filename target filename
*/ */
public function generate($filename){ public function generate($filename)
{
/* /*
* reset rules * reset rules
*/ */
...@@ -306,24 +348,25 @@ class Rules { ...@@ -306,24 +348,25 @@ class Rules {
/* /*
* generate new * generate new
*/ */
$this->generate_default_rules(); $this->generateDefaultRules();
$this->generate_this_host_rules(); $this->generateThisHostRules();
$this->generate_zones(); $this->generateZones();
$this->generate_reflect_rules(); $this->generateReflectRules();
$this->generate_accounting_section(); $this->generateAccountingSection();
$this->generate_closure(); $this->generateClosure();
// ruleset array -> text // ruleset array -> text
$ruleset_txt = ""; $ruleset_txt = "";
$prev_rule = "#"; $prev_rule = "#";
foreach($this->rules as $rule){ foreach ($this->rules as $rule) {
if (trim($rule)[0] == '#' && trim($prev_rule)[0] != "#" ) $ruleset_txt .= "\n"; if (trim($rule)[0] == '#' && trim($prev_rule)[0] != "#") {
$ruleset_txt .= "\n";
}
$ruleset_txt .= $rule."\n"; $ruleset_txt .= $rule."\n";
$prev_rule = $rule ; $prev_rule = $rule ;
} }
// write to file // write to file
file_put_contents($filename,$ruleset_txt); file_put_contents($filename, $ruleset_txt);
} }
} }
...@@ -34,17 +34,14 @@ ...@@ -34,17 +34,14 @@
namespace OPNsense\Core; namespace OPNsense\Core;
/** use \Phalcon\DI\FactoryDefault;
* Class ConfigException
* @package Core
*/
class ConfigException extends \Exception { }
/** /**
* Class Config * Class Config
* @package Core * @package Core
*/ */
class Config extends Singleton { class Config extends Singleton
{
/** /**
* config file location ( path + name ) * config file location ( path + name )
...@@ -68,32 +65,52 @@ class Config extends Singleton { ...@@ -68,32 +65,52 @@ class Config extends Singleton {
* status field: valid config loaded * status field: valid config loaded
* @var bool * @var bool
*/ */
private $isValid = False; private $isValid = false;
/** /**
* Load config file * print config xml in dot notation
* @param DOMNode $node
* @param string $nodename
* @throws ConfigException * @throws ConfigException
*/ */
private function load(){ public function dump($node = null, $nodename = "")
// exception handling {
if ( !file_exists($this->config_file) ) throw new ConfigException('file not found') ; $this->checkvalid();
$xml = file_get_contents($this->config_file); // root node
if (trim($xml) == '') { if ($node == null) {
throw new ConfigException('empty file') ; $node = $this->configxml;
} }
$this->configxml = new \DOMDocument; $subNodes = $node->childNodes ;
$this->configxml->loadXML($xml); foreach ($subNodes as $subNode) {
$this->simplexml = simplexml_import_dom($this->configxml); if ($subNode->nodeType == XML_TEXT_NODE &&(strlen(trim($subNode->wholeText))>=1)) {
$this->isValid = true; print($nodename.".". $node->tagName." " .$subNode->nodeValue ."\n");
}
if ($subNode->hasChildNodes()) {
if ($nodename != "") {
$tmp = $nodename.".".$node->tagName;
} elseif ($node != $this->configxml) {
$tmp = $node->tagName;
} else {
$tmp = "";
}
$this->dump($subNode, $tmp);
}
}
} }
/** /**
* @throws ConfigException * @throws ConfigException
*/ */
private function checkvalid(){ private function checkvalid()
if ( !$this->isValid ) throw new ConfigException('no valid config loaded') ; {
if (!$this->isValid) {
throw new ConfigException('no valid config loaded') ;
}
} }
/* /*
...@@ -102,41 +119,23 @@ class Config extends Singleton { ...@@ -102,41 +119,23 @@ class Config extends Singleton {
* @param string $nodename * @param string $nodename
* @throws ConfigException * @throws ConfigException
*/ */
public function dump($node=null,$nodename=""){
$this->checkvalid();
// root node
if ($node == null ) $node = $this->configxml;
$subNodes = $node->childNodes ;
foreach($subNodes as $subNode){
if ( $subNode->nodeType == XML_TEXT_NODE &&(strlen(trim($subNode->wholeText))>=1)) {
print($nodename.".". $node->tagName." " .$subNode->nodeValue ."\n");
}
if ( $subNode->hasChildNodes() ){
if ( $nodename != "" ) $tmp = $nodename.".".$node->tagName;
elseif ($node != $this->configxml) $tmp = $node->tagName;
else $tmp = "";
$this->dump($subNode,$tmp);
}
}
public function xpath($query)
{
$this->checkvalid();
$xpath = new \DOMXPath($this->configxml);
return $xpath->query($query);
} }
/* /*
* init new config object, try to load current configuration * init new config object, try to load current configuration
* (executed via Singleton) * (executed via Singleton)
*/ */
protected function init() {
$this->config_file = \Phalcon\DI\FactoryDefault::getDefault()->get('config')->globals->config_path . "config.xml";
try {
$this->load();
} catch (\Exception $e){
$this->configxml = null ;
}
public function object()
{
$this->checkvalid();
return $this->simplexml;
} }
/* /*
...@@ -145,10 +144,16 @@ class Config extends Singleton { ...@@ -145,10 +144,16 @@ class Config extends Singleton {
* @return \DOMNodeList * @return \DOMNodeList
* @throws ConfigException * @throws ConfigException
*/ */
function xpath($query){
$this->checkvalid(); protected function init()
$xpath = new \DOMXPath($this->configxml); {
return $xpath->query($query); $this->config_file = FactoryDefault::getDefault()->get('config')->globals->config_path . "config.xml";
try {
$this->load();
} catch (\Exception $e) {
$this->configxml = null ;
}
} }
/* /*
...@@ -156,9 +161,26 @@ class Config extends Singleton { ...@@ -156,9 +161,26 @@ class Config extends Singleton {
* @return SimpleXML * @return SimpleXML
* @throws ConfigException * @throws ConfigException
*/ */
function object(){
$this->checkvalid(); /**
return $this->simplexml; * Load config file
* @throws ConfigException
*/
private function load()
{
// exception handling
if (!file_exists($this->config_file)) {
throw new ConfigException('file not found') ;
}
$xml = file_get_contents($this->config_file);
if (trim($xml) == '') {
throw new ConfigException('empty file') ;
} }
$this->configxml = new \DOMDocument;
$this->configxml->loadXML($xml);
$this->simplexml = simplexml_import_dom($this->configxml);
$this->isValid = true;
}
} }
<?php
/**
* Created by PhpStorm.
* User: ad
* Date: 04-01-15
* Time: 20:06
*/
namespace app\models\OPNsense\Core;
/**
* Class ConfigException
* @package Core
*/
class ConfigException extends \Exception
{
}
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
namespace OPNsense\Core; namespace OPNsense\Core;
use \Phalcon\DI\FactoryDefault;
class Shell class Shell
{ {
...@@ -52,11 +53,31 @@ class Shell ...@@ -52,11 +53,31 @@ class Shell
/** /**
* new shell object * new shell object
*/ */
function __construct() public function __construct()
{ {
// init, set simulation mode / debug autoput // init, set simulation mode / debug autoput
$this->simulate = \Phalcon\DI\FactoryDefault::getDefault()->get('config')->globals->simulate_mode; $this->simulate = FactoryDefault::getDefault()->get('config')->globals->simulate_mode;
$this->debug = \Phalcon\DI\FactoryDefault::getDefault()->get('config')->globals->debug; $this->debug = FactoryDefault::getDefault()->get('config')->globals->debug;
}
/**
* execute command or list of commands
*
* @param string/Array() $command command to execute
* @param bool $mute
* @param bool $clearsigmask
* @param Array() &$output
*/
public function exec($command, $mute = false, $clearsigmask = false, &$output = null)
{
if (is_array($command)) {
foreach ($command as $comm) {
$this->execSingle($comm, $mute, $clearsigmask, $output);
}
} else {
$this->execSingle($command, $mute, $clearsigmask, $output);
}
} }
...@@ -65,8 +86,11 @@ class Shell ...@@ -65,8 +86,11 @@ class Shell
* @param string $command command to execute * @param string $command command to execute
* @param bool $mute * @param bool $mute
* @param bool $clearsigmask * @param bool $clearsigmask
* @param Array() &$output
* @return int
*/ */
private function _exec($command, $mute = false, $clearsigmask = false,&$output=null){ private function execSingle($command, $mute = false, $clearsigmask = false, &$output = null)
{
$oarr = array(); $oarr = array();
$retval = 0; $retval = 0;
...@@ -82,10 +106,11 @@ class Shell ...@@ -82,10 +106,11 @@ class Shell
pcntl_sigprocmask(SIG_SETMASK, array(), $oldset); pcntl_sigprocmask(SIG_SETMASK, array(), $oldset);
} }
$garbage = exec("$command 2>&1", $output, $retval); exec("$command 2>&1", $output, $retval);
if (($retval <> 0) && ($mute === false)) { if (($retval <> 0) && ($mute === false)) {
//log_error(sprintf(gettext("The command '%1\$s' returned exit code '%2\$d', the output was '%3\$s' "), implode(" ", $output); //log_error(sprintf(gettext("The command '%1\$s'
// returned exit code '%2\$d', the output was '%3\$s' "), implode(" ", $output);
// TODO: log // TODO: log
unset($output); unset($output);
} }
...@@ -101,26 +126,4 @@ class Shell ...@@ -101,26 +126,4 @@ class Shell
return null; return null;
} }
/**
* execute command or list of commands
*
* @param string/Array() $command command to execute
* @param bool $mute
* @param bool $clearsigmask
* @param Array() &$output
*/
function exec($command, $mute = false, $clearsigmask = false,&$output=null)
{
if (is_array($command)){
foreach($command as $comm ){
$this->_exec($comm,$mute, $clearsigmask ,$output);
}
}
else{
$this->_exec($command,$mute, $clearsigmask ,$output);
}
}
} }
...@@ -33,11 +33,6 @@ ...@@ -33,11 +33,6 @@
namespace OPNsense\Core; namespace OPNsense\Core;
/**
* Class Singleton
* @package Core
*/
/** /**
* Class Singleton * Class Singleton
* @package Core * @package Core
...@@ -65,7 +60,7 @@ abstract class Singleton ...@@ -65,7 +60,7 @@ abstract class Singleton
*/ */
final private function __clone() final private function __clone()
{ {
throw new \Exception("An instance of ".get_called_class()." cannot be cloned."); throw new \Exception("An instance of " . get_called_class() . " cannot be cloned.");
} }
/** /**
...@@ -76,7 +71,7 @@ abstract class Singleton ...@@ -76,7 +71,7 @@ abstract class Singleton
{ {
$className = get_called_class(); $className = get_called_class();
if(isset(self::$instances[$className]) == false) { if (isset(self::$instances[$className]) == false) {
self::$instances[$className] = new static(); self::$instances[$className] = new static();
} }
return self::$instances[$className]; return self::$instances[$className];
...@@ -88,6 +83,7 @@ abstract class Singleton ...@@ -88,6 +83,7 @@ abstract class Singleton
* so an extended class could simply * so an extended class could simply
* specify its own init * specify its own init
*/ */
protected function init(){} protected function init()
{
}
} }
...@@ -79,7 +79,7 @@ if (!empty($cpzone)) { ...@@ -79,7 +79,7 @@ if (!empty($cpzone)) {
$cpdb = $cpdb_handle->listClients(array(),"and",array($order) ) ; $cpdb = $cpdb_handle->listClients(array(),"and",array($order) ) ;
if ($_GET['showact']) { if ($_GET['showact']) {
$accounting_info = $cpclient_handle->list_accounting(); $accounting_info = $cpclient_handle->listAccounting();
} }
else { else {
$accounting_info = array() ; $accounting_info = array() ;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment