diff --git a/plist b/plist index a5a732168..eda839f9b 100644 --- a/plist +++ b/plist @@ -383,10 +383,13 @@ /usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/forms/general.xml /usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/forms/services.xml /usr/local/opnsense/mvc/app/controllers/OPNsense/Monit/forms/tests.xml +/usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/Api/ClientOverwritesController.php /usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/Api/ExportController.php /usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/Api/ServiceController.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/ClientOverwritesController.php /usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/ExportController.php /usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/StatusController.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/forms/dialogCSO.xml /usr/local/opnsense/mvc/app/controllers/OPNsense/OpenVPN/forms/export_options.xml /usr/local/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/ServiceController.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Proxy/Api/SettingsController.php @@ -645,6 +648,10 @@ /usr/local/opnsense/mvc/app/models/OPNsense/Ntpd/Menu/Menu.xml /usr/local/opnsense/mvc/app/models/OPNsense/OpenVPN/Export.php /usr/local/opnsense/mvc/app/models/OPNsense/OpenVPN/Export.xml +/usr/local/opnsense/mvc/app/models/OPNsense/OpenVPN/FieldTypes/OpenVPNServerField.php +/usr/local/opnsense/mvc/app/models/OPNsense/OpenVPN/Migrations/M1_0_0.php +/usr/local/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.php +/usr/local/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.xml /usr/local/opnsense/mvc/app/models/OPNsense/Proxy/ACL/ACL.xml /usr/local/opnsense/mvc/app/models/OPNsense/Proxy/Menu/Menu.xml /usr/local/opnsense/mvc/app/models/OPNsense/Proxy/Migrations/M1_0_0.php @@ -721,6 +728,7 @@ /usr/local/opnsense/mvc/app/views/OPNsense/Interface/vxlan.volt /usr/local/opnsense/mvc/app/views/OPNsense/Monit/index.volt /usr/local/opnsense/mvc/app/views/OPNsense/Monit/status.volt +/usr/local/opnsense/mvc/app/views/OPNsense/OpenVPN/cso.volt /usr/local/opnsense/mvc/app/views/OPNsense/OpenVPN/export.volt /usr/local/opnsense/mvc/app/views/OPNsense/OpenVPN/status.volt /usr/local/opnsense/mvc/app/views/OPNsense/Proxy/index.volt @@ -1999,7 +2007,6 @@ /usr/local/www/vpn_ipsec_phase2.php /usr/local/www/vpn_ipsec_settings.php /usr/local/www/vpn_openvpn_client.php -/usr/local/www/vpn_openvpn_csc.php /usr/local/www/vpn_openvpn_server.php /usr/local/www/widgets/api/get.php /usr/local/www/widgets/api/plugins/interfaces.inc diff --git a/src/etc/inc/plugins.inc.d/openvpn.inc b/src/etc/inc/plugins.inc.d/openvpn.inc index c74abd2e1..6a347e510 100644 --- a/src/etc/inc/plugins.inc.d/openvpn.inc +++ b/src/etc/inc/plugins.inc.d/openvpn.inc @@ -1043,38 +1043,6 @@ function openvpn_csc_conf_write($settings, $server, $target_filename = null) } } -/** - * Construct a single array containing all client specific overrides per server and common name - * @return array [vpnid][common_name] = settings - */ -function openvpn_fetch_csc_list() -{ - global $config; - $result = array(); - if (!empty($config['openvpn']['openvpn-csc'])) { - $all_servers = array_keys(openvpn_get_remote_access_servers()); - foreach ($config['openvpn']['openvpn-csc'] as $settings) { - if (!isset($settings['disable'])) { - if (!empty($settings['ovpn_servers'])) { - $ovpn_servers = explode(',', $settings['ovpn_servers']); - } else { - $ovpn_servers = $all_servers; - } - foreach ($ovpn_servers as $vpnid) { - if (in_array($vpnid, $all_servers)) { - $vpnid = filter_var($vpnid, FILTER_SANITIZE_NUMBER_INT); - if (!isset($result[$vpnid])) { - $result[$vpnid] = array(); - } - $result[$vpnid][$settings['common_name']] = $settings; - } - } - } - } - } - return $result; -} - function openvpn_prepare($device) { global $config; diff --git a/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/Api/ClientOverwritesController.php b/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/Api/ClientOverwritesController.php new file mode 100644 index 000000000..b8f971837 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/Api/ClientOverwritesController.php @@ -0,0 +1,70 @@ +searchBase( + 'Overwrites.Overwrite', + ['description', 'common_name', 'enabled', 'tunnel_network', 'tunnel_networkv6'] + ); + } + public function getAction($uuid = null) + { + return $this->getBase('cso', 'Overwrites.Overwrite', $uuid); + } + public function addAction() + { + return $this->addBase('cso', 'Overwrites.Overwrite'); + } + public function setAction($uuid = null) + { + return $this->setBase('cso', 'Overwrites.Overwrite', $uuid); + } + public function delAction($uuid) + { + return $this->delBase('Overwrites.Overwrite', $uuid); + } + public function toggleAction($uuid, $enabled = null) + { + return $this->toggleBase('Overwrites.Overwrite', $uuid, $enabled); + } +} \ No newline at end of file diff --git a/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/ClientOverwritesController.php b/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/ClientOverwritesController.php new file mode 100644 index 000000000..d3d4007bb --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/ClientOverwritesController.php @@ -0,0 +1,48 @@ +view->pick('OPNsense/OpenVPN/cso'); + $this->view->formDialogCSO = $this->getForm('dialogCSO'); + } +} diff --git a/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/forms/dialogCSO.xml b/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/forms/dialogCSO.xml new file mode 100644 index 000000000..e703e2159 --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/OpenVPN/forms/dialogCSO.xml @@ -0,0 +1,148 @@ + + + header + + + + cso.enabled + + checkbox + + + cso.servers + + select_multiple + Select the OpenVPN servers where this override applies to, leave empty for all + + + cso.description + + text + You may enter a description here for your reference (not parsed). + + + cso.common_name + + text + Enter the client's X.509 common name here. + + + cso.block + + checkbox + + Block this client connection based on its common name. + Don't use this option to permanently disable a client due to a compromised key or password. Use a CRL (certificate revocation list) instead. + + + + cso.push_reset + + checkbox + + Don't inherit the global push list for a specific client instance. + NOTE: --push-reset is very thorough: it will remove almost all options from the list of to-be-pushed options. + In many cases, some of these options will need to be re-configured afterwards - specifically, --topology subnet + and --route-gateway will get lost and this will break client configs in many cases. + + true + + + header + + + + cso.tunnel_network + + text + Push virtual IP endpoints for client tunnel, overriding dynamic allocation. + + + cso.tunnel_networkv6 + + text + Push virtual IP endpoints for client tunnel, overriding dynamic allocation. + + + cso.local_networks + + select_multiple + + true + These are the networks accessible by the client, these are pushed via route{-ipv6} clauses in OpenVPN to the client. + + + cso.remote_networks + + select_multiple + + true + + Remote networks for the server, these are configured via iroute{-ipv6} clauses in OpenVPN and inform the server to send these networks to this specific client. + + + + cso.redirect_gateway + + select_multiple + Automatically execute routing commands to cause all outgoing IP traffic to be redirected over the VPN. + + + header + + true + + + cso.register_dns + + checkbox + Run ipconfig /flushdns and ipconfig /registerdns on connection initiation. This is known to kick Windows into recognizing pushed DNS servers. + + + cso.dns_domain + + text + Set Connection-specific DNS Suffix. + + + cso.dns_domain_search + + select_multiple + + true + + Add name to the domain search list. Repeat this option to add more entries. Up to 10 domains are supported + + + + cso.dns_servers + + select_multiple + + true + + Set primary domain name server IPv4 or IPv6 address. Repeat this option to set secondary DNS server addresses. + + + + cso.ntp_servers + + select_multiple + + true + + Set primary NTP server address (Network Time Protocol). Repeat this option to set secondary NTP server addresses. + + + + cso.wins_servers + + select_multiple + + true + true + + Set primary WINS server address (NetBIOS over TCP/IP Name Server). Repeat this option to set secondary WINS server addresses. + + + \ No newline at end of file diff --git a/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml b/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml index f36a88628..f63940b40 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml +++ b/src/opnsense/mvc/app/models/OPNsense/Core/ACL/ACL.xml @@ -741,7 +741,8 @@ VPN: OpenVPN: Client Specific Override - vpn_openvpn_csc.php* + ui/openvpn/client_overwrites + api/openvpn/client_overwrites/* diff --git a/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml b/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml index 574923f60..e017f29a0 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml +++ b/src/opnsense/mvc/app/models/OPNsense/Core/Menu/Menu.xml @@ -211,9 +211,7 @@ - - - + diff --git a/src/opnsense/mvc/app/models/OPNsense/OpenVPN/FieldTypes/OpenVPNServerField.php b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/FieldTypes/OpenVPNServerField.php new file mode 100644 index 000000000..f78948275 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/FieldTypes/OpenVPNServerField.php @@ -0,0 +1,60 @@ +object()->openvpn) && + isset(Config::getInstance()->object()->openvpn->$ref) + ) { + foreach (Config::getInstance()->object()->openvpn->$ref as $server) { + $label = (string)$server->description ?? ''; + $label .= ' ( ' . (string)$server->local_port . ' / ' . (string)$server->protocol . ' )'; + self::$internalCacheOptionList[(string)$server->vpnid] = $label; + } + } + natcasesort(self::$internalCacheOptionList); + } + $this->internalOptionList = self::$internalCacheOptionList; + } +} diff --git a/src/opnsense/mvc/app/models/OPNsense/OpenVPN/Migrations/M1_0_0.php b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/Migrations/M1_0_0.php new file mode 100644 index 000000000..e3a139fd9 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/Migrations/M1_0_0.php @@ -0,0 +1,116 @@ +object(); + if (!empty($cfgObj->openvpn) && !empty($cfgObj->openvpn->{'openvpn-csc'})) { + foreach ($cfgObj->openvpn->{'openvpn-csc'} as $csc) { + $record = $model->Overwrites->Overwrite->Add(); + $record->enabled = empty((string)$csc->disable) ? '1' : '0'; + if (!empty((string)$csc->ovpn_servers)) { + $record->servers = (string)$csc->ovpn_servers; + } + $record->common_name = (string)$csc->common_name; + $record->description = (string)$csc->description; + if ($this->valid_net((string)$csc->tunnel_network)) { + $record->tunnel_network = (string)$csc->tunnel_network; + } + if ($this->valid_net((string)$csc->tunnel_networkv6)) { + $record->tunnel_networkv6 = (string)$csc->tunnel_networkv6; + } + foreach (['local', 'remote'] as $type) { + $nets = []; + $f1 = $type . '_network'; + $f2 = $type . '_networkv6'; + foreach (explode(',', (string)$csc->$f1 . ',' . (string)$csc->$f2) as $item) { + if (trim($item) != '' && $this->valid_net($item)) { + $nets[] = trim($item); + } + } + $record->{$type.'_networks'} = implode(',', $nets); + } + if (!empty((string)$csc->gwredir)) { + $record->redirect_gateway = 'def1'; + } + $record->push_reset = !empty((string)$csc->push_reset) ? '1' : '0'; + $record->block = !empty((string)$csc->block) ? '1' : '0'; + $record->dns_domain = (string)$csc->dns_domain; + $record->dns_domain_search = (string)$csc->dns_domain_search; + foreach (['dns_server', 'ntp_server', 'wins_server'] as $fieldname) { + $items = []; + for ($i=1 ; $i <= 4; ++$i) { + $fname = $fieldname . $i; + if (!empty((string)$csc->$fname)){ + $items[] = (string)$csc->$fname; + } + } + $record->{$fieldname . 's'} = implode(',', $items); + } + } + } + } + } + + /** + * cleanup old config after config save + * @param $model + */ + public function post($model) + { + if ($model instanceof OpenVPN) { + $cfgObj = Config::getInstance()->object(); + unset($cfgObj->openvpn->{'openvpn-csc'}); + } + } +} diff --git a/src/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.php b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.php new file mode 100644 index 000000000..a3f864a32 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.php @@ -0,0 +1,94 @@ +Overwrites->Overwrite->iterateItems() as $cso) { + if (empty((string)$cso->enabled)) { + continue; + } + $servers = !empty((string)$cso->servers) ? explode(',', (string)$cso->servers) : []; + if (!empty($servers) && !in_array($server_id, $servers)) { + continue; + } + if ((string)$cso->common_name != $common_name) { + continue; + } + // translate content to legacy format so this may easily inject into the existing codebase + $result['ovpn_servers'] = (string)$cso->servers; + $result['common_name'] = (string)$cso->common_name; + $result['description'] = (string)$cso->description; + + $result['tunnel_network'] = (string)$cso->tunnel_network; + $result['tunnel_networkv6'] = (string)$cso->tunnel_networkv6; + foreach (['local', 'remote'] as $type) { + $f1 = $type . '_network'; + $f2 = $type . '_networkv6'; + foreach (explode(',', (string)$cso->{$type.'_networks'}) as $item) { + if (strpos($item, ":") === false) { + $target_fieldname = $f1; + } else { + $target_fieldname = $f2; + } + if (!isset($result[$target_fieldname])) { + $result[$target_fieldname] = $item; + } else { + $result[$target_fieldname] .= "," . $item; + } + } + } + if (!empty((string)$cso->push_reset)){ + $result['push_reset'] = '1'; + } + if (!empty((string)$cso->block)){ + $result['block'] = '1'; + } + $result['dns_domain'] = (string)$cso->dns_domain; + $result['dns_domain_search'] = (string)$cso->dns_domain_search; + foreach (['dns_server', 'ntp_server', 'wins_server'] as $fieldname) { + if (!empty((string)$cso->$fieldname . 's')) { + foreach (explode(',', (string)$cso->{$fieldname . 's'}) as $idx => $item) { + $result[$fieldname. (string)($idx+1)] = $item; + } + } + } + } + return $result; + } +} diff --git a/src/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.xml b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.xml new file mode 100644 index 000000000..d59e959a6 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/OpenVPN/OpenVPN.xml @@ -0,0 +1,97 @@ + + //OPNsense/OpenVPN + 1.0.0 + OpenVPN + + + + + 1 + Y + + + N + Y + + + Y + + + 0 + Y + + + 0 + Y + + + Y + N + ipv4 + + + Y + N + ipv6 + + + , + N + Y + + + , + N + Y + + + N + Y + + local + autolocal + default + bypass dhcp + bypass dns + block local + ipv6 (default) + not ipv4 (default) + + + + 0 + Y + + + N + + + N + , + Y + + + N + N + , + Y + + + N + N + , + Y + + + N + N + , + Y + + + N + + + + + diff --git a/src/opnsense/mvc/app/views/OPNsense/OpenVPN/cso.volt b/src/opnsense/mvc/app/views/OPNsense/OpenVPN/cso.volt new file mode 100644 index 000000000..5872c9974 --- /dev/null +++ b/src/opnsense/mvc/app/views/OPNsense/OpenVPN/cso.volt @@ -0,0 +1,97 @@ +{# + # Copyright (c) 2023 Deciso B.V. + # 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. + #} + + + + + +
+
+ + + + + + + + + + + + + + + + + + + +
{{ lang._('ID') }}{{ lang._('Enabled') }}{{ lang._('Common name') }}{{ lang._('Tunnel Network') }}{{ lang._('Description') }}{{ lang._('Commands') }}
+ + +
+
+ +
+
+
+
+ +{{ partial("layout_partials/base_dialog",['fields':formDialogCSO,'id':'DialogCSO','label':lang._('Edit CSO')])}} \ No newline at end of file diff --git a/src/opnsense/scripts/openvpn/client_connect.php b/src/opnsense/scripts/openvpn/client_connect.php index 6d8de3118..4e63dfa3b 100755 --- a/src/opnsense/scripts/openvpn/client_connect.php +++ b/src/opnsense/scripts/openvpn/client_connect.php @@ -41,11 +41,9 @@ if (isset($config['openvpn']['openvpn-server'])) { if ($server['vpnid'] == $vpnid) { // XXX: Eventually we should move the responsibility to determine if we do want to write a file // to here instead of the configuration file (always call event, filter relevant). - $all_cso = openvpn_fetch_csc_list(); - if (!empty($all_cso[$vpnid][$common_name])) { - $cso = $all_cso[$vpnid][$common_name]; - } else { - $cso = ["common_name" => $common_name]; + $cso = (new OPNsense\OpenVPN\OpenVPN())->getOverwrite($vpnid, $common_name); + if (empty($cso)) { + $cso = array("common_name" => $common_name); } if (!empty($config_file)) { $cso_filename = openvpn_csc_conf_write($cso, $server, $config_file); diff --git a/src/opnsense/scripts/openvpn/user_pass_verify.php b/src/opnsense/scripts/openvpn/user_pass_verify.php index 3fb4be2c8..69702786b 100755 --- a/src/opnsense/scripts/openvpn/user_pass_verify.php +++ b/src/opnsense/scripts/openvpn/user_pass_verify.php @@ -137,12 +137,9 @@ function do_auth($common_name, $serverid, $method, $auth_file) if ($authenticator->authenticate($username, $password)) { $vpnid = filter_var($a_server['vpnid'], FILTER_SANITIZE_NUMBER_INT); // fetch or create client specif override - $all_cso = openvpn_fetch_csc_list(); $common_name = empty($a_server['cso_login_matching']) ? $common_name : $username; - $login_type = empty($a_server['cso_login_matching']) ? "CN" : "USER"; - if (!empty($all_cso[$vpnid][$common_name])) { - $cso = $all_cso[$vpnid][$common_name]; - } else { + $cso = (new OPNsense\OpenVPN\OpenVPN())->getOverwrite($vpnid, $common_name); + if (empty($cso)) { $cso = array("common_name" => $common_name); } diff --git a/src/www/vpn_openvpn_csc.php b/src/www/vpn_openvpn_csc.php deleted file mode 100644 index d441e8787..000000000 --- a/src/www/vpn_openvpn_csc.php +++ /dev/null @@ -1,787 +0,0 @@ - - * 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. - */ - -require_once("guiconfig.inc"); -require_once("interfaces.inc"); -require_once("plugins.inc.d/openvpn.inc"); - -$all_form_fields = "custom_options,disable,common_name,block,description - ,tunnel_network,tunnel_networkv6,local_network,local_networkv6,remote_network - ,remote_networkv6,gwredir,push_reset,dns_domain,dns_domain_search,dns_server1 - ,dns_server2,dns_server3,dns_server4,ntp_server1,ntp_server2 - ,netbios_enable,netbios_ntype,netbios_scope,wins_server1 - ,wins_server2,ovpn_servers"; - -$a_csc = &config_read_array('openvpn', 'openvpn-csc'); -$vpnid = 0; -$act = null; - -if ($_SERVER['REQUEST_METHOD'] === 'GET') { - $pconfig = array(); - if (isset($_GET['dup']) && isset($a_csc[$_GET['dup']])) { - $configId = $_GET['dup']; - } elseif (isset($_GET['id']) && isset($a_csc[$_GET['id']])) { - $id = $_GET['id']; - $configId = $id; - } - - if (isset($_GET['act'])) { - $act = $_GET['act']; - } - - // 1 on 1 copy of config attributes - foreach (explode(",", $all_form_fields) as $fieldname) { - $fieldname = trim($fieldname); - if (isset($a_csc[$configId][$fieldname])) { - $pconfig[$fieldname] = $a_csc[$configId][$fieldname]; - } elseif (!isset($pconfig[$fieldname])) { - // initialize element - $pconfig[$fieldname] = null; - } - } - // servers => array - $pconfig['ovpn_servers'] = empty($pconfig['ovpn_servers']) ? array() : explode(',', $pconfig['ovpn_servers']); -} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { - $input_errors = array(); - $pconfig = $_POST; - if (isset($_POST['act'])) { - $act = $_POST['act']; - } - if (isset($_POST['id']) && isset($a_csc[$_POST['id']])) { - $id = $_POST['id']; - } - - if ($act == "del") { - if (isset($id)) { - unset($a_csc[$id]); - write_config(); - } - header(url_safe('Location: /vpn_openvpn_csc.php')); - exit; - } elseif ($act == "del_x") { - if (!empty($pconfig['rule']) && is_array($pconfig['rule'])) { - foreach ($pconfig['rule'] as $rulei) { - if (isset($a_csc[$rulei])) { - unset($a_csc[$rulei]); - } - } - write_config(); - } - header(url_safe('Location: /vpn_openvpn_csc.php')); - exit; - } elseif ($act == "move"){ - // move selected items - if (!isset($id)) { - // if id not set/found, move to end - $id = count($a_csc); - } - $a_csc = legacy_move_config_list_items($a_csc, $id, $pconfig['rule']); - write_config(); - header(url_safe('Location: /vpn_openvpn_csc.php')); - exit; - } elseif ($act == "toggle") { - if (isset($id)) { - if (isset($a_csc[$id]['disable'])) { - unset($a_csc[$id]['disable']); - } else { - $a_csc[$id]['disable'] = true; - } - write_config(); - } - header(url_safe('Location: /vpn_openvpn_csc.php')); - exit; - } else { - if ($result = openvpn_validate_cidr($pconfig['tunnel_network'], gettext('IPv4 Tunnel Network'), false, 'ipv4')) { - $input_errors[] = $result; - } - if ($result = openvpn_validate_cidr($pconfig['tunnel_networkv6'], gettext('IPv6 Tunnel Network'), false, 'ipv6')) { - $input_errors[] = $result; - } - if ($result = openvpn_validate_cidr($pconfig['local_network'], gettext('IPv4 Local Network'), true, 'ipv4')) { - $input_errors[] = $result; - } - if ($result = openvpn_validate_cidr($pconfig['local_networkv6'], gettext('IPv6 Local Network'), true, 'ipv6')) { - $input_errors[] = $result; - } - if ($result = openvpn_validate_cidr($pconfig['remote_network'], gettext('IPv4 Remote Network'), true, 'ipv4')) { - $input_errors[] = $result; - } - if ($result = openvpn_validate_cidr($pconfig['remote_networkv6'], gettext('IPv6 Remote Network'), true, 'ipv6')) { - $input_errors[] = $result; - } - - if (!empty($pconfig['dns_server_enable'])) { - if (!empty($pconfig['dns_server1']) && !is_ipaddr(trim($pconfig['dns_server1']))) { - $input_errors[] = gettext("The field 'DNS Server #1' must contain a valid IP address"); - } - if (!empty($pconfig['dns_server2']) && !is_ipaddr(trim($pconfig['dns_server2']))) { - $input_errors[] = gettext("The field 'DNS Server #2' must contain a valid IP address"); - } - if (!empty($pconfig['dns_server3']) && !is_ipaddr(trim($pconfig['dns_server3']))) { - $input_errors[] = gettext("The field 'DNS Server #3' must contain a valid IP address"); - } - if (!empty($pconfig['dns_server4']) && !is_ipaddr(trim($pconfig['dns_server4']))) { - $input_errors[] = gettext("The field 'DNS Server #4' must contain a valid IP address"); - } - } - if (!empty($pconfig['dns_domain_search'])) { - $tmp_ok_domain = 0; - $tmp_nok_domain = 0; - foreach (explode(",", $pconfig['dns_domain_search'] ?? "") as $domain) { - if (is_domain($domain)) { - $tmp_ok_domain++; - } else { - $tmp_nok_domain++; - } - } - if ($tmp_nok_domain > 0) { - $input_errors[] = gettext("The field 'DNS Domain search list' must contain valid domain names"); - } elseif ($tmp_ok_domain > 10) { - $input_errors[] = gettext("The field 'DNS Domain search list' may contain max 10 entries"); - } - } - - if (!empty($pconfig['ntp_server_enable'])) { - if (!empty($pconfig['ntp_server1']) && !is_ipaddr(trim($pconfig['ntp_server1']))) { - $input_errors[] = gettext("The field 'NTP Server #1' must contain a valid IP address"); - } - if (!empty($pconfig['ntp_server2']) && !is_ipaddr(trim($pconfig['ntp_server2']))) { - $input_errors[] = gettext("The field 'NTP Server #2' must contain a valid IP address"); - } - } - - if (!empty($pconfig['netbios_enable'])) { - if ($pconfig['wins_server_enable']) { - if (!empty($pconfig['wins_server1']) && !is_ipaddr(trim($pconfig['wins_server1']))) { - $input_errors[] = gettext("The field 'WINS Server #1' must contain a valid IP address"); - } - if (!empty($pconfig['wins_server2']) && !is_ipaddr(trim($pconfig['wins_server2']))) { - $input_errors[] = gettext("The field 'WINS Server #2' must contain a valid IP address"); - } - } - } - $prev_opt = (isset($id) && !empty($a_csc[$id])) ? $a_csc[$id]['custom_options'] : ""; - if ($prev_opt != str_replace("\r\n", "\n", $pconfig['custom_options']) && !userIsAdmin($_SESSION['Username'])) { - $input_errors[] = gettext('Advanced options may only be edited by system administrators due to the increased possibility of privilege escalation.'); - } - - - $reqdfields[] = 'common_name'; - $reqdfieldsn[] = 'Common name'; - - do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors); - - if (count($input_errors) == 0) { - $csc = array(); - // 1 on 1 copy of config attributes - foreach (explode(",", $all_form_fields) as $fieldname) { - $fieldname = trim($fieldname); - if (!empty($pconfig[$fieldname])) { - if (is_array($pconfig[$fieldname])) { - $csc[$fieldname] = implode(',', $pconfig[$fieldname]); - } else { - $csc[$fieldname] = $pconfig[$fieldname]; - } - } - } - - // handle fields with some kind of logic - if (!empty($pconfig['disable']) && $pconfig['disable'] == "yes") { - $csc['disable'] = true; - } - - if (isset($id)) { - $a_csc[$id] = $csc; - } else { - $a_csc[] = $csc; - } - - write_config(); - - header(url_safe('Location: /vpn_openvpn_csc.php')); - exit; - } - } -} - -// escape form output before processing -legacy_html_escape_form_data($pconfig); - -include("head.inc"); -?> - - - - - -
-
-
- 0) { - print_input_errors($input_errors); - } - if (isset($savemsg)) { - print_info_box($savemsg); - }?> -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- /> - -
- - -
- - -
- - -
- /> - -
- - -
- - -
- - -
- - -
- - -
- - -
- /> - -
- /> - -
- /> - - -
- /> -
- -
- -
- /> - - -
- /> - - -
- /> - - -
- :  - - - Scope ID:  - - -
-
- /> - - -
- - - -
  - - - - - -
-
-
- -
- - - -
- - -
-
-
-
-
- -