summaryrefslogtreecommitdiffstats
path: root/etc
diff options
context:
space:
mode:
authorScott Ullrich <sullrich@pfsense.org>2006-04-26 20:08:56 +0000
committerScott Ullrich <sullrich@pfsense.org>2006-04-26 20:08:56 +0000
commit8dc3ef6724f1970eed1b397ae0a4555235763393 (patch)
tree58fd513dd7e4d342b39c19079b617bfadf289b56 /etc
parentb3ed929300dbd10c2ab7a5a2a46e2100dad37617 (diff)
downloadpfsense-8dc3ef6724f1970eed1b397ae0a4555235763393.zip
pfsense-8dc3ef6724f1970eed1b397ae0a4555235763393.tar.gz
Synch with -HEAD.
Diffstat (limited to 'etc')
-rw-r--r--etc/inc/openvpn.inc299
1 files changed, 218 insertions, 81 deletions
diff --git a/etc/inc/openvpn.inc b/etc/inc/openvpn.inc
index ae7b60a..be584e9 100644
--- a/etc/inc/openvpn.inc
+++ b/etc/inc/openvpn.inc
@@ -1,49 +1,41 @@
<?php
-require('config.inc');
-
-/* $Id$ */
-/*
- openvpn.inc
- part of pfSense (www.pfSense.com)
- (C)2006 Fernando Lemos
- 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('config.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));
+ 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);
- }
+ 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;
}
@@ -51,36 +43,46 @@ function openvpn_get_ciphers($pkg) {
function openvpn_validate_input($mode, $post, $input_errors) {
$Mode = ucfirst($mode);
- $port = trim($post['port']);
- if ($port && (!is_numeric($port) || ($port < 0) || ($port > 65535)))
- $input_errors[] = 'The field \'Port\' should contain a valid port number, between 1 and 65536.';
- if ($mode == 'client') {
- $server_port = trim($post['serverport']);
- if ($server_port && (!is_numeric($server_port) || ($server_port < 0) || ($port > 65535)))
- $input_errors[] = 'The field \'Server port\' should contain a valid port number, between 1 and 65536.';
- }
-
- $reqfields = array('local_ip', 'remote_ip');
- $reqfieldsn = array('Local IP', 'Remote IP');
- foreach($reqfields as $i => $field) {
- $value = trim($post[$field]);
- if ($value and (!is_ipaddr($value)))
- $input_errors[] = "The field '{$reqfieldsn[$i]}' must contain a valid IP address";
+ 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;
}
- if ($mode == 'client') {
+ else { // Client mode
+ if ($result = openvpn_validate_port($post['serverport'], 'Server port'))
+ $input_errors[] = $result;
+
$server_addr = trim($post['serveraddr']);
- if ($value && !(is_domain($server_addr) || is_ipaddr($server_addr)))
+ 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.';
- }
- $value = trim($post['ipblock']);
- if ($value) {
- list($ip, $mask) = explode('/', $value);
- if (!is_ipaddr($ip) or !is_numeric($mask) or ($mask > 32) or ($mask < 0))
- $input_errors[] = "The field 'IP block' must contain a valid CIDR range.";
+ 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 ($settings['protocol'] != "TCP")
+ $input_errors[] = 'The protocol must be TCP to use a HTTP proxy server.';
+ }
+
}
+ 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';
@@ -134,6 +136,12 @@ function openvpn_validate_input($mode, $post, $input_errors) {
}
+function openvpn_validate_input_csc($post, $input_errors) {
+ if ($result = openvpn_validate_cidr($post['ifconfig_push'], 'Interface IP'))
+ $input_errors[] = $result;
+}
+
+
// Rewrite the settings
function openvpn_reconfigure($mode, $id) {
global $g, $config;
@@ -141,8 +149,8 @@ function openvpn_reconfigure($mode, $id) {
$settings = $config['installedpackages']["openvpn$mode"]['config'][$id];
if ($settings['disable']) return;
- // Set up the keys
- // Note that the keys' extension is the directive that goes to the config file
+ // 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')
@@ -163,13 +171,11 @@ function openvpn_reconfigure($mode, $id) {
chgrp($filename, 'nobody');
}
+ $pidfile = $g['varrun_path'] . "/openvpn_{$mode}{$id}.pid";
$proto = ($settings['protocol'] == 'UDP' ? 'udp' : "tcp-{$mode}");
- $port = $settings['port'];
- $ifconfig = $settings['local_ip'] . ' ' . $settings['remote_ip'];
- list($route_ip, $route_mask) = explode('/', $settings['ipblock']);
- $route_mask = gen_subnet_mask($route_mask);
$cipher = $settings['crypto'];
$openvpn_conf = <<<EOD
+writepid $pidfile
user nobody
group nobody
daemon
@@ -179,27 +185,131 @@ persist-tun
persist-key
dev tun
proto $proto
-port $port
-ifconfig $ifconfig
-route $route_ip $route_mask
cipher $cipher
EOD;
- if ($settings['auth_method'] == 'pki')
- $openvpn_conf .= "tls-$mode\n";
+
+ // Mode-specific stuff
+ if ($mode == 'server') {
+ list($ip, $mask) = explode('/', $settings['addresspool']);
+ $mask = gen_subnet_mask($mask);
+
+ // Using a shared key or not dynamically assigning IPs to the clients
+ if (($settings['auth_method'] == 'shared_key') || ($settings['nopool'] == 'on')) {
+ if ($settings['auth_method'] == 'pki') $openvpn_conf .= "tls-server\n";
+
+ $baselong = ip2long($ip) & ip2long($mask);
+ $ip1 = long2ip($baselong + 1);
+ $ip2 = long2ip($baselong + 2);
+ $openvpn_conf .= "ifconfig $ip1 $ip2\n";
+ }
+ // Using a PKI
+ else if ($settings['auth_method'] == 'pki') {
+ if ($settings['client2client']) $openvpn_conf .= "client-to-client\n";
+ $openvpn_conf .= "server $ip $mask\n";
+ $csc_dir = "{$g['varetc_path']}/openvpn_csc";
+ $openvpn_conf .= "client-config-dir $csc_dir\n";
+ }
+
+ // We can push routes
+ if (!empty($settings['local_network'])) {
+ list($ip, $mask) = explode('/', $settings['local_network']);
+ $mask = gen_subnet_mask($mask);
+ $openvpn_conf .= "push \"route $ip $mask\"\n";
+ }
+
+ // The port we'll listen at
+ $openvpn_conf .= "lport {$settings['local_port']}\n";
+ }
+
+ else { // $mode == client
+ // The remote server
+ $openvpn_conf .= "remote {$settings['serveraddr']} {$settings['serverport']}\n";
+
+ if ($settings['auth_method'] == 'pki') $openvpn_conf .= "client\n";
+
+ if (!empty($settings['interface_ip'])) {
+ // Configure the IPs according to the address pool
+ list($ip, $mask) = explode('/', $settings['interface_ip']);
+ $mask = gen_subnet_mask($mask);
+ $baselong = ip2long($ip) & ip2long($mask);
+ $ip1 = long2ip($baselong + 1);
+ $ip2 = long2ip($baselong + 2);
+ $openvpn_conf .= "ifconfig $ip2 $ip1\n";
+ }
+ if (isset($settings['proxy_hostname']) && $settings['proxy_hostname'] != "") {
+ /* ;http-proxy-retry # retry on connection failures */
+ $openvpn_conf .= "http-proxy {$settings['proxy_hostname']} {$settings['proxy_port']}\n";
+ }
+ }
+
+ // Add the routes if they're set
+ if (!empty($settings['remote_network'])) {
+ list($ip, $mask) = explode('/', $settings['remote_network']);
+ $mask = gen_subnet_mask($mask);
+ $openvpn_conf .= "route $ip $mask\n";
+ }
// Write the settings for the keys
foreach ($keys as $key)
$openvpn_conf .= $key['directive'] . ' ' . $base_file . $key['ext'] . "\n";
- if ($mode == 'client') $openvpn_conf .= 'remote ' . $settings['serveraddr'] . ' ' .$settings['serverport'] . "\n";
if ($settings['use_lzo']) $openvpn_conf .= "comp-lzo\n";
- if ($settings['dynamic_ip']) $openvpn_conf .= "persist-remote-ip\n";
+
+ if ($settings['dynamic_ip']) {
+ $openvpn_conf .= "persist-remote-ip\n";
+ $openvpn_conf .= "float\n";
+ }
+
+ if (!empty($settings['custom_options'])) {
+ $options = explode(';', $settings['custom_options']);
+ if (is_array($options)) {
+ foreach ($options as $option)
+ $openvpn_conf .= "$option\n";
+ }
+ else {
+ $openvpn_conf .= "{$settings['custom_options']}\n";
+ }
+ }
file_put_contents($g['varetc_path'] . "/openvpn_{$mode}{$id}.conf", $openvpn_conf);
}
+function openvpn_resync_csc($id) {
+ global $g, $config;
+
+ $settings = $config['installedpackages']['openvpncsc']['config'][$id];
+
+ if ($settings['disable'] == 'on') return;
+
+ $conf = '';
+ if ($settings['block'] == 'on') $conf .= "disable\n";
+ if ($settings['push_reset'] == 'on') $conf .= "push-reset\n";
+ if (!empty($settings['ifconfig_push'])) {
+ list($ip, $mask) = explode('/', $settings['ifconfig_push']);
+ $baselong = ip2long($ip) & gen_subnet_mask_long($mask);
+ $conf .= 'ifconfig-push ' . long2ip($baselong + 1) . ' ' . long2ip($baselong + 2) . "\n";
+ }
+ if (!empty($settings['custom_options'])) {
+ $options = explode(';', $settings['custom_options']);
+ if (is_array($options)) {
+ foreach ($options as $option)
+ $conf .= "$option\n";
+ }
+ else {
+ $conf .= "{$settings['custom_options']}\n";
+ }
+ }
+
+ openvpn_create_cscdir();
+ $filename = "{$g['varetc_path']}/openvpn_csc/{$settings['commonname']}";
+ file_put_contents($filename, $conf);
+ chown($filename, 'nobody');
+ chgrp($filename, 'nogroup');
+}
+
+
function openvpn_restart($mode, $id) {
global $g, $config;
@@ -211,7 +321,7 @@ function openvpn_restart($mode, $id) {
if ($settings['disable']) return;
$configfile = $g['varetc_path'] . "/openvpn_{$mode}{$id}.conf";
- mwexec("openvpn --config $configfile --writepid $pidfile");
+ mwexec("openvpn --config $configfile");
}
@@ -221,6 +331,16 @@ function openvpn_resync($mode, $id) {
openvpn_restart($mode, $id);
}
+function openvpn_create_cscdir() {
+ global $g;
+
+ $csc_dir = "{$g['varetc_path']}/openvpn_csc";
+ if (!is_dir($csc_dir)) {
+ mkdir($csc_dir);
+ chown($csc_dir, 'nobody');
+ chgrp($csc_dir, 'nobody');
+ }
+}
// Resync and restart all VPNs
function openvpn_resync_all() {
@@ -232,6 +352,12 @@ function openvpn_resync_all() {
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);
+ }
}
@@ -250,9 +376,20 @@ function onAuthMethodChanged() {
EOD;
if ($mode == 'server') {
- $javascript .= "\tdocument.iform.dh_params.disabled = endis;\n";
- $javascript .= "\tdocument.iform.crl.disabled = endis;\n";
+ $javascript .= <<<EOD
+ document.iform.dh_params.disabled = endis;
+ document.iform.crl.disabled = endis;
+ document.iform.nopool.disabled = endis;
+ document.iform.local_network.disabled = endis;
+ document.iform.client2client.disabled = endis;
+
+EOD;
+ }
+
+ else { // Client mode
+ $javascript .= "\tdocument.iform.remote_network.disabled = !endis;\n";
}
+
$javascript .= <<<EOD
}
//-->
@@ -274,4 +411,4 @@ function openvpn_print_javascript2() {
EOD;
print($javascript);
}
-?>
+?> \ No newline at end of file
OpenPOWER on IntegriCloud