summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErmal <eri@pfsense.org>2014-09-12 19:22:48 +0200
committerErmal <eri@pfsense.org>2014-09-12 19:22:48 +0200
commitfa4e059e17708cc12f258b636a7b701a99528c84 (patch)
tree88e3d2bc6737f153dd48b9e524607e5644943a4f
parente373e4cd1cd9557f5ad6ec87c869d44b779357b1 (diff)
downloadpfsense-fa4e059e17708cc12f258b636a7b701a99528c84.zip
pfsense-fa4e059e17708cc12f258b636a7b701a99528c84.tar.gz
Provide a first implementation of EAP-TLS authentication with IKEv2. It is a start and might not work on all cases
-rw-r--r--etc/inc/ipsec.inc1
-rw-r--r--etc/inc/vpn.inc82
-rw-r--r--usr/local/www/vpn_ipsec_phase1.php165
3 files changed, 134 insertions, 114 deletions
diff --git a/etc/inc/ipsec.inc b/etc/inc/ipsec.inc
index fe5cbd6..cd5c4b7 100644
--- a/etc/inc/ipsec.inc
+++ b/etc/inc/ipsec.inc
@@ -114,6 +114,7 @@ $p1_authentication_methods = array(
'hybrid_rsa_server' => array( 'name' => 'Hybrid RSA + Xauth', 'mobile' => true ),
'xauth_rsa_server' => array( 'name' => 'Mutual RSA + Xauth', 'mobile' => true ),
'xauth_psk_server' => array( 'name' => 'Mutual PSK + Xauth', 'mobile' => true ),
+ 'eap-tls' => array( 'name' => 'EAP-TLS', 'mobile' => false ),
'rsasig' => array( 'name' => 'Mutual RSA', 'mobile' => false ),
'pre_shared_key' => array( 'name' => 'Mutual PSK', 'mobile' => false ) );
diff --git a/etc/inc/vpn.inc b/etc/inc/vpn.inc
index 581479c..804a27c 100644
--- a/etc/inc/vpn.inc
+++ b/etc/inc/vpn.inc
@@ -49,7 +49,7 @@ function vpn_ipsec_configure_loglevels($forconfig = false)
$cfgtext = array();
foreach ($ipsec_loglevels as $lkey => $ldescr) {
if (!isset($config['ipsec']["ipsec_{$lkey}"]) && !$forconfig)
- mwexec("/usr/local/sbin/ipsec stroke loglevel {$lkey} -- -1", false);
+ mwexec("/usr/local/sbin/ipsec stroke loglevel {$lkey} -1", false);
else if (is_numeric($config['ipsec']["ipsec_{$lkey}"]) &&
intval($config['ipsec']["ipsec_{$lkey}"]) >= 1 && intval($config['ipsec']["ipsec_{$lkey}"]) <= 5)
$forconfig ? $cfgtext[] = "${lkey} = " . (intval($config['ipsec']["ipsec_{$lkey}"]) - 1) :
@@ -128,6 +128,10 @@ function vpn_ipsec_configure($ipchg = false)
return 0;
} else {
+ $certpath = "{$g['varetc_path']}/ipsec/ipsec.d/certs";
+ $capath = "{$g['varetc_path']}/ipsec/ipsec.d/cacerts";
+ $keypath = "{$g['varetc_path']}/ipsec/ipsec.d/private";
+
mwexec("/sbin/ifconfig enc0 up");
set_single_sysctl("net.inet.ip.ipsec_in_use", "1");
/* needed for config files */
@@ -135,14 +139,14 @@ function vpn_ipsec_configure($ipchg = false)
mkdir("{$g['varetc_path']}/ipsec");
if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d"))
mkdir("{$g['varetc_path']}/ipsec/ipsec.d");
- if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/cacerts"))
- mkdir("{$g['varetc_path']}/ipsec/ipsec.d/cacerts");
- if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/private"))
- mkdir("{$g['varetc_path']}/ipsec/ipsec.d/private");
+ if (!is_dir($capath))
+ mkdir($capath);
+ if (!is_dir($keypath))
+ mkdir($keypath);
if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/crls"))
mkdir("{$g['varetc_path']}/ipsec/ipsec.d/crls");
- if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/certs"))
- mkdir("{$g['varetc_path']}/ipsec/ipsec.d/certs");
+ if (!is_dir($certpath))
+ mkdir($certpath);
if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/aacerts"))
mkdir("{$g['varetc_path']}/ipsec/ipsec.d/aacerts");
if (!is_dir("{$g['varetc_path']}/ipsec/ipsec.d/acerts"))
@@ -416,7 +420,7 @@ EOD;
log_error(sprintf(gettext("Error: Invalid certificate hash info for %s"), $ca['descr']));
continue;
}
- $fname = "{$g['varetc_path']}/ipsec/ipsec.d/cacerts/{$x509cert['hash']}.0";
+ $fname = "{$capath}/{$x509cert['hash']}.0.crt";
if (!@file_put_contents($fname, $cert)) {
log_error(sprintf(gettext("Error: Cannot write IPsec CA file for %s"), $ca['descr']));
continue;
@@ -433,47 +437,36 @@ EOD;
if (isset($ph1ent['disabled']))
continue;
- if (strstr($ph1ent['authentication_method'],'rsa')) {
+ if (strpos($ph1ent['authentication_method'], 'rsa') || $ph1ent['authentication_method'] == 'eap-tls') {
$certline = '';
- if (strstr($authmethod,'rsa')) {
-
- $ikeid = $ph1ent['ikeid'];
- $cert = lookup_cert($ph1ent['certref']);
-
- if (!$cert) {
- log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
- continue;
- }
-
- chmod($certpath, 0600);
-
- $keyfile = "cert-{$ikeid}.key";
- $keypath = "{$g['varetc_path']}/ipsec/{$keyfile}";
-
- if (!file_put_contents($keypath, base64_decode($cert['prv']))) {
- log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
- continue;
- }
+ $ikeid = $ph1ent['ikeid'];
+ $cert = lookup_cert($ph1ent['certref']);
- chmod($keypath, 0600);
- /* XXX" Traffic selectors? */
- $pskconf .= " : RSA {$keypath}\n";
+ if (!$cert) {
+ log_error(sprintf(gettext("Error: Invalid phase1 certificate reference for %s"), $ph1ent['name']));
+ continue;
+ }
- $ca = lookup_ca($ph1ent['caref']);
- if ($ca) {
- $cafile = "ca-{$ikeid}.crt";
- $capath = "{$g['varetc_path']}/ipsec/ipsec.d/cacerts/{$cafile}";
+ @chmod($certpath, 0600);
- if (!file_put_contents($capath, base64_decode($ca['crt'])))
- {
- log_error(sprintf(gettext("Error: Cannot write phase1 CA certificate file for %s"), $ph1ent['name']));
- continue;
- }
+ $ph1keyfile = "{$keypath}/cert-{$ikeid}.key";
+ if (!file_put_contents($ph1keyfile, base64_decode($cert['prv']))) {
+ log_error(sprintf(gettext("Error: Cannot write phase1 key file for %s"), $ph1ent['name']));
+ continue;
+ }
+ @chmod($ph1keyfile, 0600);
- chmod($capath, 0600);
- }
+ $ph1certfile = "{$certpath}/cert-{$ikeid}.crt";
+ if (!file_put_contents($ph1certfile, base64_decode($cert['crt']))) {
+ log_error(sprintf(gettext("Error: Cannot write phase1 certificate file for %s"), $ph1ent['name']));
+ @unlink($ph1keyfile);
+ continue;
}
+ @chmod($ph1certfile, 0600);
+
+ /* XXX" Traffic selectors? */
+ $pskconf .= " : RSA {$ph1keyfile}\n";
} else {
list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, "local");
list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, "peer", $rgmap);
@@ -595,6 +588,11 @@ EOD;
$authentication = "";
switch ($ph1ent['authentication_method']) {
+ case 'eap-tls':
+ $authentication = "leftauth=eap-tls\n\trightauth=eap-tls";
+ if (!empty($ph1ent['certref']))
+ $authentication .= "\n\tleftcert={$certpath}/cert-{$ph1ent['ikeid']}.crt";
+ break;
case 'xauth_rsa_server':
$authentication = "leftauth = pubkey\n\trightauth = pubkey";
$authentication .= "\n\trightauth2 = xauth-generic";
diff --git a/usr/local/www/vpn_ipsec_phase1.php b/usr/local/www/vpn_ipsec_phase1.php
index c8276fc..9f22a68 100644
--- a/usr/local/www/vpn_ipsec_phase1.php
+++ b/usr/local/www/vpn_ipsec_phase1.php
@@ -5,6 +5,7 @@
Copyright (C) 2008 Shrew Soft Inc
Copyright (C) 2003-2005 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2014 Ermal LUÇI
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -79,7 +80,10 @@ if (isset($p1index) && $a_phase1[$p1index]) {
else
$pconfig['remotegw'] = $a_phase1[$p1index]['remote-gateway'];
- $pconfig['iketype'] = $a_phase1[$p1index]['iketype'];
+ if (empty($a_phase1[$p1index]['iketype']))
+ $pconfig['iketype'] = "ikev1";
+ else
+ $pconfig['iketype'] = $a_phase1[$p1index]['iketype'];
$pconfig['mode'] = $a_phase1[$p1index]['mode'];
$pconfig['protocol'] = $a_phase1[$p1index]['protocol'];
$pconfig['myid_type'] = $a_phase1[$p1index]['myid_type'];
@@ -150,6 +154,10 @@ if ($_POST) {
// Only require PSK here for normal PSK tunnels (not mobile) or xauth.
// For RSA methods, require the CA/Cert.
switch ($method) {
+ case "eap-tls":
+ if ($pconfig['iketype'] != 'ikev2')
+ $input_errors[] = gettext("EAP-TLS can only be used with IKEv2 type VPNs.");
+ break;
case "pre_shared_key":
// If this is a mobile PSK tunnel the user PSKs go on
// the PSK tab, not here, so skip the check.
@@ -405,41 +413,49 @@ function methodsel_change() {
value = document.iform.authentication_method.options[index].value;
switch (value) {
- case 'hybrid_rsa_server':
- document.getElementById('opt_psk').style.display = 'none';
- document.getElementById('opt_peerid').style.display = '';
- document.getElementById('opt_cert').style.display = '';
- document.getElementById('opt_ca').style.display = '';
- document.getElementById('opt_cert').disabled = false;
- document.getElementById('opt_ca').disabled = false;
- break;
- case 'xauth_rsa_server':
- case 'rsasig':
- document.getElementById('opt_psk').style.display = 'none';
- document.getElementById('opt_peerid').style.display = '';
- document.getElementById('opt_cert').style.display = '';
- document.getElementById('opt_ca').style.display = '';
- document.getElementById('opt_cert').disabled = false;
- document.getElementById('opt_ca').disabled = false;
- break;
+ case 'eap-tls':
+ document.getElementById('opt_psk').style.display = 'none';
+ document.getElementById('opt_peerid').style.display = '';
+ document.getElementById('opt_cert').style.display = '';
+ document.getElementById('opt_ca').style.display = '';
+ document.getElementById('opt_cert').disabled = false;
+ document.getElementById('opt_ca').disabled = false;
+ break;
+ case 'hybrid_rsa_server':
+ document.getElementById('opt_psk').style.display = 'none';
+ document.getElementById('opt_peerid').style.display = '';
+ document.getElementById('opt_cert').style.display = '';
+ document.getElementById('opt_ca').style.display = '';
+ document.getElementById('opt_cert').disabled = false;
+ document.getElementById('opt_ca').disabled = false;
+ break;
+ case 'xauth_rsa_server':
+ case 'rsasig':
+ document.getElementById('opt_psk').style.display = 'none';
+ document.getElementById('opt_peerid').style.display = '';
+ document.getElementById('opt_cert').style.display = '';
+ document.getElementById('opt_ca').style.display = '';
+ document.getElementById('opt_cert').disabled = false;
+ document.getElementById('opt_ca').disabled = false;
+ break;
<?php if ($pconfig['mobile']) { ?>
- case 'pre_shared_key':
- document.getElementById('opt_psk').style.display = 'none';
- document.getElementById('opt_peerid').style.display = 'none';
- document.getElementById('opt_cert').style.display = 'none';
- document.getElementById('opt_ca').style.display = 'none';
- document.getElementById('opt_cert').disabled = true;
- document.getElementById('opt_ca').disabled = true;
- break;
+ case 'pre_shared_key':
+ document.getElementById('opt_psk').style.display = 'none';
+ document.getElementById('opt_peerid').style.display = 'none';
+ document.getElementById('opt_cert').style.display = 'none';
+ document.getElementById('opt_ca').style.display = 'none';
+ document.getElementById('opt_cert').disabled = true;
+ document.getElementById('opt_ca').disabled = true;
+ break;
<?php } ?>
- default: /* psk modes*/
- document.getElementById('opt_psk').style.display = '';
- document.getElementById('opt_peerid').style.display = '';
- document.getElementById('opt_cert').style.display = 'none';
- document.getElementById('opt_ca').style.display = 'none';
- document.getElementById('opt_cert').disabled = true;
- document.getElementById('opt_ca').disabled = true;
- break;
+ default: /* psk modes*/
+ document.getElementById('opt_psk').style.display = '';
+ document.getElementById('opt_peerid').style.display = '';
+ document.getElementById('opt_cert').style.display = 'none';
+ document.getElementById('opt_ca').style.display = 'none';
+ document.getElementById('opt_cert').disabled = true;
+ document.getElementById('opt_ca').disabled = true;
+ break;
}
}
@@ -709,6 +725,49 @@ function dpdchkbox_change() {
</span>
</td>
</tr>
+ <tr id="opt_cert">
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("My Certificate"); ?></td>
+ <td width="78%" class="vtable">
+ <select name="certref" class="formselect">
+ <?php
+ foreach ($config['cert'] as $cert):
+ $selected = "";
+ if ($pconfig['certref'] == $cert['refid'])
+ $selected = "selected=\"selected\"";
+ ?>
+ <option value="<?=$cert['refid'];?>" <?=$selected;?>><?=$cert['descr'];?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <span class="vexpl">
+ <?=gettext("Select a certificate previously configured in the Certificate Manager"); ?>.
+ </span>
+ </td>
+ </tr>
+ <tr id="opt_ca">
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("My Certificate Authority"); ?></td>
+ <td width="78%" class="vtable">
+ <select name="caref" class="formselect">
+ <?php
+ foreach ($config['ca'] as $ca):
+ $selected = "";
+ if ($pconfig['caref'] == $ca['refid'])
+ $selected = "selected=\"selected\"";
+ ?>
+ <option value="<?=$ca['refid'];?>" <?=$selected;?>><?=$ca['descr'];?></option>
+ <?php endforeach; ?>
+ </select>
+ <br />
+ <span class="vexpl">
+ <?=gettext("Select a certificate authority previously configured in the Certificate Manager"); ?>.
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" valign="top" class="listtopic">
+ <?=gettext("Phase 1 proposal (Algorithms)"); ?>
+ </td>
+ </tr>
<tr>
<td width="22%" valign="top" class="vncellreq"><?=gettext("Encryption algorithm"); ?></td>
<td width="78%" class="vtable">
@@ -767,44 +826,6 @@ function dpdchkbox_change() {
<?=gettext("seconds"); ?>
</td>
</tr>
- <tr id="opt_cert">
- <td width="22%" valign="top" class="vncellreq"><?=gettext("My Certificate"); ?></td>
- <td width="78%" class="vtable">
- <select name="certref" class="formselect">
- <?php
- foreach ($config['cert'] as $cert):
- $selected = "";
- if ($pconfig['certref'] == $cert['refid'])
- $selected = "selected=\"selected\"";
- ?>
- <option value="<?=$cert['refid'];?>" <?=$selected;?>><?=$cert['descr'];?></option>
- <?php endforeach; ?>
- </select>
- <br />
- <span class="vexpl">
- <?=gettext("Select a certificate previously configured in the Certificate Manager"); ?>.
- </span>
- </td>
- </tr>
- <tr id="opt_ca">
- <td width="22%" valign="top" class="vncellreq"><?=gettext("My Certificate Authority"); ?></td>
- <td width="78%" class="vtable">
- <select name="caref" class="formselect">
- <?php
- foreach ($config['ca'] as $ca):
- $selected = "";
- if ($pconfig['caref'] == $ca['refid'])
- $selected = "selected=\"selected\"";
- ?>
- <option value="<?=$ca['refid'];?>" <?=$selected;?>><?=$ca['descr'];?></option>
- <?php endforeach; ?>
- </select>
- <br />
- <span class="vexpl">
- <?=gettext("Select a certificate authority previously configured in the Certificate Manager"); ?>.
- </span>
- </td>
- </tr>
<tr>
<td colspan="2" class="list" height="12"></td>
</tr>
OpenPOWER on IntegriCloud