diff options
-rw-r--r-- | src/etc/inc/openvpn.inc | 49 | ||||
-rw-r--r-- | src/usr/local/www/vpn_openvpn_server.php | 32 |
2 files changed, 76 insertions, 5 deletions
diff --git a/src/etc/inc/openvpn.inc b/src/etc/inc/openvpn.inc index c290d58..81e3c09 100644 --- a/src/etc/inc/openvpn.inc +++ b/src/etc/inc/openvpn.inc @@ -76,8 +76,21 @@ $openvpn_verbosity_level = array( global $openvpn_dh_lengths; $openvpn_dh_lengths = array( - 1024, 2048, 3072, 4096, 7680, 8192, 15360, 16384 + 1024 => "1024 bit", + 2048 => "2048 bit", + 3072 => "3072 bit", + 4096 => "4096 bit", + 7680 => "7680 bit", + 8192 => "8192 bit", + 15360 => "15360 bit", + 16384 => "16384 bit", + "none" => "ECDH Only" ); +foreach ($openvpn_dh_lengths as $idx => $dhlen) { + if (is_numeric($idx) && !file_exists("/etc/dh-parameters.{$idx}")) { + unset($openvpn_dh_lengths[$idx]); + } +} global $openvpn_cert_depths; $openvpn_cert_depths = array( @@ -386,6 +399,25 @@ function openvpn_get_cipherlist() { return $ciphers; } +function openvpn_get_curvelist() { + + $curves = array(); + $curves["none"] = gettext("Use Default"); + $curve_out = shell_exec('/usr/local/sbin/openvpn --show-curves | /usr/bin/grep -v \'Available Elliptic curves\''); + $curve_lines = explode("\n", trim($curve_out)); + sort($curve_lines); + foreach ($curve_lines as $line) { + $line = trim($line); + $curves[$line] = $line; + } + return $curves; +} + +function openvpn_validate_curve($curve) { + $curves = openvpn_get_curvelist(); + return array_key_exists($curve, $curves); +} + function openvpn_get_digestlist() { $digests = array(); @@ -1019,7 +1051,20 @@ function openvpn_reconfigure($mode, $settings) { openvpn_add_keyfile($cert['prv'], $conf, $mode_id, "key"); } if ($mode == 'server') { - $conf .= "dh {$g['etc_path']}/dh-parameters.{$settings['dh_length']}\n"; + if (is_numeric($settings['dh_length'])) { + if (!in_array($pconfig['dh_length'], array_keys($openvpn_dh_lengths))) { + /* The user selected a DH parameter length that does not have a corresponding file. */ + log_error(gettext("Failed to construct OpenVPN server configuration. The selected DH Parameter length cannot be used.")); + return; + } + $dh_file = "{$g['etc_path']}/dh-parameters.{$settings['dh_length']}"; + } else { + $dh_file = $settings['dh_length']; + } + $conf .= "dh {$dh_file}\n"; + if (!empty($settings['ecdh_curve']) && ($settings['ecdh_curve'] != "none") && openvpn_validate_curve($settings['ecdh_curve'])) { + $conf .= "ecdh-curve {$settings['ecdh_curve']}\n"; + } } if (!empty($settings['crlref'])) { $crl = lookup_crl($settings['crlref']); diff --git a/src/usr/local/www/vpn_openvpn_server.php b/src/usr/local/www/vpn_openvpn_server.php index 7503095..433b689 100644 --- a/src/usr/local/www/vpn_openvpn_server.php +++ b/src/usr/local/www/vpn_openvpn_server.php @@ -138,6 +138,7 @@ if ($_GET['act'] == "edit") { $pconfig['crlref'] = $a_server[$id]['crlref']; $pconfig['certref'] = $a_server[$id]['certref']; $pconfig['dh_length'] = $a_server[$id]['dh_length']; + $pconfig['ecdh_curve'] = $a_server[$id]['ecdh_curve']; if (isset($a_server[$id]['cert_depth'])) { $pconfig['cert_depth'] = $a_server[$id]['cert_depth']; } else { @@ -396,6 +397,15 @@ if ($_POST) { if (empty(trim($pconfig['certref']))) { $input_errors[] = gettext("The selected certificate is not valid"); } + + if (!empty($pconfig['dh_length']) && !in_array($pconfig['dh_length'], array_keys($openvpn_dh_lengths))) { + $input_errors[] = gettext("The specified DH Parameter length is invalid or the DH file does not exist."); + } + + if (!empty($pconfig['ecdh_curve']) && !openvpn_validate_curve($pconfig['ecdh_curve'])) { + $input_errors[] = gettext("The specified ECDH Curve is invalid."); + } + $reqdfields = explode(" ", "caref certref"); $reqdfieldsn = array(gettext("Certificate Authority"), gettext("Certificate")); } elseif (!$pconfig['autokey_enable']) { @@ -466,6 +476,7 @@ if ($_POST) { $server['crlref'] = $pconfig['crlref']; $server['certref'] = $pconfig['certref']; $server['dh_length'] = $pconfig['dh_length']; + $server['ecdh_curve'] = $pconfig['ecdh_curve']; $server['cert_depth'] = $pconfig['cert_depth']; if ($pconfig['mode'] == "server_tls_user") { $server['strictusercn'] = $pconfig['strictusercn']; @@ -761,11 +772,18 @@ if ($act=="new" || $act=="edit"): $section->addInput(new Form_Select( 'dh_length', - 'DH Parameter length (bits)', + 'DH Parameter Length', $pconfig['dh_length'], - array_combine($openvpn_dh_lengths, $openvpn_dh_lengths) + $openvpn_dh_lengths ))->setHelp(count($a_cert) ? '':sprintf('No Certificates defined. One may be created here: %s', '<a href="system_camanager.php">System > Cert. Manager</a>')); + $section->addInput(new Form_Select( + 'ecdh_curve', + 'ECDH Curve', + $pconfig['ecdh_curve'], + openvpn_get_curvelist() + )); + if (!$pconfig['shared_key']) { $section->addInput(new Form_Checkbox( 'autokey_enable', @@ -1202,7 +1220,12 @@ else: <?=htmlspecialchars($server['tunnel_networkv6'])?> </td> <td> - <?=sprintf("Crypto: %s/%s<br/>D-H Params: %d bits", $server['crypto'], $server['digest'], $server['dh_length'])?><br /> + <?=sprintf("Crypto: %s/%s", $server['crypto'], $server['digest']);?> + <?php if (is_numeric($server['dh_length'])): ?> + <?=sprintf("<br/>D-H Params: %d bits", $server['dh_length']);?> + <?php elseif ($server['dh_length'] == "none"): ?> + <br />D-H Disabled, using ECDH Only + <?php endif; ?> </td> <td> <?=htmlspecialchars(sprintf('%s (%s)', $server['description'], $server['dev_mode']))?> @@ -1269,6 +1292,7 @@ events.push(function() { hideInput('tls', false); hideInput('certref', false); hideInput('dh_length', false); + hideInput('ecdh_curve', false); hideInput('cert_depth', false); hideCheckbox('strictusercn', true); hideCheckbox('autokey_enable', true); @@ -1279,6 +1303,7 @@ events.push(function() { hideInput('tls', false); hideInput('certref', false); hideInput('dh_length', false); + hideInput('ecdh_curve', false); hideInput('cert_depth', false); hideCheckbox('strictusercn', false); hideCheckbox('autokey_enable', true); @@ -1294,6 +1319,7 @@ events.push(function() { hideInput('certref', true); hideCheckbox('tlsauth_enable', true); hideInput('dh_length', true); + hideInput('ecdh_curve', true); hideInput('cert_depth', true); hideCheckbox('strictusercn', true); hideCheckbox('autokey_enable', true); |