From c30477bef708fa02c19b447699097767836c1ca1 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Tue, 23 Apr 2019 15:48:47 +0200 Subject: [PATCH] openvpn: remove hardcoded service include Add two temporary spots that need to be reworked later when this is verified working. Other plugins also register their interfaces so it would be nice to pin them all down in a shared hook. --- src/etc/inc/interfaces.inc | 38 +++++------ src/etc/inc/plugins.inc.d/openvpn.inc | 65 +------------------ .../inc/plugins.inc.d/openvpn/tls-verify.php | 50 +++++++------- src/etc/inc/services.inc | 11 +--- src/etc/rc.bootup | 3 +- src/etc/rc.openvpn | 1 - src/etc/rc.syshook.d/carp/20-openvpn | 1 + src/www/status_openvpn.php | 2 +- src/www/system_crlmanager.php | 7 +- src/www/system_gateway_groups.php | 5 +- src/www/vpn_openvpn_client.php | 2 +- src/www/vpn_openvpn_csc.php | 52 +++++++-------- src/www/vpn_openvpn_server.php | 52 +++++++-------- src/www/widgets/widgets/openvpn.widget.php | 48 +++++++------- 14 files changed, 133 insertions(+), 204 deletions(-) diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 8a494b18b..27be11968 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -889,6 +889,9 @@ function interfaces_configure($verbose = false) interfaces_lagg_configure('', $verbose); interfaces_vlan_configure('', $verbose); + /* XXX temporary plugin spot */ + plugins_configure('openvpn_prepare', $verbose); + $delayed_list = array(); $bridge_list = array(); $track6_list = array(); @@ -2269,24 +2272,6 @@ function kill_wpasupplicant($interface) mwexec("/bin/pkill -f \"wpa_supplicant .*{$interface}\\.conf\"\n"); } -function interface_virtual_create($interface) -{ - if (strstr($interface, '_vlan')) { - interfaces_vlan_configure($interface); - } elseif (substr($interface, 0, 3) == 'gre') { - interfaces_gre_configure(0, false, $interface); - } elseif (substr($interface, 0, 3) == 'gif') { - interfaces_gif_configure(0, false, $interface); - } elseif (substr($interface, 0, 4) == 'ovpn') { - /* XXX this looks like a plugin spot... */ - openvpn_configure_interface($interface); - } elseif (substr($interface, 0, 4) == 'lagg') { - interfaces_lagg_configure($interface); - } elseif (substr($interface, 0, 6) == 'bridge') { - interfaces_bridge_configure(0, $interface); - } -} - function interface_static_configure($interface, $wancfg) { if (empty($wancfg['ipaddr']) || !is_ipaddrv4($wancfg['ipaddr']) || $wancfg['subnet'] == '') { @@ -2366,8 +2351,21 @@ function interface_configure($verbose = false, $interface = 'wan', $reload = fal } /* Need to check that the interface exists or not in the case where its coming back from disabled state see #3270 */ - if (in_array(substr($realif, 0, 3), array("gre", "gif")) || !does_interface_exist($interface_to_check)) { - interface_virtual_create($interface_to_check); + if (in_array(substr($realif, 0, 3), array('gre', 'gif')) || !does_interface_exist($interface_to_check)) { + if (strstr($interface_to_check, '_vlan')) { + interfaces_vlan_configure($interface_to_check); + } elseif (substr($interface_to_check, 0, 3) == 'gre') { + interfaces_gre_configure(0, false, $interface_to_check); + } elseif (substr($interface_to_check, 0, 3) == 'gif') { + interfaces_gif_configure(0, false, $interface_to_check); + /* XXX OpenVPN resolves the virtual interface name, check too explicit here */ + } elseif (substr($interface_to_check, 0, 4) == 'ovpn') { + plugins_configure('openvpn_reload', false, array($interface)); + } elseif (substr($interface_to_check, 0, 4) == 'lagg') { + interfaces_lagg_configure($interface_to_check); + } elseif (substr($interface_to_check, 0, 6) == 'bridge') { + interfaces_bridge_configure(0, $interface_to_check); + } } /* Disable Accepting router advertisements unless specifically requested */ diff --git a/src/etc/inc/plugins.inc.d/openvpn.inc b/src/etc/inc/plugins.inc.d/openvpn.inc index c2b0c7404..6a90ca6dd 100644 --- a/src/etc/inc/plugins.inc.d/openvpn.inc +++ b/src/etc/inc/plugins.inc.d/openvpn.inc @@ -33,6 +33,9 @@ function openvpn_configure() { return array( + 'crl' => array('openvpn_refresh_crls:0'), + 'openvpn_reload' => array('openvpn_configure_do:2'), + 'openvpn_prepare' => array('openvpn_prepare_all'), 'remote' => array('openvpn_configure_do'), 'vpn' => array('openvpn_configure_do:2'), ); @@ -1161,35 +1164,6 @@ function openvpn_prepare_all($verbose = false) } } -function openvpn_configure_interface($interface) -{ - global $config; - - if (substr($interface, 0, 5) == 'ovpns') { - if (isset($config['openvpn']['openvpn-server'])) { - foreach ($config['openvpn']['openvpn-server'] as $server) { - if ($interface == "ovpns{$server['vpnid']}") { - log_error("OpenVPN: Resync server {$server['description']}"); - openvpn_reconfigure('server', $server); - openvpn_restart('server', $server); - } - } - unset($server); - } - } elseif (substr($interface, 0, 5) == 'ovpnc') { - if (isset($config['openvpn']['openvpn-client'])) { - foreach ($config['openvpn']['openvpn-client'] as $client) { - if ($interface == "ovpnc{$client['vpnid']}") { - log_error("OpenVPN: Resync server {$client['description']}"); - openvpn_reconfigure('client', $client); - openvpn_restart('client', $client); - } - } - unset($client); - } - } -} - function openvpn_configure_single($id) { global $config; @@ -1598,39 +1572,6 @@ function openvpn_get_remote_access_servers() return $result; } -// Resync and restart all VPNs using a gateway group. -function openvpn_configure_gwgroup($gwgroupname = '') -{ - global $config; - - if (empty($gwgroupname)) { - log_error("openvpn_configure_gwgroup() called without gwgroup parameter."); - return; - } - - if (isset($config['openvpn']['openvpn-server'])) { - foreach ($config['openvpn']['openvpn-server'] as &$settings) { - if ($gwgroupname == $settings['interface']) { - log_error("Resyncing OpenVPN server for gateway group " . - $gwgroupname . " server " . $settings["description"] . "."); - openvpn_reconfigure('server', $settings); - openvpn_restart('server', $settings); - } - } - } - - if (isset($config['openvpn']['openvpn-client'])) { - foreach ($config['openvpn']['openvpn-client'] as &$settings) { - if ($gwgroupname == $settings['interface']) { - log_error("Resyncing OpenVPN client for gateway group " . - $gwgroupname . " client " . $settings["description"] . "."); - openvpn_reconfigure('client', $settings); - openvpn_restart('client', $settings); - } - } - } -} - function openvpn_refresh_crls() { global $config; diff --git a/src/etc/inc/plugins.inc.d/openvpn/tls-verify.php b/src/etc/inc/plugins.inc.d/openvpn/tls-verify.php index 95fc239c8..ea4212bc1 100644 --- a/src/etc/inc/plugins.inc.d/openvpn/tls-verify.php +++ b/src/etc/inc/plugins.inc.d/openvpn/tls-verify.php @@ -2,31 +2,31 @@ - Copyright (C) 2018 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. -*/ + * Copyright (C) 2011 Jim Pingle + * Copyright (C) 2018 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. + */ /* * OpenVPN calls this script to validate a certificate diff --git a/src/etc/inc/services.inc b/src/etc/inc/services.inc index 61d1a3c7b..1f5bf49a8 100644 --- a/src/etc/inc/services.inc +++ b/src/etc/inc/services.inc @@ -30,15 +30,10 @@ */ /* - * XXX OpenVPN is the last base plugin that is not gracefully registering - * its functionality to core. With it being gone we can assume all - * plugins even if core functionality must adhere to this idiom. - * - * This will allow us to remove all service-relevant parts from system.inc - * and services.inc so that the latter does become obsolete. For this to - * succeed DHCP functionality needs to be put into a plugin as well. + * XXX Remove all service-relevant parts from system.inc and services.inc + * so that the latter does become obsolete. For this to succeed all DHCP + * functionality needs to be put into its own plugin file. */ -require_once('plugins.inc.d/openvpn.inc'); function generate_ipv6_from_mac($mac) { diff --git a/src/etc/rc.bootup b/src/etc/rc.bootup index e160e53b3..1b83471d3 100755 --- a/src/etc/rc.bootup +++ b/src/etc/rc.bootup @@ -2,7 +2,7 @@ + * Copyright (C) 2014-2019 Franco Fichtner * Copyright (C) 2004-2009 Scott Ullrich * Copyright (C) 2003-2004 Manuel Kasper * Copyright (C) 2009 Erik Kristensen @@ -95,7 +95,6 @@ system_hostname_configure(true); system_hosts_generate(true); system_syslogd_start(true); -openvpn_prepare_all(true); interfaces_configure(true); system_resolvconf_generate(true); diff --git a/src/etc/rc.openvpn b/src/etc/rc.openvpn index c095cbb56..931fc288d 100755 --- a/src/etc/rc.openvpn +++ b/src/etc/rc.openvpn @@ -34,7 +34,6 @@ require_once("interfaces.inc"); require_once("filter.inc"); require_once("plugins.inc.d/openvpn.inc"); - function try_lock($lock, $timeout = 5) { if (!$lock) { diff --git a/src/etc/rc.syshook.d/carp/20-openvpn b/src/etc/rc.syshook.d/carp/20-openvpn index 1bab345ed..cb8862b94 100755 --- a/src/etc/rc.syshook.d/carp/20-openvpn +++ b/src/etc/rc.syshook.d/carp/20-openvpn @@ -31,6 +31,7 @@ require_once("config.inc"); require_once("services.inc"); require_once("interfaces.inc"); require_once("util.inc"); +require_once("plugins.inc.d/openvpn.inc"); $subsystem = !empty($argv[1]) ? $argv[1] : ''; $type = !empty($argv[2]) ? $argv[2] : ''; diff --git a/src/www/status_openvpn.php b/src/www/status_openvpn.php index 185ac1768..ff2829c3c 100644 --- a/src/www/status_openvpn.php +++ b/src/www/status_openvpn.php @@ -31,9 +31,9 @@ */ require_once("guiconfig.inc"); -require_once("plugins.inc.d/openvpn.inc"); require_once("services.inc"); require_once("interfaces.inc"); +require_once("plugins.inc.d/openvpn.inc"); function kill_client($port, $remipp) { diff --git a/src/www/system_crlmanager.php b/src/www/system_crlmanager.php index c3e6dd3d7..137f14494 100644 --- a/src/www/system_crlmanager.php +++ b/src/www/system_crlmanager.php @@ -28,7 +28,6 @@ */ require_once('guiconfig.inc'); -require_once('services.inc'); function cert_unrevoke($cert, &$crl) { @@ -140,7 +139,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { } $name = $thiscert['descr']; if (cert_unrevoke($thiscert, $thiscrl)) { - openvpn_refresh_crls(); + plugins_configure('crl'); write_config(sprintf('Deleted certificate %s from CRL %s', $name, $thiscrl['descr'])); header(url_safe('Location: /system_crlmanager.php')); exit; @@ -173,7 +172,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { if (!count($input_errors)) { $reason = (empty($pconfig['crlreason'])) ? OCSP_REVOKED_STATUS_UNSPECIFIED : $pconfig['crlreason']; cert_revoke($cert, $crl, $reason); - openvpn_refresh_crls(); + plugins_configure('crl'); write_config(sprintf('Revoked certificate %s in CRL %s', $cert['descr'], $crl['descr'])); header(url_safe('Location: /system_crlmanager.php')); exit; @@ -230,7 +229,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { } write_config(sprintf('Saved CRL %s', $crl['descr'])); - openvpn_refresh_crls(); + plugins_configure('crl'); header(url_safe('Location: /system_crlmanager.php')); exit; } diff --git a/src/www/system_gateway_groups.php b/src/www/system_gateway_groups.php index c6428c1e0..5c949bf90 100644 --- a/src/www/system_gateway_groups.php +++ b/src/www/system_gateway_groups.php @@ -62,10 +62,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { foreach ($a_gateway_groups as $gateway_group) { $gw_subsystem = 'gwgroup.' . $gateway_group['name']; - if (is_subsystem_dirty($gw_subsystem)) { - openvpn_configure_gwgroup($gateway_group['name']); - clear_subsystem_dirty($gw_subsystem); - } + clear_subsystem_dirty($gw_subsystem); } header(url_safe('Location: /system_gateway_groups.php')); diff --git a/src/www/vpn_openvpn_client.php b/src/www/vpn_openvpn_client.php index b90f07e73..bb41f7a05 100644 --- a/src/www/vpn_openvpn_client.php +++ b/src/www/vpn_openvpn_client.php @@ -28,9 +28,9 @@ */ require_once("guiconfig.inc"); -require_once("plugins.inc.d/openvpn.inc"); require_once("services.inc"); require_once("interfaces.inc"); +require_once("plugins.inc.d/openvpn.inc"); $a_client = &config_read_array('openvpn', 'openvpn-client'); diff --git a/src/www/vpn_openvpn_csc.php b/src/www/vpn_openvpn_csc.php index 9f18c058b..7492ca4d6 100644 --- a/src/www/vpn_openvpn_csc.php +++ b/src/www/vpn_openvpn_csc.php @@ -1,36 +1,36 @@ - 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. -*/ + * Copyright (C) 2014-2015 Deciso B.V. + * Copyright (C) 2008 Shrew Soft Inc. + * 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("plugins.inc.d/openvpn.inc"); require_once("services.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 diff --git a/src/www/vpn_openvpn_server.php b/src/www/vpn_openvpn_server.php index 51bfd3346..333b7522f 100644 --- a/src/www/vpn_openvpn_server.php +++ b/src/www/vpn_openvpn_server.php @@ -1,36 +1,36 @@ - 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. -*/ + * Copyright (C) 2014-2015 Deciso B.V. + * Copyright (C) 2008 Shrew Soft Inc. + * 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("plugins.inc.d/openvpn.inc"); require_once("services.inc"); require_once("interfaces.inc"); +require_once("plugins.inc.d/openvpn.inc"); $a_server = &config_read_array('openvpn', 'openvpn-server'); diff --git a/src/www/widgets/widgets/openvpn.widget.php b/src/www/widgets/widgets/openvpn.widget.php index 493662e50..f6a681016 100644 --- a/src/www/widgets/widgets/openvpn.widget.php +++ b/src/www/widgets/widgets/openvpn.widget.php @@ -1,30 +1,30 @@