diff --git a/security/openvpn-legacy/src/opnsense/mvc/app/models/OPNsense/OpenVPN/ACL/ACL.xml b/security/openvpn-legacy/src/opnsense/mvc/app/models/OPNsense/OpenVPN/ACL/ACL.xml new file mode 100644 index 000000000..006053043 --- /dev/null +++ b/security/openvpn-legacy/src/opnsense/mvc/app/models/OPNsense/OpenVPN/ACL/ACL.xml @@ -0,0 +1,14 @@ + + + VPN: OpenVPN: Client + + vpn_openvpn_client.php* + + + + VPN: OpenVPN: Server + + vpn_openvpn_server.php* + + + diff --git a/security/openvpn-legacy/src/opnsense/mvc/app/models/OPNsense/OpenVPN/Menu/Menu.xml b/security/openvpn-legacy/src/opnsense/mvc/app/models/OPNsense/OpenVPN/Menu/Menu.xml new file mode 100644 index 000000000..c611e9fc6 --- /dev/null +++ b/security/openvpn-legacy/src/opnsense/mvc/app/models/OPNsense/OpenVPN/Menu/Menu.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/security/openvpn-legacy/src/www/vpn_openvpn_client.php b/security/openvpn-legacy/src/www/vpn_openvpn_client.php new file mode 100644 index 000000000..bded6628b --- /dev/null +++ b/security/openvpn-legacy/src/www/vpn_openvpn_client.php @@ -0,0 +1,1231 @@ + + * 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"); + +$a_client = &config_read_array('openvpn', 'openvpn-client'); + +$vpnid = 0; +$act = null; +if ($_SERVER['REQUEST_METHOD'] === 'GET') { + if (isset($_GET['dup']) && isset($a_client[$_GET['dup']])) { + $configId = $_GET['dup']; + } elseif (isset($_GET['id']) && isset($a_client[$_GET['id']])) { + $id = $_GET['id']; + $configId = $id; + } + + if (isset($_GET['act'])) { + $act = $_GET['act']; + } + + $pconfig = array(); + // set defaults + $pconfig['autokey_enable'] = "yes"; // just in case the modes switch + $pconfig['autotls_enable'] = "yes"; // just in case the modes switch + $pconfig['tlsmode'] = "auth"; + $pconfig['digest'] = "SHA1"; + $pconfig['verbosity_level'] = 1; // Default verbosity is 1 + + // edit existing. + if (isset($configId)) { + // 1 on 1 copy of config attributes + $copy_fields = "auth_user,auth_pass,disable,mode,protocol,interface + ,local_port,server_addr,server_port,resolve_retry,remote_random,reneg-sec + ,proxy_addr,proxy_port,proxy_user,proxy_passwd,proxy_authtype,description + ,custom_options,ns_cert_type,dev_mode,tlsmode,caref,certref,crypto,digest + ,tunnel_network,tunnel_networkv6,remote_network,remote_networkv6,use_shaper + ,compression,passtos,route_no_pull,route_no_exec,verbosity_level"; + + foreach (explode(",", $copy_fields) as $fieldname) { + $fieldname = trim($fieldname); + if (isset($a_client[$configId][$fieldname])) { + $pconfig[$fieldname] = $a_client[$configId][$fieldname]; + } elseif (!isset($pconfig[$fieldname])) { + // initialize element + $pconfig[$fieldname] = null; + } + } + + // load / convert + if (!empty($a_client[$configId]['ipaddr'])) { + $pconfig['interface'] = $pconfig['interface'] . '|' . $a_client[$configId]['ipaddr']; + } + + if (isset($a_client[$configId]['tls'])) { + $pconfig['tls'] = base64_decode($a_client[$configId]['tls']); + } else { + $pconfig['tls'] = null; + $pconfig['tlsmode'] = null; + } + + if (isset($a_client[$configId]['shared_key'])) { + $pconfig['shared_key'] = base64_decode($a_client[$configId]['shared_key']); + } else { + $pconfig['shared_key'] = null ; + } + + if (isset($id)) { + $vpnid = $a_client[$id]['vpnid']; + } + } elseif ($act=="new") { + // create new + $pconfig['interface'] = 'any'; + $init_fields = "auth_user,auth_pass,disable,mode,protocol,interface + ,local_port,server_addr,server_port,resolve_retry,remote_random,reneg-sec + ,proxy_addr,proxy_port,proxy_user,proxy_passwd,proxy_authtype,description + ,custom_options,ns_cert_type,dev_mode,caref,certref,crypto,digest,tlsmode + ,tunnel_network,tunnel_networkv6,remote_network,remote_networkv6,use_shaper + ,compression,passtos,route_no_pull,route_no_exec,verbosity_level"; + + foreach (explode(",", $init_fields) as $fieldname) { + $fieldname = trim($fieldname); + if (!isset($pconfig[$fieldname])) { + $pconfig[$fieldname] = null; + } + } + } +} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { + $pconfig = $_POST; + $input_errors = array(); + if (isset($_POST['id']) && isset($a_client[$_POST['id']])) { + $id = $_POST['id']; + } + if (isset($_POST['act'])) { + $act = $_POST['act']; + } + + if ($act == "del") { + $response = ["status" => "failed", "message" => gettext("not found")]; + if (isset($id) && !empty($a_client[$id])) { + openvpn_delete('client', $a_client[$id]); + unset($a_client[$id]); + write_config(); + $response = ["status" => "ok"]; + } + echo json_encode($response); + exit; + } elseif ($act == "del_x") { + if (!empty($pconfig['rule']) && is_array($pconfig['rule'])) { + foreach ($pconfig['rule'] as $rulei) { + $vpn_id = !empty($a_client[$rulei]) ? $a_client[$rulei]['vpnid'] : null; + if (!empty($a_client[$rulei])) { + openvpn_delete('client', $a_client[$rulei]); + unset($a_client[$rulei]); + } + } + write_config(); + } + header(url_safe('Location: /vpn_openvpn_client.php')); + exit; + } elseif ($act == "move"){ + // move selected items + if (!isset($id)) { + // if id not set/found, move to end + $id = count($a_client); + } + $a_client = legacy_move_config_list_items($a_client, $id, $pconfig['rule']); + write_config(); + header(url_safe('Location: /vpn_openvpn_client.php')); + exit; + } elseif ($act == "toggle") { + if (isset($id)) { + if (isset($a_client[$id]['disable'])) { + unset($a_client[$id]['disable']); + } else { + $a_client[$id]['disable'] = true; + } + write_config(); + openvpn_configure_single($a_client[$id]['vpnid']); + } + header(url_safe('Location: /vpn_openvpn_client.php')); + exit; + } else { + // update client (after validation) + if (isset($id)) { + $vpnid = $a_client[$id]['vpnid']; + } + if (isset($pconfig['mode']) && $pconfig['mode'] != "p2p_shared_key") { + $tls_mode = true; + } else { + $tls_mode = false; + } + + // generate new key + if (!empty($pconfig['autokey_enable'])) { + $pconfig['shared_key'] = openvpn_create_key(); + } + + /* input validation */ + if (strpos($pconfig['interface'], '|') !== false) { + list($iv_iface, $iv_ip) = explode("|", $pconfig['interface']); + } else { + $iv_iface = $pconfig['interface']; + $iv_ip = null; + } + + if (is_ipaddrv4($iv_ip) && (stristr($pconfig['protocol'], "6") !== false)) { + $input_errors[] = gettext("Protocol and IP address families do not match. You cannot select an IPv6 protocol and an IPv4 address."); + } elseif (is_ipaddrv6($iv_ip) && (stristr($pconfig['protocol'], "6") === false)) { + $input_errors[] = gettext("Protocol and IP address families do not match. You cannot select an IPv4 protocol and an IPv6 address."); + } elseif ((stristr($pconfig['protocol'], "6") === false) && !get_interface_ip($iv_iface) && ($pconfig['interface'] != "any")) { + $input_errors[] = gettext("An IPv4 protocol was selected, but the selected interface has no IPv4 address."); + } elseif ((stristr($pconfig['protocol'], "6") !== false) && !get_interface_ipv6($iv_iface) && ($pconfig['interface'] != "any")) { + $input_errors[] = gettext("An IPv6 protocol was selected, but the selected interface has no IPv6 address."); + } + if (!empty($pconfig['local_port'])) { + if (!is_numeric($pconfig['local_port']) || $pconfig['local_port'] < 0 || ($pconfig['local_port'] > 65535)) { + $input_errors[] = gettext("The field 'Local port' must contain a valid port, ranging from 0 to 65535."); + } + $portused = openvpn_port_used($pconfig['protocol'], $pconfig['interface'], $pconfig['local_port'], $vpnid); + if (($portused != $vpnid) && ($portused != 0)) { + $input_errors[] = gettext("The specified 'Local port' is in use. Please select another value"); + } + } + + $server_addr_a = array(); + $server_port_a = array(); + + foreach (array_keys($pconfig['server_addr']) as $i) { + if (empty($pconfig['server_addr'][$i]) && empty($pconfig['server_port'][$i])) { + continue; + } + if (empty($pconfig['server_addr'][$i]) || (!is_domain($pconfig['server_addr'][$i]) && !is_ipaddr($pconfig['server_addr'][$i]))) { + $input_errors[] = gettext("The field 'Server host or address' must contain a valid IP address or domain name.") ; + } + if (empty($pconfig['server_port'][$i]) || !is_numeric($pconfig['server_port'][$i]) || $pconfig['server_port'][$i] < 0 || $pconfig['server_port'][$i] > 65535) { + $input_errors[] = gettext("The field 'Server port' must contain a valid port, ranging from 0 to 65535."); + } + $server_addr_a[] = $pconfig['server_addr'][$i]; + $server_port_a[] = $pconfig['server_port'][$i]; + } + + $pconfig['server_addr'] = implode(',', $server_addr_a); + $pconfig['server_port'] = implode(',', $server_port_a); + + if (empty($pconfig['server_addr']) || empty($pconfig['server_port'])) { + $input_errors[] = gettext("At least one remote server must be specified."); + } + + if (isset($pconfig['reneg-sec']) && $pconfig['reneg-sec'] != "" && (string)((int)$pconfig['reneg-sec']) != $pconfig['reneg-sec']) { + $input_errors[] = gettext("Renegotiate time should contain a valid number of seconds."); + } + + if (!empty($pconfig['proxy_addr'])) { + if (empty($pconfig['proxy_addr']) || (!is_domain($pconfig['proxy_addr']) && !is_ipaddr($pconfig['proxy_addr']))) { + $input_errors[] = gettext("The field 'Proxy host or address' must contain a valid IP address or domain name."); + } + if (empty($pconfig['proxy_port']) || !is_numeric($pconfig['proxy_port']) || $pconfig['proxy_port'] < 0 || ($pconfig['proxy_port'] > 65535)) { + $input_errors[] = gettext("The field 'Proxy port' must contain a valid port, ranging from 0 to 65535."); + } + if (isset($pconfig['proxy_authtype']) && $pconfig['proxy_authtype'] != "none") { + if (empty($pconfig['proxy_user']) || empty($pconfig['proxy_passwd'])) { + $input_errors[] = gettext("User name and password are required for proxy with authentication."); + } + } + } + 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['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['use_shaper']) && (!is_numeric($pconfig['use_shaper']) || ($pconfig['use_shaper'] <= 0))) { + $input_errors[] = gettext("The bandwidth limit must be a positive numeric value."); + } + if (!$tls_mode && empty($pconfig['autokey_enable'])) { + if (!strstr($pconfig['shared_key'], "-----BEGIN OpenVPN Static key V1-----") || + !strstr($pconfig['shared_key'], "-----END OpenVPN Static key V1-----")) { + $input_errors[] = gettext("The field 'Shared Key' does not appear to be valid"); + } + } + if ($tls_mode && !empty($pconfig['tlsmode']) && empty($pconfig['autotls_enable'])) { + if (!strstr($pconfig['tls'], "-----BEGIN OpenVPN Static key V1-----") || + !strstr($pconfig['tls'], "-----END OpenVPN Static key V1-----")) { + $input_errors[] = gettext("The field 'TLS Shared Key' does not appear to be valid"); + } + } + + /* If we are not in shared key mode, then we need the CA/Cert. */ + if (isset($pconfig['mode']) && $pconfig['mode'] != "p2p_shared_key") { + $reqdfields = explode(" ", "caref"); + $reqdfieldsn = array(gettext("Certificate Authority")); + } elseif (empty($pconfig['autokey_enable'])) { + /* We only need the shared key filled in if we are in shared key mode and autokey is not selected. */ + $reqdfields = array('shared_key'); + $reqdfieldsn = array(gettext('Shared key')); + } + + do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors); + + if (($pconfig['mode'] != "p2p_shared_key") && empty($pconfig['certref']) && empty($pconfig['auth_user']) && empty($pconfig['auth_pass'])) { + $input_errors[] = gettext("If no Client Certificate is selected, a username and password must be entered."); + } + $prev_opt = (isset($id) && !empty($a_client[$id])) ? $a_client[$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.'); + } + + if (count($input_errors) == 0) { + // save data + $client = array(); + // 1 on 1 copy of config attributes + $copy_fields = "auth_user,auth_pass,protocol,dev_mode,local_port,reneg-sec + ,server_addr,server_port,resolve_retry,proxy_addr,proxy_port,remote_random + ,proxy_authtype,proxy_user,proxy_passwd,description,mode,crypto,digest + ,tunnel_network,tunnel_networkv6,remote_network,remote_networkv6 + ,use_shaper,compression,passtos,route_no_pull,route_no_exec,tlsmode + ,verbosity_level,interface"; + + foreach (explode(",", $copy_fields) as $fieldname) { + $fieldname = trim($fieldname); + if (!empty($pconfig[$fieldname]) || $pconfig[$fieldname] == '0') { + $client[$fieldname] = $pconfig[$fieldname]; + } + } + + // attributes containing some kind of logic + if ($vpnid) { + $client['vpnid'] = $vpnid; + } else { + $client['vpnid'] = openvpn_vpnid_next(); + } + if (isset($pconfig['disable']) && $pconfig['disable'] == "yes") { + $client['disable'] = true; + } + + if (strpos($pconfig['interface'], "|") !== false) { + list($client['interface'], $client['ipaddr']) = explode("|", $pconfig['interface']); + } + $client['custom_options'] = str_replace("\r\n", "\n", $pconfig['custom_options']); + + if ($tls_mode) { + $client['caref'] = $pconfig['caref']; + $client['certref'] = $pconfig['certref']; + if (!empty($pconfig['tlsmode'])) { + if (!empty($pconfig['autotls_enable'])) { + $pconfig['tls'] = openvpn_create_key(); + } + $client['tls'] = base64_encode($pconfig['tls']); + } + } else { + $client['shared_key'] = base64_encode($pconfig['shared_key']); + } + + if (isset($id)) { + $a_client[$id] = $client; + } else { + $a_client[] = $client; + } + + write_config(); + + openvpn_configure_single($client['vpnid']); + + header(url_safe('Location: /vpn_openvpn_client.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); + }?> + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ /> + +
+ + +
+ +
+ + +
+ +
+ +
+ + + + + + + + + + $item): ?> + + + + + + + +
+ + + + + + + + + +
+
+ /> + +
+ /> + + +
+ +
+ +
+ + + +
+ + +
+
+
+
+
+
+
+ + + + + + + + + + + + +
+
+
+
+
+ +
+
+ + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + > + . + +
+ +

.

+
+
+ + + +
+ . + +
+ + +
+ + +
+ + /> + . + +
+ + . +
+
+ + +
+ + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ /> + +
+ /> + +
+ /> + +
+
+
+
+
+
+
+ + + + + + + + + + + + +
+ + + +
+ + +
+
+
+
+
+
+
+ + + + + +
  + + + + + +
+
+
+
+
+ +
+
+ + +
+
+ + +
+
+
+ diff --git a/security/openvpn-legacy/src/www/vpn_openvpn_server.php b/security/openvpn-legacy/src/www/vpn_openvpn_server.php new file mode 100644 index 000000000..da97ce84a --- /dev/null +++ b/security/openvpn-legacy/src/www/vpn_openvpn_server.php @@ -0,0 +1,1710 @@ + + * 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"); + +$a_server = &config_read_array('openvpn', 'openvpn-server'); + +$act = null; +if ($_SERVER['REQUEST_METHOD'] === 'GET') { + // fetch id if provided + if (isset($_GET['dup']) && isset($a_server[$_GET['dup']])) { + $configId = $_GET['dup']; + } elseif (isset($_GET['id']) && is_numericint($_GET['id'])) { + $id = $_GET['id']; + $configId = $id; + } + if (isset($_GET['act'])) { + $act = $_GET['act']; + } + $pconfig = array(); + // defaults + $vpnid = 0; + $pconfig['verbosity_level'] = 1; + $pconfig['digest'] = "SHA1"; // OpenVPN Defaults to SHA1 if unset + $pconfig['crypto'] = ""; + $pconfig['tlsmode'] = "auth"; + $pconfig['autokey_enable'] = "yes"; + $pconfig['autotls_enable'] = "yes"; + if (isset($configId) && isset($a_server[$configId])) { + if ($a_server[$configId]['mode'] != "p2p_shared_key") { + $pconfig['cert_depth'] = 1; + } + + // 1 on 1 copy of config attributes + $copy_fields = "mode,protocol,authmode,dev_mode,interface,local_port + ,description,custom_options,crypto,tunnel_network + ,tunnel_networkv6,remote_network,remote_networkv6,gwredir,local_network + ,local_networkv6,maxclients,compression,passtos,client2client + ,dynamic_ip,topology_subnet,serverbridge_dhcp + ,serverbridge_interface,serverbridge_dhcp_start,serverbridge_dhcp_end + ,dns_server1,dns_server2,dns_server3,dns_server4,ntp_server1 + ,ntp_server2,netbios_enable,netbios_ntype,netbios_scope,wins_server1 + ,wins_server2,push_register_dns,push_block_outside_dns,dns_domain,dns_domain_search,local_group + ,client_mgmt_port,verbosity_level,tlsmode,caref,crlref,certref + ,cert_depth,strictusercn,digest,disable,duplicate_cn,vpnid,reneg-sec,use-common-name,cso_login_matching"; + + foreach (explode(",", $copy_fields) as $fieldname) { + $fieldname = trim($fieldname); + if (isset($a_server[$configId][$fieldname])) { + $pconfig[$fieldname] = $a_server[$configId][$fieldname]; + } elseif (!isset($pconfig[$fieldname])) { + // initialize element + $pconfig[$fieldname] = null; + } + } + + // load / convert + if (!empty($a_server[$configId]['ipaddr'])) { + $pconfig['interface'] = $pconfig['interface'] . '|' . $a_server[$configId]['ipaddr']; + } + if (!empty($a_server[$configId]['shared_key'])) { + $pconfig['shared_key'] = base64_decode($a_server[$configId]['shared_key']); + } else { + $pconfig['shared_key'] = null; + } + if (!empty($a_server[$configId]['tls'])) { + $pconfig['tls'] = base64_decode($a_server[$configId]['tls']); + } else { + $pconfig['tls'] = null; + $pconfig['tlsmode'] = null; + } + } elseif ($act == "new") { + $pconfig['dev_mode'] = "tun"; + $pconfig['interface'] = 'any'; + $pconfig['protocol'] = 'UDP'; + $pconfig['local_port'] = openvpn_port_next($pconfig['protocol']); + $pconfig['cert_depth'] = 1; + // init all fields used in the form + $init_fields = "mode,protocol,authmode,dev_mode,interface,local_port + ,description,custom_options,crypto,tunnel_network + ,tunnel_networkv6,remote_network,remote_networkv6,gwredir,local_network + ,local_networkv6,maxclients,compression,passtos,client2client + ,dynamic_ip,topology_subnet,serverbridge_dhcp + ,serverbridge_interface,serverbridge_dhcp_start,serverbridge_dhcp_end + ,dns_server1,dns_server2,dns_server3,dns_server4,ntp_server1 + ,ntp_server2,netbios_enable,netbios_ntype,netbios_scope,wins_server1 + ,wins_server2,push_register_dns,push_block_outside_dns,dns_domain,dns_domain_search + ,client_mgmt_port,verbosity_level,tlsmode,caref,crlref,certref + ,cert_depth,strictusercn,digest,disable,duplicate_cn,vpnid,shared_key,tls,reneg-sec,use-common-name + ,cso_login_matching"; + foreach (explode(",", $init_fields) as $fieldname) { + $fieldname = trim($fieldname); + if (!isset($pconfig[$fieldname])) { + $pconfig[$fieldname] = null; + } + } + + } +} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') { + if (isset($_POST['id']) && isset($a_server[$_POST['id']])) { + $id = $_POST['id']; + } + if (isset($_POST['act'])) { + $act = $_POST['act']; + } + + if ($act == "del") { + $response = ["status" => "failed", "message" => gettext("not found")]; + if (isset($id) && !empty($a_client[$id])) { + openvpn_delete('server', $a_server[$id]); + unset($a_server[$id]); + write_config(); + $response = ["status" => "ok"]; + } + echo json_encode($response); + exit; + } elseif ($act == "toggle") { + if (isset($id)) { + if (isset($a_server[$id]['disable'])) { + unset($a_server[$id]['disable']); + } else { + $a_server[$id]['disable'] = true; + } + write_config(); + openvpn_configure_single($a_server[$id]['vpnid']); + } + header(url_safe('Location: /vpn_openvpn_server.php')); + exit; + } else { + // action add/update + $input_errors = array(); + $pconfig = $_POST; + + $vpnid = (isset($id) && $a_server[$id]) ? $a_server[$id]['vpnid'] : 0; + $tls_mode = ($pconfig['mode'] != "p2p_shared_key"); + + if (!empty($pconfig['autokey_enable'])) { + $pconfig['shared_key'] = openvpn_create_key(); + } + + // all input validators + if (strpos($pconfig['interface'], '|') !== false) { + list($iv_iface, $iv_ip) = explode("|", $pconfig['interface']); + } else { + $iv_iface = $pconfig['interface']; + $iv_ip = null; + } + + if (is_ipaddrv4($iv_ip) && (stristr($pconfig['protocol'], "6") !== false)) { + $input_errors[] = gettext("Protocol and IP address families do not match. You cannot select an IPv6 protocol and an IPv4 IP address."); + } elseif (is_ipaddrv6($iv_ip) && (stristr($pconfig['protocol'], "6") === false)) { + $input_errors[] = gettext("Protocol and IP address families do not match. You cannot select an IPv4 protocol and an IPv6 IP address."); + } elseif ((stristr($pconfig['protocol'], "6") === false) && !get_interface_ip($iv_iface) && ($pconfig['interface'] != "any")) { + $input_errors[] = gettext("An IPv4 protocol was selected, but the selected interface has no IPv4 address."); + } elseif ((stristr($pconfig['protocol'], "6") !== false) && !get_interface_ipv6($iv_iface) && ($pconfig['interface'] != "any")) { + $input_errors[] = gettext("An IPv6 protocol was selected, but the selected interface has no IPv6 address."); + } + + if (empty($pconfig['authmode']) && (($pconfig['mode'] == "server_user") || ($pconfig['mode'] == "server_tls_user"))) { + $input_errors[] = gettext("You must select a Backend for Authentication if the server mode requires User Auth."); + } + + if ($result = openvpn_validate_port($pconfig['local_port'], gettext('Local port'))) { + $input_errors[] = $result; + } + + if ($result = openvpn_validate_cidr($pconfig['tunnel_network'], gettext('IPv4 Tunnel Network'), false, 'ipv4')) { + $input_errors[] = $result; + } elseif (!empty($pconfig['tunnel_network']) && (strpos($pconfig['mode'], "p2p_") === false)) { + // Check IPv4 tunnel_network pool size for Remote Access modes + list($ipv4tunnel_base, $ipv4tunnel_prefix) = explode('/',trim($pconfig['tunnel_network'])); + if ($pconfig['dev_mode'] == "tun") { + if ($ipv4tunnel_prefix > 28 && empty($pconfig['topology_subnet'])) { + $input_errors[] = gettext('A prefix longer than 28 cannot be used with a net30 topology.'); + } elseif ($ipv4tunnel_prefix > 29 && !empty($pconfig['topology_subnet'])) { + $input_errors[] = gettext('A prefix longer than 29 cannot be used for tunnel network.'); + } + } elseif ($pconfig['dev_mode'] == "tap" && $ipv4tunnel_prefix > 29) { + $input_errors[] = gettext('A prefix longer than 29 cannot be used for tunnel network.'); + } + } + + if ($result = openvpn_validate_cidr($pconfig['tunnel_networkv6'], gettext('IPv6 Tunnel Network'), false, '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 ($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 (!empty($pconfig['local_port'])) { + $portused = openvpn_port_used($pconfig['protocol'], $pconfig['interface'], $pconfig['local_port'], $vpnid); + if ($portused) { + $input_errors[] = gettext("The specified 'Local port' is in use. Please select another value"); + } + } + + if (!$tls_mode && empty($pconfig['autokey_enable'])) { + if (!strstr($pconfig['shared_key'], "-----BEGIN OpenVPN Static key V1-----") || + !strstr($pconfig['shared_key'], "-----END OpenVPN Static key V1-----")) { + $input_errors[] = gettext("The field 'Shared Key' does not appear to be valid"); + } + } + + if ($tls_mode && !empty($pconfig['tlsmode']) && empty($pconfig['autotls_enable'])) { + if (!strstr($pconfig['tls'], "-----BEGIN OpenVPN Static key V1-----") || + !strstr($pconfig['tls'], "-----END OpenVPN Static key V1-----")) { + $input_errors[] = gettext("The field 'TLS Shared Key' does not appear to be valid"); + } + } + + 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['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['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['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"); + } + } + + if (!empty($pconfig['client_mgmt_port_enable'])) { + if ($result = openvpn_validate_port($pconfig['client_mgmt_port'], gettext('Client management port'))) { + $input_errors[] = $result; + } + } + + if (!empty($pconfig['maxclients']) && !is_numeric($pconfig['maxclients'])) { + $input_errors[] = gettext("The field 'Concurrent connections' must be numeric."); + } + + /* If we are not in shared key mode, then we need the CA/Cert. */ + if (isset($pconfig['mode']) && $pconfig['mode'] != "p2p_shared_key") { + $reqdfields = explode(" ", "caref certref"); + $reqdfieldsn = array(gettext("Certificate Authority"),gettext("Certificate")); + } elseif (empty($pconfig['autokey_enable'])) { + /* We only need the shared key filled in if we are in shared key mode and autokey is not selected. */ + $reqdfields = array('shared_key'); + $reqdfieldsn = array(gettext('Shared key')); + } + + $reqdfields[] = 'local_port'; + $reqdfieldsn[] = gettext('Local port'); + + if ($pconfig['dev_mode'] != "tap") { + $reqdfields[] = 'tunnel_network,tunnel_networkv6'; + $reqdfieldsn[] = gettext('Tunnel Network'); + } else { + if ($pconfig['serverbridge_dhcp'] && ($pconfig['tunnel_network'] || $pconfig['tunnel_networkv6'])) { + $input_errors[] = gettext("Using a tunnel network and server bridge settings together is not allowed."); + } + if (($pconfig['serverbridge_dhcp_start'] && !$pconfig['serverbridge_dhcp_end']) + || (!$pconfig['serverbridge_dhcp_start'] && $pconfig['serverbridge_dhcp_end'])) { + $input_errors[] = gettext("Server Bridge DHCP Start and End must both be empty, or defined."); + } + if (($pconfig['serverbridge_dhcp_start'] && !is_ipaddrv4($pconfig['serverbridge_dhcp_start']))) { + $input_errors[] = gettext("Server Bridge DHCP Start must be an IPv4 address."); + } + if (($pconfig['serverbridge_dhcp_end'] && !is_ipaddrv4($pconfig['serverbridge_dhcp_end']))) { + $input_errors[] = gettext("Server Bridge DHCP End must be an IPv4 address."); + } + if (ip2ulong($pconfig['serverbridge_dhcp_start']) > ip2ulong($pconfig['serverbridge_dhcp_end'])) { + $input_errors[] = gettext("The Server Bridge DHCP range is invalid (start higher than end)."); + } + } + if (isset($pconfig['reneg-sec']) && $pconfig['reneg-sec'] != "" && (string)((int)$pconfig['reneg-sec']) != $pconfig['reneg-sec']) { + $input_errors[] = gettext("Renegotiate time should contain a valid number of seconds."); + } + + if (!empty($pconfig['certref'])) { + foreach ($config['cert'] as $cert) { + if ($cert['refid'] == $pconfig['certref']) { + if (cert_get_purpose($cert['crt'])['id-kp-serverAuth'] == 'No') { + $input_errors[] = gettext( + sprintf('Certificate %s is not intended for server use.', $cert['descr']) + ); + } + } + } + } + + $prev_opt = (isset($id) && !empty($a_server[$id])) ? $a_server[$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.'); + } + + do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors); + + if (count($input_errors) == 0) { + // validation correct, save data + $server = array(); + + // delete(rename) old interface so a new TUN or TAP interface can be created. + if (isset($id) && $pconfig['dev_mode'] != $a_server[$id]['dev_mode']) { + openvpn_delete('server', $a_server[$id]); + } + // 1 on 1 copy of config attributes + $copy_fields = "mode,protocol,dev_mode,local_port,description,crypto,digest + ,tunnel_network,tunnel_networkv6,remote_network,remote_networkv6 + ,gwredir,local_network,local_networkv6,maxclients,compression + ,passtos,client2client,dynamic_ip,topology_subnet,local_group + ,serverbridge_dhcp,serverbridge_interface,serverbridge_dhcp_start + ,serverbridge_dhcp_end,dns_domain,dns_domain_search,dns_server1,dns_server2,dns_server3 + ,dns_server4,push_register_dns,push_block_outside_dns,ntp_server1,ntp_server2,netbios_enable + ,netbios_ntype,netbios_scope,verbosity_level,wins_server1,tlsmode + ,wins_server2,client_mgmt_port,strictusercn,reneg-sec,use-common-name,cso_login_matching"; + + foreach (explode(",", $copy_fields) as $fieldname) { + $fieldname = trim($fieldname); + if (!empty($pconfig[$fieldname]) || $pconfig[$fieldname] == '0') { + $server[$fieldname] = $pconfig[$fieldname]; + } + } + + // attributes containing some kind of logic + if ($vpnid != 0) { + $server['vpnid'] = $vpnid; + } else { + $server['vpnid'] = openvpn_vpnid_next(); + } + + if ($pconfig['disable'] == "yes") { + $server['disable'] = true; + } + if (!empty($pconfig['authmode'])) { + $server['authmode'] = implode(",", $pconfig['authmode']); + } + if (strpos($pconfig['interface'], "|") !== false) { + list($server['interface'], $server['ipaddr']) = explode("|", $pconfig['interface']); + } else { + $server['interface'] = $pconfig['interface']; + } + + $server['custom_options'] = str_replace("\r\n", "\n", $pconfig['custom_options']); + + if ($tls_mode) { + if ($pconfig['tlsmode']) { + if (!empty($pconfig['autotls_enable'])) { + $pconfig['tls'] = openvpn_create_key(); + } + $server['tls'] = base64_encode($pconfig['tls']); + } + foreach (['caref', 'crlref', 'certref', 'cert_depth'] as $cpKey) { + if (isset($pconfig[$cpKey])) { + $server[$cpKey] = $pconfig[$cpKey]; + } + } + if (isset($pconfig['mode']) && $pconfig['mode'] == "server_tls_user" && isset($server['strictusercn'])) { + $server['strictusercn'] = $pconfig['strictusercn']; + } + } else { + $server['shared_key'] = base64_encode($pconfig['shared_key']); + } + + if (isset($_POST['duplicate_cn']) && $_POST['duplicate_cn'] == "yes") { + $server['duplicate_cn'] = true; + } + + // update or add to config + if (isset($id) && $a_server[$id]) { + $a_server[$id] = $server; + } else { + $a_server[] = $server; + } + + write_config(); + + openvpn_configure_single($server['vpnid']); + + header(url_safe('Location: /vpn_openvpn_server.php')); + exit; + } elseif (!empty($pconfig['authmode'])) { + $pconfig['authmode'] = implode(",", $pconfig['authmode']); + } + } +} + +include("head.inc"); + +legacy_html_escape_form_data($pconfig); + +?> + + + + +
+
+
+ 0) { + print_input_errors($input_errors); + } + if (isset($savemsg)) { + print_info_box($savemsg); + }?> + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ /> +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + /> + . + +
+ +

.

+
+
+ + + + +
. + +
+ + + + +
. + +
+ + + + +
. + +
+ +
+ /> + . +
+ +
+ + . +
+
+ + +
+ + +
+ + + + + +
+ +
+ +
+
+ /> + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ /> + +
+ + +
+ + +
+ +
+ /> + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ /> + +
+ /> + +
+ /> + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ /> + +
+ /> + +
+ /> + +
+ +   + + + +   + + +
+
+ /> +
+ +
+ +
+ /> + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + +
+ + +
+ /> + +
  + + + + + +
+
+
+
+
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ "> + "> + + + / + + + + + + + + + + + + +
+
+
+ +
+
+
+ +