From 7d9e42f0b179417650e9b336fdf925b058863250 Mon Sep 17 00:00:00 2001 From: mfuchs Date: Tue, 19 May 2009 21:30:08 +0200 Subject: add OpenVPN-TLS, etc... enhancements package for 1.2.x --- config/ovpnenhance/openvpn.inc_tls | 668 +++++++++++++++++++++++++++++++++++++ 1 file changed, 668 insertions(+) create mode 100644 config/ovpnenhance/openvpn.inc_tls (limited to 'config/ovpnenhance/openvpn.inc_tls') diff --git a/config/ovpnenhance/openvpn.inc_tls b/config/ovpnenhance/openvpn.inc_tls new file mode 100644 index 00000000..9ea4c7da --- /dev/null +++ b/config/ovpnenhance/openvpn.inc_tls @@ -0,0 +1,668 @@ + + All rights reserved. + + Copyright (C) 2004 Peter Curran (peter@closeconsultants.com). + 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 notices, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notices, 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('config.inc'); +require_once('pfsense-utils.inc'); +require_once('util.inc'); + +// Return the list of ciphers OpenVPN supports +function openvpn_get_ciphers($pkg) { + foreach ($pkg['fields']['field'] as $i => $field) { + if ($field['fieldname'] == 'crypto') break; + } + $option_array = &$pkg['fields']['field'][$i]['options']['option']; + $ciphers_out = shell_exec('openvpn --show-ciphers | grep "default key" | awk \'{print $1, "(" $2 "-" $3 ")";}\''); + $ciphers = explode("\n", trim($ciphers_out)); + sort($ciphers); + foreach ($ciphers as $cipher) { + $value = explode(' ', $cipher); + $value = $value[0]; + $option_array[] = array('value' => $value, 'name' => $cipher); + } +} + + +function openvpn_validate_port($value, $name) { + $value = trim($value); + if (!empty($value) && !(is_numeric($value) && ($value > 0) && ($value < 65535))) + return "The field '$name' must contain a valid port, ranging from 0 to 65535."; + return false; +} + + +function openvpn_validate_cidr($value, $name) { + $value = trim($value); + if (!empty($value)) { + list($ip, $mask) = explode('/', $value); + if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0)) + return "The field '$name' must contain a valid CIDR range."; + } + return false; +} + + +// Do the input validation +function openvpn_validate_input($mode, $post, $input_errors) { + $Mode = ucfirst($mode); + + if ($mode == 'server') { + if ($result = openvpn_validate_port($post['local_port'], 'Local port')) + $input_errors[] = $result; + + if ($result = openvpn_validate_cidr($post['addresspool'], 'Address pool')) + $input_errors[] = $result; + + if ($result = openvpn_validate_cidr($post['local_network'], 'Local network')) + $input_errors[] = $result; + +/* check for port in use - update of existing entries not possible because $_GET['act'] is not passed from pkg_edit.php :-( mfuchs + $portinuse = shell_exec('sockstat | grep '.$post['local_port'].' | grep '.strtolower($post['protocol'])); + if (!empty($portinuse)) + $input_errors[] = 'The port '.$post['local_port'].'/'.strtolower($post['protocol']).' is already in use.'; +*/ + + if (!empty($post['dhcp_dns'])) { + $servers = explode(';', $post['dhcp_dns']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: DNS-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + if (!empty($post['dhcp_wins'])) { + $servers = explode(';', $post['dhcp_wins']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: WINS-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + if (!empty($post['dhcp_nbdd'])) { + $servers = explode(';', $post['dhcp_nbdd']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: NBDD-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + if (!empty($post['dhcp_ntp'])) { + $servers = explode(';', $post['dhcp_ntp']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: NTP-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + if (isset($post['maxclients']) && $post['maxclients'] != "") { + if (!is_numeric($post['maxclients'])) + $input_errors[] = 'The field \'Maximum clients\' must be numeric.'; + } + + } + + else { // Client mode + if ($result = openvpn_validate_port($post['serverport'], 'Server port')) + $input_errors[] = $result; + + $server_addr = trim($post['serveraddr']); + if (!empty($value) && !(is_domain($server_addr) || is_ipaddr($server_addr))) + $input_errors[] = 'The field \'Server address\' must contain a valid IP address or domain name.'; + + if ($result = openvpn_validate_cidr($post['interface_ip'], 'Interface IP')) + $input_errors[] = $result; + + if ($post['auth_method'] == 'shared_key') { + if (empty($post['interface_ip'])) + $input_errors[] = 'The field \'Interface IP\' is required.'; + } + if (isset($post['proxy_hostname']) && $post['proxy_hostname'] != "") { + if (!is_domain($post['proxy_hostname']) || is_ipaddr($post['proxy_hostname'])) + $input_errors[] = 'The field \'Proxy Host\' must contain a valid IP address or domain name.'; + if (!is_port($post['proxy_port'])) + $input_errors[] = 'The field \'Proxy port\' must contain a valid port number.'; + if ($post['protocol'] != "TCP") + $input_errors[] = 'The protocol must be TCP to use a HTTP proxy server.'; + } + if (isset($post['use_shaper']) && $post['use_shaper'] != "") { + if (!is_numeric($post['use_shaper'])) + $input_errors[] = 'The field \'Limit outgoing bandwidth\' must be numeric.'; + } + + } + + if ($result = openvpn_validate_cidr($post['remote_network'], 'Remote network')) + $input_errors[] = $result; + + if ($_POST['auth_method'] == 'shared_key') { + $reqfields[] = 'shared_key'; + $reqfieldsn[] = 'Shared key'; + } + else { + $req = explode(' ', "ca_cert {$mode}_cert {$mode}_key"); + $reqn = array( 'CA certificate', + ucfirst($mode) . ' certificate', + ucfirst($mode) . ' key'); + $reqfields = array_merge($reqfields, $req); + $reqfieldsn = array_merge($reqfieldsn, $reqn); + if ($mode == 'server') { + $reqfields[] = 'dh_params'; + $reqfieldsn[] = 'DH parameters'; + } + } + do_input_validation($post, $reqfields, $reqfieldsn, &$input_errors); + + $value = trim($post['shared_key']); + $items = array(); + + if ($_POST['auth_method'] == 'shared_key') { + $items[] = array( 'field' => 'shared_key', + 'string' => 'OpenVPN Static key V1', + 'name' => 'Shared key'); + } + else { + $items[] = array( 'field' => 'ca_cert', + 'string' => 'CERTIFICATE', + 'name' => 'CA certificate'); + $items[] = array( 'field' => "{$mode}_cert", + 'string' => 'CERTIFICATE', + 'name' => "$Mode certificate"); + $items[] = array( 'field' => "{$mode}_key", + 'string' => 'RSA PRIVATE KEY', + 'name' => "$Mode key"); + $items[] = array( 'field' => 'tls', + 'string' => 'OpenVPN Static key V1', + 'name' => 'TLS'); + if ($mode == 'server') { + $items[] = array( 'field' => 'dh_params', + 'string' => 'DH PARAMETERS', + 'name' => 'DH parameters'); + $items[] = array( 'field' => 'crl', + 'string' => 'X509 CRL', + 'name' => 'CRL'); + } + } + foreach ($items as $item) { + $value = trim($_POST[$item['field']]); + $string = $item['string']; + if ($value && (!strstr($value, "-----BEGIN {$string}-----") || !strstr($value, "-----END {$string}-----"))) + $input_errors[] = "The field '{$item['name']}' does not appear to be valid"; + } +} + + +function openvpn_validate_input_csc($post, $input_errors) { + if ($result = openvpn_validate_cidr($post['ifconfig_push'], 'Interface IP')) + $input_errors[] = $result; + + if ($post['push_reset'] != 'on') { + if (!empty($post['dhcp_domainname'])) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + elseif (!empty($post['dhcp_dns'])) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + elseif (!empty($post['dhcp_wins'])) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + elseif (!empty($post['dhcp_nbdd'])) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + elseif (!empty($post['dhcp_ntp'])) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + elseif ($post['dhcp_nbttype']) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + elseif (!empty($post['dhcp_nbtscope'])) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + elseif ($post['dhcp_nbtdisable']) + $input_errors[] = 'It makes no sense to unselect push reset and configure dhcp-options'; + + } + else { + + if (!empty($post['dhcp_dns'])) { + $servers = explode(';', $post['dhcp_dns']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: DNS-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + if (!empty($post['dhcp_wins'])) { + $servers = explode(';', $post['dhcp_wins']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: WINS-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + if (!empty($post['dhcp_nbdd'])) { + $servers = explode(';', $post['dhcp_nbdd']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: NBDD-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + if (!empty($post['dhcp_ntp'])) { + $servers = explode(';', $post['dhcp_ntp']); + foreach ($servers as $server) if (!is_ipaddr($server)) + {$input_errors[] = 'The field \'DHCP-Opt.: NTP-Server\' must contain a valid IP address and no whitespaces.'; + break;}} + +}} + +// Rewrite the settings +function openvpn_reconfigure($mode, $id) { + global $g, $config; + + $settings = $config['installedpackages']["openvpn$mode"]['config'][$id]; + if ($settings['disable']) return; + + $lport = 1194 + $id; + + // Set the keys up + // Note that the keys' extension is also the directive that goes to the config file + $base_file = $g['varetc_path'] . "/openvpn_{$mode}{$id}."; + $keys = array(); + if ($settings['auth_method'] == 'shared_key') + $keys[] = array('field' => 'shared_key', 'ext' => 'secret', 'directive' => 'secret'); + else { + $keys[] = array('field' => 'ca_cert', 'ext' => 'ca', 'directive' => 'ca'); + $keys[] = array('field' => "{$mode}_cert", 'ext' => 'cert', 'directive' => 'cert'); + $keys[] = array('field' => "{$mode}_key", 'ext' => 'key', 'directive' => 'key'); + if ($mode == 'server') + $keys[] = array('field' => 'dh_params', 'ext' => 'dh', 'directive' => 'dh'); + if ($settings['crl']) + $keys[] = array('field' => 'crl', 'ext' => 'crl', 'directive' => 'crl-verify'); + if ($settings['tls']) + $keys[] = array('field' => 'tls', 'ext' => 'tls', 'directive' => 'tls-auth'); + + } + foreach($keys as $key) { + $filename = $base_file . $key['ext']; + file_put_contents($filename, base64_decode($settings[$key['field']])); + chown($filename, 'nobody'); + chgrp($filename, 'nobody'); + } + + $pidfile = $g['varrun_path'] . "/openvpn_{$mode}{$id}.pid"; + $proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}"); + $cipher = $settings['crypto']; + $openvpn_conf = << $settings) + openvpn_resync($mode, $id); + } + } + + openvpn_create_cscdir(); + if (is_array($config['installedpackages']['openvpncsc']['config'])) { + foreach ($config['installedpackages']['openvpncsc']['config'] as $id => $csc) + openvpn_resync_csc($id); + } + + /* give speedy machines time to settle */ + sleep(5); + + /* reload the filter policy */ + filter_configure(); + +} + +function openvpn_print_javascript($mode) { + $javascript = << + + + +EOD; + print($javascript); +} + + +function openvpn_print_javascript2() { + $javascript = << + + + +EOD; + print($javascript); +} +?> -- cgit v1.2.3