diff options
author | jim-p <jimp@pfsense.org> | 2011-10-10 17:18:22 -0400 |
---|---|---|
committer | jim-p <jimp@pfsense.org> | 2011-10-27 10:29:38 -0400 |
commit | 77ed2f4c9f67af9c041ae5de3dcf82455238fdb7 (patch) | |
tree | bb547a99f575145841359005adbb00039e5c1036 | |
parent | 3f9c177572d5d2c2995b5e6a81679fd5bb7ce6ec (diff) | |
download | pfsense-77ed2f4c9f67af9c041ae5de3dcf82455238fdb7.zip pfsense-77ed2f4c9f67af9c041ae5de3dcf82455238fdb7.tar.gz |
Add GUI option to limit the certificate depth allowed when OpenVPN clients are connecting.
-rw-r--r-- | etc/inc/openvpn.inc | 18 | ||||
-rw-r--r-- | etc/inc/openvpn.tls-verify.php | 77 | ||||
-rw-r--r-- | usr/local/www/vpn_openvpn_server.php | 30 |
3 files changed, 125 insertions, 0 deletions
diff --git a/etc/inc/openvpn.inc b/etc/inc/openvpn.inc index ce97469..b34d442 100644 --- a/etc/inc/openvpn.inc +++ b/etc/inc/openvpn.inc @@ -71,6 +71,14 @@ $openvpn_dev_mode = array("tun", "tap"); $openvpn_dh_lengths = array( 1024, 2048, 4096 ); +$openvpn_cert_depths = array( + 1 => "One (Client+Server)", + 2 => "Two (Client+Intermediate+Server)", + 3 => "Three (Client+2xIntermediate+Server)", + 4 => "Four (Client+3xIntermediate+Server)", + 5 => "Five (Client+4xIntermediate+Server)" +); + $openvpn_server_modes = array( 'p2p_tls' => "Peer to Peer ( SSL/TLS )", 'p2p_shared_key' => "Peer to Peer ( Shared Key )", @@ -430,6 +438,16 @@ function openvpn_reconfigure($mode, $settings) { } break; } + if (is_numeric($settings['cert_depth'])) { + $sed = ""; + $cert = lookup_cert($settings['certref']); + $servercn = cert_get_cn($cert['crt']); + $sed .= "\$server_cn = \"{$servercn}\";\\\n"; + $sed .= "\$allowed_depth = {$settings['cert_depth']};\\\n"; + mwexec("/bin/cat /etc/inc/openvpn.tls-verify.php | /usr/bin/sed 's/\/\/<template>/{$sed}/g' > {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php"); + mwexec("/bin/chmod a+x {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php"); + $conf .= "tls-verify {$g['varetc_path']}/openvpn/{$mode_id}.tls-verify.php\n"; + } // The local port to listen on $conf .= "lport {$settings['local_port']}\n"; diff --git a/etc/inc/openvpn.tls-verify.php b/etc/inc/openvpn.tls-verify.php new file mode 100644 index 0000000..dd01645 --- /dev/null +++ b/etc/inc/openvpn.tls-verify.php @@ -0,0 +1,77 @@ +#!/usr/local/bin/php -f +<?php +/* $Id$ */ +/* + openvpn.tls-verify.php + + Copyright (C) 2011 Jim Pingle + 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. + + DISABLE_PHP_LINT_CHECKING +*/ +/* + pfSense_BUILDER_BINARIES: + pfSense_MODULE: openvpn +*/ +/* + * OpenVPN calls this script to validate a certificate + * This script is called ONCE per DEPTH of the certificate chain + * Normal operation would have two runs - one for the server certificate + * and one for the client certificate. Beyond that, you're dealing with + * intermediates. + */ + +require_once("globals.inc"); +require_once("config.inc"); +require_once("interfaces.inc"); + +openlog("openvpn", LOG_ODELAY, LOG_AUTH); + +/* read data from command line */ +$cert_depth = intval($argv[1]); +$cert_subject = $argv[2]; + +/* Reserved for future use in case we decide to verify CNs and such as well +$subj = explode("/", $cert_subject); +foreach ($subj at $s) { + list($n, $v) = explode("=", $s); + if ($n == "CN") + $common_name = $v; +} +*/ + +/* Replaced by sed with proper variables used below ( $server_cn and $allowed_depth ). */ +//<template> + +if (isset($allowed_depth) && ($cert_depth > $allowed_depth)) { + syslog(LOG_WARNING, "Certificate depth {$cert_depth} exceeded max allowed depth of {$allowed_depth}.\n"); + exit(1); +} + +// Debug +syslog(LOG_WARNING, "Found certificate {$argv[2]} with depth {$cert_depth}\n"); + +exit(0); + +?> diff --git a/usr/local/www/vpn_openvpn_server.php b/usr/local/www/vpn_openvpn_server.php index b08c481..fa3cc24 100644 --- a/usr/local/www/vpn_openvpn_server.php +++ b/usr/local/www/vpn_openvpn_server.php @@ -123,6 +123,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['cert_depth'] = $a_server[$id]['cert_depth']; if ($pconfig['mode'] == "server_tls_user") $pconfig['strictusercn'] = $a_server[$id]['strictusercn']; } else @@ -315,6 +316,7 @@ if ($_POST) { $server['crlref'] = $pconfig['crlref']; $server['certref'] = $pconfig['certref']; $server['dh_length'] = $pconfig['dh_length']; + $server['cert_depth'] = $pconfig['cert_depth']; if ($pconfig['mode'] == "server_tls_user") $server['strictusercn'] = $pconfig['strictusercn']; } else { @@ -404,6 +406,7 @@ function mode_change() { document.getElementById("tls_crl").style.display=""; document.getElementById("tls_cert").style.display=""; document.getElementById("tls_dh").style.display=""; + document.getElementById("cert_depth").style.display=""; document.getElementById("strictusercn").style.display="none"; document.getElementById("psk").style.display="none"; break; @@ -413,6 +416,7 @@ function mode_change() { document.getElementById("tls_crl").style.display=""; document.getElementById("tls_cert").style.display=""; document.getElementById("tls_dh").style.display=""; + document.getElementById("cert_depth").style.display=""; document.getElementById("strictusercn").style.display=""; document.getElementById("psk").style.display="none"; break; @@ -422,6 +426,7 @@ function mode_change() { document.getElementById("tls_crl").style.display="none"; document.getElementById("tls_cert").style.display="none"; document.getElementById("tls_dh").style.display="none"; + document.getElementById("cert_depth").style.display="none"; document.getElementById("strictusercn").style.display="none"; document.getElementById("psk").style.display=""; break; @@ -917,6 +922,31 @@ if ($savemsg) </select> </td> </tr> + <tr id="cert_depth"> + <td width="22%" valign="top" class="vncell"><?=gettext("Certificate Depth"); ?></td> + <td width="78%" class="vtable"> + <table border="0" cellpadding="2" cellspacing="0"> + <tr><td> + <select name="cert_depth" class="formselect"> + <option value="">Do Not Check</option> + <?php + foreach ($openvpn_cert_depths as $depth => $depthdesc): + $selected = ''; + if ($depth == $pconfig['cert_depth']) + $selected = ' selected'; + ?> + <option value="<?= $depth ?>" <?= $selected ?>><?= $depthdesc ?></option> + <?php endforeach; ?> + </select> + </td></tr> + <tr><td> + <span class="vexpl"> + <?=gettext("When a certificate-based client logs in, do not accept certificates below this depth. Useful for denying certificates made with intermediate CAs generated from the same CA as the server."); ?> + </span> + </td></tr> + </table> + </td> + </tr> <tr id="strictusercn"> <td width="22%" valign="top" class="vncell"><?=gettext("Strict User/CN Matching"); ?></td> <td width="78%" class="vtable"> |