From 6e060977098fa2763154eb3567a3f9eb6ab047cf Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Fri, 5 Aug 2016 19:37:39 +0200 Subject: [PATCH 01/15] (packet capture) stream/flush output to browser, closes https://github.com/opnsense/core/issues/1116 --- src/www/diag_packet_capture.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/www/diag_packet_capture.php b/src/www/diag_packet_capture.php index beb39e33a..4f175658e 100644 --- a/src/www/diag_packet_capture.php +++ b/src/www/diag_packet_capture.php @@ -154,7 +154,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=packetcapture.cap"); header("Content-Length: ".filesize("/root/packetcapture.cap")); - readfile("/root/packetcapture.cap"); + $file = fopen("/root/packetcapture.cap", "r"); + while(!feof($file)) { + print(fread($file, 32 * 1024)); + ob_flush(); + } + fclose($file); exit; } elseif (!empty($_GET['view'])) { // download capture contents From 7bf1343bf7edc9f40e025df6c4e95afecd096242 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sat, 6 Aug 2016 09:25:22 +0200 Subject: [PATCH 02/15] IDS / crash reports, closes https://github.com/opnsense/core/issues/1117 --- .../OPNsense/IDS/Api/SettingsController.php | 14 +++++++++----- src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php | 4 ++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php b/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php index e4c111254..c564caf2c 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php @@ -147,15 +147,19 @@ class SettingsController extends ApiControllerBase /** * get rule information - * @param $sid rule identifier + * @param string|null $sid rule identifier * @return array|mixed */ - public function getRuleInfoAction($sid) + public function getRuleInfoAction($sid=null) { // request list of installed rules - $backend = new Backend(); - $response = $backend->configdpRun("ids query rules", array(1, 0,'sid/'.$sid)); - $data = json_decode($response, true); + if (!empty($sid)) { + $backend = new Backend(); + $response = $backend->configdpRun("ids query rules", array(1, 0,'sid/'.$sid)); + $data = json_decode($response, true); + } else { + $data = null; + } if ($data != null && array_key_exists("rows", $data) && count($data['rows'])>0) { $row = $data['rows'][0]; diff --git a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php index efef19fd3..dcee0ca51 100644 --- a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php +++ b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php @@ -131,7 +131,7 @@ class IDS extends BaseModel public function getRuleStatus($sid, $default) { $this->updateSIDlist(); - if (array_key_exists($sid, $this->sid_list)) { + if (!empty($sid) && array_key_exists($sid, $this->sid_list)) { return (string)$this->sid_list[$sid]->enabled; } else { return $default; @@ -148,7 +148,7 @@ class IDS extends BaseModel public function getRuleAction($sid, $default, $response_plain = false) { $this->updateSIDlist(); - if (array_key_exists($sid, $this->sid_list)) { + if (!empty($sid) && array_key_exists($sid, $this->sid_list)) { if (!$response_plain) { return $this->sid_list[$sid]->action->getNodeData(); } else { From 5ec2101ac2c67824b94306fe01d1ed97211ea730 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sun, 7 Aug 2016 16:10:19 +0200 Subject: [PATCH 03/15] (insight) check database integrity before start, repair if broken --- .../scripts/netflow/flowd_aggregate.py | 5 +- src/opnsense/site-python/sqlite3_helper.py | 69 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/opnsense/site-python/sqlite3_helper.py diff --git a/src/opnsense/scripts/netflow/flowd_aggregate.py b/src/opnsense/scripts/netflow/flowd_aggregate.py index 8915576f7..1368046ed 100755 --- a/src/opnsense/scripts/netflow/flowd_aggregate.py +++ b/src/opnsense/scripts/netflow/flowd_aggregate.py @@ -28,7 +28,6 @@ Aggregate flowd data for reporting """ import time -import datetime import os import sys import signal @@ -37,6 +36,7 @@ import copy import syslog import traceback sys.path.insert(0, "/usr/local/opnsense/site-python") +from sqlite3_helper import check_and_repair from lib.parse import parse_flow from lib.aggregate import AggMetadata import lib.aggregates @@ -130,6 +130,9 @@ class Main(object): """ run, endless loop, until sigterm is received :return: None """ + # check database consistency / repair + check_and_repair('/var/netflow/*.sqlite') + vacuum_interval = (60*60*8) # 8 hour vacuum cycle vacuum_countdown = None while self.running: diff --git a/src/opnsense/site-python/sqlite3_helper.py b/src/opnsense/site-python/sqlite3_helper.py new file mode 100644 index 000000000..6c32f7ef4 --- /dev/null +++ b/src/opnsense/site-python/sqlite3_helper.py @@ -0,0 +1,69 @@ +""" + Copyright (c) 2016 Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------------- + SQLite3 support functions +""" +import datetime +import glob +import sqlite3 +import syslog +import os + +def check_and_repair(filename_mask): + """ check and repair sqlite databases + :param filename_mask: filenames (glob pattern) + :return: None + """ + for filename in glob.glob(filename_mask): + try: + conn = sqlite3.connect(filename, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) + cur = conn.cursor() + cur.execute("SELECT name FROM sqlite_master where type = 'table'") + except sqlite3.DatabaseError: + # unrecoverable, doesn't look like a database, rename to .bck + filename_tmp = '%s.%s.bck'%(filename, datetime.datetime.now().strftime("%Y%m%d%H%M%S")) + syslog.syslog(syslog.LOG_ERR, "sqlite3 %s doesn't look like a database, rename to %s " % (filename, + filename_tmp)) + cur = None + os.rename(filename, filename_tmp) + + # try to vacuum all tables, triggers a "database disk image is malformed" when corrupted + # force a repair when corrupted, using a dump / import + if cur is not None: + try: + for table in cur.fetchall(): + cur.execute('vacuum %s' % table[0]) + except sqlite3.DatabaseError, e: + if e.message.find('malformed') > -1: + syslog.syslog(syslog.LOG_ERR, "sqlite3 repair %s" % filename) + filename_tmp = '%s.fix'%filename + if os.path.exists(filename_tmp): + os.remove(filename_tmp) + os.system('echo ".dump" | /usr/local/bin/sqlite3 %s | /usr/local/bin/sqlite3 %s' % (filename, + filename_tmp)) + if os.path.exists(filename_tmp): + os.remove(filename) + os.rename(filename_tmp, filename) From 3973a6ce8667321b0e1f54178ff55a07bf2069cb Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sun, 7 Aug 2016 18:10:23 +0200 Subject: [PATCH 04/15] (trust, csr) add optional ou field, closes https://github.com/opnsense/core/issues/1121 --- src/www/system_certmanager.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/www/system_certmanager.php b/src/www/system_certmanager.php index 6ee49e27e..70844fa1f 100644 --- a/src/www/system_certmanager.php +++ b/src/www/system_certmanager.php @@ -464,6 +464,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { 'organizationName' => $pconfig['csr_dn_organization'], 'emailAddress' => $pconfig['csr_dn_email'], 'commonName' => $pconfig['csr_dn_commonname']); + if (!empty($pconfig['csr_dn_organizationalunit'])) { + $dn['organizationalUnitName'] = $pconfig['csr_dn_organizationalunit']; + } if (count($altnames)) { $altnames_tmp = ""; foreach ($altnames as $altname) { @@ -1056,6 +1059,17 @@ $( document ).ready(function() { + + :   + + + + + :   From c43eaff4816cee89cfa2393d4ecb4e0ed014e61c Mon Sep 17 00:00:00 2001 From: Per von Zweigbergk Date: Fri, 5 Aug 2016 19:53:52 +0200 Subject: [PATCH 05/15] (Proxy) Fixed incorrect capitalization of unit names in form --- .../mvc/app/controllers/OPNsense/Proxy/forms/main.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Proxy/forms/main.xml b/src/opnsense/mvc/app/controllers/OPNsense/Proxy/forms/main.xml index 480b2527f..b71f52554 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Proxy/forms/main.xml +++ b/src/opnsense/mvc/app/controllers/OPNsense/Proxy/forms/main.xml @@ -166,25 +166,25 @@ proxy.general.traffic.maxDownloadSize - + text proxy.general.traffic.maxUploadSize - + text proxy.general.traffic.OverallBandwidthTrotteling - + text proxy.general.traffic.perHostTrotteling - + text From fdf05de617180d22459b3315fe5a328a4c1b1ae8 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sun, 7 Aug 2016 18:49:41 +0200 Subject: [PATCH 06/15] (firewall, scrub) add direction and source port. closes https://github.com/opnsense/core/issues/1087 --- src/etc/inc/filter.inc | 5 +- src/www/firewall_scrub_edit.php | 81 ++++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/src/etc/inc/filter.inc b/src/etc/inc/filter.inc index 19b250866..82111fb55 100644 --- a/src/etc/inc/filter.inc +++ b/src/etc/inc/filter.inc @@ -584,7 +584,9 @@ function filter_generate_scrubing(&$FilterIflist) if (!empty($config['filter']['scrub']['rule'])) { foreach ($config['filter']['scrub']['rule'] as $scrub_rule) { if (!isset($scrub_rule['disabled'])) { - $scrub_rule_out = "scrub on "; + $scrub_rule_out = "scrub"; + $scrub_rule_out .= !empty($scrub_rule['direction']) ? " " . $scrub_rule['direction'] : "" ; + $scrub_rule_out .= " on "; $interfaces = array(); foreach (explode(',', $scrub_rule['interface']) as $interface) { if (!empty($FilterIflist[$interface]['if'])) { @@ -603,6 +605,7 @@ function filter_generate_scrubing(&$FilterIflist) } else { $scrub_rule_out .= "any"; } + $scrub_rule_out .= !empty($scrub_rule['srcport']) ? " port " . $scrub_rule['srcport'] : ""; $scrub_rule_out .= " to "; if (is_alias($scrub_rule['dst'])) { $scrub_rule_out .= !empty($scrub_rule['dstnot']) ? "!" : ""; diff --git a/src/www/firewall_scrub_edit.php b/src/www/firewall_scrub_edit.php index d055691ce..0392e9f51 100644 --- a/src/www/firewall_scrub_edit.php +++ b/src/www/firewall_scrub_edit.php @@ -53,7 +53,8 @@ $a_scrub = &$config['filter']['scrub']['rule']; // define form fields $config_fields = array('interface', 'proto', 'srcnot', 'src', 'srcmask', 'dstnot', 'dst', 'dstmask', 'dstport', - 'no-df', 'random-id', 'max-mss', 'min-ttl', 'set-tos', 'descr', 'disabled'); + 'no-df', 'random-id', 'max-mss', 'min-ttl', 'set-tos', 'descr', 'disabled', 'direction', + 'srcport'); if ($_SERVER['REQUEST_METHOD'] === 'GET') { // input record id, if valid @@ -102,6 +103,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { if (!empty($pconfig['dstport']) && $pconfig['dstport'] != 'any' && !is_portoralias($pconfig['dstport']) && !is_portrange($pconfig['dstport'])) { $input_errors[] = sprintf(gettext("%s doesn't appear to be a valid port number, alias or range"), $pconfig['dstport']) ; } + if (!empty($pconfig['srcport']) && $pconfig['srcport'] != 'any' && !is_portoralias($pconfig['srcport']) && !is_portrange($pconfig['srcport'])) { + $input_errors[] = sprintf(gettext("%s doesn't appear to be a valid port number, alias or range"), $pconfig['srcport']) ; + } if (is_ipaddrv4($pconfig['src']) && is_ipaddrv6($pconfig['dst'])) { $input_errors[] = gettext("You can not use IPv6 addresses in IPv4 rules."); } @@ -220,15 +224,28 @@ include("head.inc"); // lock src/dst ports on other then tcp/udp if ($("#proto").val() == 'tcp' || $("#proto").val() == 'udp' || $("#proto").val() == 'tcp/udp') { $("#dstport").prop('disabled', false); + $("#srcport").prop('disabled', false); } else { $("#dstport optgroup:last option:first").prop('selected', true); $("#dstport").prop('disabled', true); + $("#srcport").prop('disabled', true); } $("#dstport").selectpicker('refresh'); $("#dstport").change(); + $("#srcport").selectpicker('refresh'); + $("#srcport").change(); }); $("#proto").change(); + if ($("#srcport").val() != "") { + $("#show_srcport").show(); + $("#show_srcport_adv").parent().hide(); + } + $("#show_srcport_adv").click(function(){ + $("#show_srcport").show(); + $("#show_srcport_adv").parent().hide(); + }); + // IPv4/IPv6 select hook_ipv4v6('ipv4v6net', 'network-id'); }); @@ -286,24 +303,22 @@ include("head.inc"); - - @@ -379,6 +394,48 @@ include("head.inc"); + + + +
+ " id="show_srcport_adv" /> +
+ + + + From b0aeb04b3f04aec18d845308aaebe8d881ee1935 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sun, 7 Aug 2016 18:50:23 +0200 Subject: [PATCH 07/15] fix typo --- src/opnsense/site-python/sqlite3_helper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opnsense/site-python/sqlite3_helper.py b/src/opnsense/site-python/sqlite3_helper.py index 6c32f7ef4..9e0ee9ef5 100644 --- a/src/opnsense/site-python/sqlite3_helper.py +++ b/src/opnsense/site-python/sqlite3_helper.py @@ -45,8 +45,8 @@ def check_and_repair(filename_mask): except sqlite3.DatabaseError: # unrecoverable, doesn't look like a database, rename to .bck filename_tmp = '%s.%s.bck'%(filename, datetime.datetime.now().strftime("%Y%m%d%H%M%S")) - syslog.syslog(syslog.LOG_ERR, "sqlite3 %s doesn't look like a database, rename to %s " % (filename, - filename_tmp)) + syslog.syslog(syslog.LOG_ERR, "sqlite3 %s doesn't look like a database, renamed to %s " % (filename, + filename_tmp)) cur = None os.rename(filename, filename_tmp) From 84b0488810565ae5306fa8211baf4369fc4931fc Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Sun, 7 Aug 2016 19:08:07 +0200 Subject: [PATCH 08/15] vpn: improve client links visibility PR: https://forum.opnsense.org/index.php?topic=3480.0 --- src/www/vpn_openvpn_export.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/www/vpn_openvpn_export.php b/src/www/vpn_openvpn_export.php index f2bf85ca2..8a7ca8fdc 100644 --- a/src/www/vpn_openvpn_export.php +++ b/src/www/vpn_openvpn_export.php @@ -559,9 +559,6 @@ if (isset($savemsg)) { - -   - @@ -701,18 +698,21 @@ if (isset($savemsg)) { + + + + -
+ -
+ -
+ -
+ : or -
+ - + + From 8b191e827d07f12aac4512bf15a502e00f86a26c Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Sun, 7 Aug 2016 19:23:15 +0200 Subject: [PATCH 09/15] services: fix a crash report in load balancer --- src/www/load_balancer_pool_edit.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/www/load_balancer_pool_edit.php b/src/www/load_balancer_pool_edit.php index 1cfd73636..5441979c2 100644 --- a/src/www/load_balancer_pool_edit.php +++ b/src/www/load_balancer_pool_edit.php @@ -352,10 +352,12 @@ include("head.inc");
From 29975dc05402731bd5aa9ffdad1a593696fafd34 Mon Sep 17 00:00:00 2001 From: Per von Zweigbergk Date: Sun, 7 Aug 2016 21:11:44 +0200 Subject: [PATCH 10/15] (base) Create ApiModelControllerBase class for ease of implementing API getters --- .../OPNsense/Base/ApiModelControllerBase.php | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php new file mode 100644 index 000000000..62c461cae --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php @@ -0,0 +1,61 @@ +request->isGet()) { + $mdl = $this->getModel(); + $result[$this->getModelName()] = $this->getModelNodes($mdl); + } + return $result; + } + abstract protected function getModel(); + abstract protected function getModelName(); + /** + * override this to customize what part of the model gets exposed + */ + protected function getModelNodes($mdl) { + return $mdl->getNodes(); + } +} From 7e695081778717984aece544bb176a20e41a1c87 Mon Sep 17 00:00:00 2001 From: Per von Zweigbergk Date: Sun, 7 Aug 2016 21:12:31 +0200 Subject: [PATCH 11/15] (base) Create ApiMutableModelControllerBase class for ease of implementing API setters --- .../Base/ApiMutableModelControllerBase.php | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php new file mode 100644 index 000000000..5a17f0031 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php @@ -0,0 +1,69 @@ +"failed"); + if ($this->request->isPost()) { + // load model and update with provided data + $mdl = $this->getModel(); + $mdl->setNodes($this->request->getPost(getModelName())); + + // perform validation + $valMsgs = $mdl->performValidation(); + foreach ($valMsgs as $field => $msg) { + if (!array_key_exists("validations", $result)) { + $result["validations"] = array(); + } + $result["validations"][$this->getModelName().".".$msg->getField()] = $msg->getMessage(); + } + + // serialize model to config and save + if ($valMsgs->count() == 0) { + $mdl->serializeToConfig(); + Config::getInstance()->save(); + $result["result"] = "saved"; + } + } + return $result; + } +} From ecdcc4b736b7a4216b4a83c057e9835b45fb8469 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Mon, 8 Aug 2016 09:04:51 +0200 Subject: [PATCH 12/15] plugins: tweak interface plugging PPPoE wasn't removed, which led to some refactoring to find out why. The outcome is the same, but works a little bit different now. While there, make it possible to omit the config write in case we are going to call write_config() shortly after anyway. This will also be necessary for the legacy VPN plugins. --- src/etc/inc/plugins.inc | 37 ++++++++++++++++++------------ src/www/interfaces_groups.php | 2 +- src/www/interfaces_groups_edit.php | 2 +- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/etc/inc/plugins.inc b/src/etc/inc/plugins.inc index 7ccce476e..a7a63a598 100644 --- a/src/etc/inc/plugins.inc +++ b/src/etc/inc/plugins.inc @@ -94,11 +94,21 @@ function plugins_syslog() * Every _interface should return a named array containing the interface unique identifier and properties. * */ -function plugins_interfaces() +function plugins_interfaces($write_config = true) { global $config; - $changed_interfaces = array(); - $registered_interfaces = array(); + + $stale_interfaces = array(); + $write_required = false; + + // mark previous dynamic registrations stale + if (isset($config['interfaces'])) { + foreach ($config['interfaces'] as $intf_ref => $intf_data) { + if (isset($intf_data[0]['internal_dynamic']) || isset($intf_data['internal_dynamic'])) { + $stale_interfaces[$intf_ref] = 1; + } + } + } // register / update interfaces foreach (plugins_scan() as $name => $path) { @@ -107,8 +117,9 @@ function plugins_interfaces() if (function_exists($func)) { foreach ($func() as $intf_ref => $intf_data) { if (is_array($intf_data)) { - if (!in_array($intf_ref, $registered_interfaces)) { - $registered_interfaces[] = $intf_ref; + // mark interface used + if (isset($stale_interfaces[$intf_ref])) { + unset($stale_interfaces[$intf_ref]); } if (empty($config['interfaces'][$intf_ref])) { $config['interfaces'][$intf_ref] = array(); @@ -124,9 +135,7 @@ function plugins_interfaces() foreach ($intf_data as $prop_name => $prop_value) { if ((empty($intf_config[$prop_name]) && !empty($prop_value)) || $intf_config[$prop_name] != $prop_value) { $intf_config[$prop_name] = $prop_value; - if (!in_array($intf_ref, $changed_interfaces)) { - $changed_interfaces[] = $intf_ref; - } + $write_required = true; } } } @@ -135,17 +144,15 @@ function plugins_interfaces() } // cleanup registrations - if (isset($config['interfaces'])) { - foreach ($config['interfaces'] as $intf => $intf_data) { - if (!empty($intf_data['internal_dynamic']) && !in_array($intf, $registered_interfaces)) { - $changed_interfaces[] = $intf; - unset($config['interfaces'][$intf]); - } + foreach ($stale_interfaces as $intf_ref => $no_data) { + if (isset($config['interfaces'][$intf_ref])) { + unset($config['interfaces'][$intf_ref]); + $write_required = true; } } // configuration changed, materialize - if (count($changed_interfaces) > 0) { + if ($write_config && $write_required) { write_config(); } } diff --git a/src/www/interfaces_groups.php b/src/www/interfaces_groups.php index ff08fc21e..5ffebd400 100644 --- a/src/www/interfaces_groups.php +++ b/src/www/interfaces_groups.php @@ -53,8 +53,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } unset($a_ifgroups[$id]); + plugins_interfaces(false); write_config(); - plugins_interfaces(); header("Location: interfaces_groups.php"); exit; } diff --git a/src/www/interfaces_groups_edit.php b/src/www/interfaces_groups_edit.php index c9ba3f079..6e1fab074 100644 --- a/src/www/interfaces_groups_edit.php +++ b/src/www/interfaces_groups_edit.php @@ -125,9 +125,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { // add new item $a_ifgroups[] = $ifgroupentry; } + plugins_interfaces(false); write_config(); interface_group_setup($ifgroupentry); - plugins_interfaces(); header("Location: interfaces_groups.php"); exit; } From 3235ee26906c1178cff3cb433bd81655a22802ad Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Mon, 8 Aug 2016 09:57:19 +0200 Subject: [PATCH 13/15] plugins: rename variable to better reflect its purpose --- src/etc/inc/plugins.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etc/inc/plugins.inc b/src/etc/inc/plugins.inc index a7a63a598..87e926396 100644 --- a/src/etc/inc/plugins.inc +++ b/src/etc/inc/plugins.inc @@ -94,7 +94,7 @@ function plugins_syslog() * Every _interface should return a named array containing the interface unique identifier and properties. * */ -function plugins_interfaces($write_config = true) +function plugins_interfaces($write_allowed = true) { global $config; @@ -152,7 +152,7 @@ function plugins_interfaces($write_config = true) } // configuration changed, materialize - if ($write_config && $write_required) { + if ($write_allowed && $write_required) { write_config(); } } From 7a67a2c03d07559c929d817aea28b7abd1edf8d0 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Mon, 8 Aug 2016 10:47:40 +0200 Subject: [PATCH 14/15] (mvc) some refactoring for https://github.com/opnsense/core/pull/1124 --- .../OPNsense/Base/ApiModelControllerBase.php | 61 +++++++++++++++++-- .../Base/ApiMutableModelControllerBase.php | 11 +++- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php index 62c461cae..a349ecd9a 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiModelControllerBase.php @@ -1,6 +1,7 @@ internalModelClass)) { + throw new \Exception('cannot instantiate without internalModelClass defined.'); + } + if (empty($this->internalModelName)) { + throw new \Exception('cannot instantiate without internalModelName defined.'); + } + } + + /** + * retrieve model settings + * @return array settings + */ public function getAction() { // define list of configurable settings $result = array(); if ($this->request->isGet()) { $mdl = $this->getModel(); - $result[$this->getModelName()] = $this->getModelNodes($mdl); + $result[$this->internalModelName] = $this->getModelNodes(); } return $result; } - abstract protected function getModel(); - abstract protected function getModelName(); + /** * override this to customize what part of the model gets exposed + * @return array */ - protected function getModelNodes($mdl) { - return $mdl->getNodes(); + protected function getModelNodes() + { + return $this->getModel()->getNodes(); + } + + /** + * override this to customize the model binding behavior + * @return null|BaseModel + */ + protected function getModel() + { + if ($this->modelHandle == null) { + $this->modelHandle = (new \ReflectionClass($this->internalModelClass))->newInstance(); + } + + return $this->modelHandle; } } diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php index 5a17f0031..412116904 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php @@ -1,6 +1,7 @@ "failed"); if ($this->request->isPost()) { // load model and update with provided data $mdl = $this->getModel(); - $mdl->setNodes($this->request->getPost(getModelName())); + $mdl->setNodes($this->request->getPost($this->internalModelName)); // perform validation $valMsgs = $mdl->performValidation(); @@ -54,7 +59,7 @@ abstract class ApiMutableModelControllerBase extends ApiModelControllerBase if (!array_key_exists("validations", $result)) { $result["validations"] = array(); } - $result["validations"][$this->getModelName().".".$msg->getField()] = $msg->getMessage(); + $result["validations"][$this->internalModelName.".".$msg->getField()] = $msg->getMessage(); } // serialize model to config and save From beff7772aa40c141619c075bc509337461f1a4bb Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Mon, 8 Aug 2016 11:04:54 +0200 Subject: [PATCH 15/15] (proxy) extend ApiMutableModelControllerBase --- .../OPNsense/Proxy/Api/SettingsController.php | 70 +++---------------- 1 file changed, 11 insertions(+), 59 deletions(-) diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/SettingsController.php b/src/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/SettingsController.php index 41c3c1d4a..94d14328a 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/SettingsController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/SettingsController.php @@ -28,8 +28,7 @@ */ namespace OPNsense\Proxy\Api; -use \OPNsense\Base\ApiControllerBase; -use \OPNsense\Proxy\Proxy; +use \OPNsense\Base\ApiMutableModelControllerBase; use \OPNsense\Cron\Cron; use \OPNsense\Core\Config; use \OPNsense\Base\UIModelGrid; @@ -38,57 +37,10 @@ use \OPNsense\Base\UIModelGrid; * Class SettingsController * @package OPNsense\Proxy */ -class SettingsController extends ApiControllerBase +class SettingsController extends ApiMutableModelControllerBase { - /** - * retrieve proxy settings - * @return array - */ - public function getAction() - { - $result = array(); - if ($this->request->isGet()) { - $mdlProxy = new Proxy(); - $result['proxy'] = $mdlProxy->getNodes(); - } - - return $result; - } - - - /** - * update proxy configuration fields - * @return array - * @throws \Phalcon\Validation\Exception - */ - public function setAction() - { - $result = array("result"=>"failed"); - if ($this->request->hasPost("proxy")) { - // load model and update with provided data - $mdlProxy = new Proxy(); - $mdlProxy->setNodes($this->request->getPost("proxy")); - - // perform validation - $valMsgs = $mdlProxy->performValidation(); - foreach ($valMsgs as $field => $msg) { - if (!array_key_exists("validations", $result)) { - $result["validations"] = array(); - } - $result["validations"]["proxy.".$msg->getField()] = $msg->getMessage(); - } - - // serialize model to config and save - if ($valMsgs->count() == 0) { - $mdlProxy->serializeToConfig(); - $cnf = Config::getInstance(); - $cnf->save(); - $result["result"] = "saved"; - } - } - - return $result; - } + protected $internalModelName = 'proxy'; + protected $internalModelClass = '\OPNsense\Proxy\Proxy'; /** * @@ -98,7 +50,7 @@ class SettingsController extends ApiControllerBase public function searchRemoteBlacklistsAction() { $this->sessionClose(); - $mdlProxy = new Proxy(); + $mdlProxy = $this->getModel(); $grid = new UIModelGrid($mdlProxy->forward->acl->remoteACLs->blacklists->blacklist); return $grid->fetchBindRequest( $this->request, @@ -114,7 +66,7 @@ class SettingsController extends ApiControllerBase */ public function getRemoteBlacklistAction($uuid = null) { - $mdlProxy = new Proxy(); + $mdlProxy = $this->getModel(); if ($uuid != null) { $node = $mdlProxy->getNodeByReference('forward.acl.remoteACLs.blacklists.blacklist.' . $uuid); if ($node != null) { @@ -139,7 +91,7 @@ class SettingsController extends ApiControllerBase public function setRemoteBlacklistAction($uuid) { if ($this->request->isPost() && $this->request->hasPost("blacklist")) { - $mdlProxy = new Proxy(); + $mdlProxy = $this->getModel(); if ($uuid != null) { $node = $mdlProxy->getNodeByReference('forward.acl.remoteACLs.blacklists.blacklist.' . $uuid); if ($node != null) { @@ -175,7 +127,7 @@ class SettingsController extends ApiControllerBase $result = array("result" => "failed"); if ($this->request->isPost() && $this->request->hasPost("blacklist")) { $result = array("result" => "failed", "validations" => array()); - $mdlProxy = new Proxy(); + $mdlProxy = $this->getModel(); $node = $mdlProxy->forward->acl->remoteACLs->blacklists->blacklist->Add(); $node->setNodes($this->request->getPost("blacklist")); $valMsgs = $mdlProxy->performValidation(); @@ -207,7 +159,7 @@ class SettingsController extends ApiControllerBase $result = array("result" => "failed"); if ($this->request->isPost()) { - $mdlProxy = new Proxy(); + $mdlProxy = $this->getModel(); if ($uuid != null) { if ($mdlProxy->forward->acl->remoteACLs->blacklists->blacklist->del($uuid)) { // if item is removed, serialize to config and save @@ -233,7 +185,7 @@ class SettingsController extends ApiControllerBase $result = array("result" => "failed"); if ($this->request->isPost()) { - $mdlProxy = new Proxy(); + $mdlProxy = $this->getModel(); if ($uuid != null) { $node = $mdlProxy->getNodeByReference('forward.acl.remoteACLs.blacklists.blacklist.' . $uuid); if ($node != null) { @@ -262,7 +214,7 @@ class SettingsController extends ApiControllerBase $result = array("result" => "failed"); if ($this->request->isPost()) { - $mdlProxy = new Proxy(); + $mdlProxy = $this->getModel(); if ((string)$mdlProxy->forward->acl->remoteACLs->UpdateCron == "") { $mdlCron = new Cron(); // update cron relation (if this doesn't break consistency)