Fix of the mutual TNC measurement use case

If the IKEv2 initiator acting as a TNC server receives invalid TNC measurements
from the IKEv2 responder acting as a TNC clienti, the exchange of PB-TNC batches
is continued until the IKEv2 responder acting as a TNC server has also finished
its TNC measurements.

In the past if these measurements in the other direction were correct
the IKEv2 responder acting as EAP server declared the IKEv2 EAP authentication
successful and the IPsec connection was established even though the TNC
measurement verification on the EAP peer side failed.

The fix adds an "allow" group membership on each endpoint if the corresponding
TNC measurements of the peer are successful. By requiring a "allow" group
membership in the IKEv2 connection definition the IPsec connection succeeds
only if the TNC measurements on both sides are valid.
This commit is contained in:
Andreas Steffen 2016-02-16 18:00:27 +01:00
parent 70934d9436
commit 4d83c5b4a6
17 changed files with 234 additions and 28 deletions

View File

@ -328,7 +328,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
tnccs = tnc->tnccs->create_instance(tnc->tnccs, tnccs_type,
is_server, server, peer, server_ip, peer_ip,
(type == EAP_TNC) ? TNC_IFT_EAP_1_1 : TNC_IFT_EAP_2_0,
is_server ? enforce_recommendation : NULL);
enforce_recommendation);
if (!tnccs)
{
DBG1(DBG_TNC, "TNCCS protocol '%s' not enabled", protocol);

View File

@ -126,6 +126,24 @@ struct private_tnccs_20_t {
};
METHOD(tls_t, is_complete, bool,
private_tnccs_20_t *this)
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
tnccs_20_server_t *tnc_server;
if (this->tnc_server)
{
tnc_server = (tnccs_20_server_t*)this->tnc_server;
if (tnc_server->have_recommendation(tnc_server, &rec, &eval))
{
return this->callback ? this->callback(rec, eval) : TRUE;
}
}
return FALSE;
}
METHOD(tnccs_t, send_msg, TNC_Result,
private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
TNC_UInt32 msg_flags,
@ -269,6 +287,7 @@ METHOD(tls_t, process, status_t,
/* Suppress a successful CLOSE batch coming from the TNC server */
if (status == SUCCESS)
{
is_complete(this);
status = NEED_MORE;
}
}
@ -359,25 +378,6 @@ METHOD(tls_t, get_purpose, tls_purpose_t,
return TLS_PURPOSE_EAP_TNC;
}
METHOD(tls_t, is_complete, bool,
private_tnccs_20_t *this)
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
if (this->tnc_server)
{
tnccs_20_server_t *tnc_server;
tnc_server = (tnccs_20_server_t*)this->tnc_server;
if (tnc_server->have_recommendation(tnc_server, &rec, &eval))
{
return this->callback ? this->callback(rec, eval) : TRUE;
}
}
return FALSE;
}
METHOD(tls_t, get_eap_msk, chunk_t,
private_tnccs_20_t *this)
{

View File

@ -0,0 +1,5 @@
The hosts <b>moon</b> and <b>sun</b> do mutual TNC measurements over IKEv2-EAP
using the PA-TNC, PB-TNC and PT-EAP protocols. The IKEv2 EAP-TTLS authentication
is based on X.509 certificates. The TNC measurement on <b>moon</b> is successful
and the measurement on <b>sun</b> fails, causing the IPsec connection to be
aborted by <b>moon</b>.

View File

@ -0,0 +1,7 @@
moon::cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
sun:: cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
moon::cat /var/log/daemon.log::final recommendation is.*no access::YES
sun:: cat /var/log/daemon.log::final recommendation is.*allow::YES
moon::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.1/32] remote-ts=\[192.168.0.2/32]::NO
sun::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.2/32] remote-ts=\[192.168.0.1/32]::NO
moon::ping -c 1 -W 1 192.168.0.2::64 bytes from 192.168.0.2: icmp_req=1::NO

View File

@ -0,0 +1,45 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce x509 openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
multiple_authentication = no
start-scripts {
creds = /usr/local/sbin/swanctl --load-creds
conns = /usr/local/sbin/swanctl --load-conns
}
syslog {
auth {
default = 0
}
daemon {
tnc = 2
imc = 2
imv = 2
}
}
plugins {
eap-ttls {
phase2_tnc = yes
}
tnccs-20 {
mutual = yes
}
}
}
libtls {
suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
}
libimcv {
plugins {
imc-test {
command = allow
}
imv-test {
rounds = 1
}
}
}

View File

@ -0,0 +1,28 @@
connections {
mutual {
local_addrs = 192.168.0.1
remote_addrs = 192.168.0.2
local {
auth = eap-ttls
certs = moonCert.pem
id = moon.strongswan.org
}
remote {
auth = eap-ttls
id = sun.strongswan.org
groups = allow
}
children {
mutual {
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm16-ecp256
}
}
version = 2
mobike = no
send_certreq = no
proposals = aes128-sha256-ecp256
}
}

View File

@ -0,0 +1,4 @@
#IMC/IMV configuration file for strongSwan endpoint
IMC "Test" /usr/local/lib/ipsec/imcvs/imc-test.so
IMV "Test" /usr/local/lib/ipsec/imcvs/imv-test.so

View File

@ -0,0 +1,47 @@
# /etc/strongswan.conf - strongSwan configuration file
charon {
load = random nonce x509 openssl pem pkcs1 revocation curl vici kernel-netlink socket-default eap-identity eap-ttls eap-tnc tnc-tnccs tnc-imc tnc-imv tnccs-20 updown
multiple_authentication = no
start-scripts {
creds = /usr/local/sbin/swanctl --load-creds
conns = /usr/local/sbin/swanctl --load-conns
}
syslog {
auth {
default = 0
}
daemon {
tnc = 2
imc = 2
imv = 2
}
}
plugins {
eap-ttls {
request_peer_auth = yes
phase2_piggyback = yes
phase2_tnc =yes
}
tnccs-20 {
mutual = yes
}
}
}
libtls {
suites = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
}
libimcv {
plugins {
imc-test {
command = none
}
imv-test {
rounds = 1
}
}
}

View File

@ -0,0 +1,28 @@
connections {
mutual {
local_addrs = 192.168.0.2
remote_addrs = 192.168.0.1
local {
auth = eap-ttls
certs = sunCert.pem
id = sun.strongswan.org
}
remote {
auth = eap-ttls
id = moon.strongswan.org
groups = allow
}
children {
mutual {
updown = /usr/local/libexec/ipsec/_updown iptables
esp_proposals = aes128gcm16-ecp256
}
}
version = 2
mobike = no
send_certreq = no
proposals = aes128-sha256-ecp256
}
}

View File

@ -0,0 +1,4 @@
#IMC/IMV configuration file for strongSwan endpoint
IMC "Test" /usr/local/lib/ipsec/imcvs/imc-test.so
IMV "Test" /usr/local/lib/ipsec/imcvs/imv-test.so

View File

@ -0,0 +1,4 @@
moon::service charon stop
sun::service charon stop
moon::iptables-restore < /etc/iptables.flush
sun::iptables-restore < /etc/iptables.flush

View File

@ -0,0 +1,6 @@
moon::iptables-restore < /etc/iptables.rules
sun::iptables-restore < /etc/iptables.rules
moon::service charon start
sun::service charon start
moon::expect-connection mutual
moon::swanctl --initiate --child mutual

View File

@ -0,0 +1,25 @@
#!/bin/bash
#
# This configuration file provides information on the
# guest instances used for this test
# All guest instances that are required for this test
#
VIRTHOSTS="moon winnetou sun"
# Corresponding block diagram
#
DIAGRAM="m-w-s.png"
# Guest instances on which tcpdump is to be started
#
TCPDUMPHOSTS="sun"
# Guest instances on which IPsec is started
# Used for IPsec logging purposes
#
IPSECHOSTS="moon sun"
# charon controlled by swanctl
#
SWANCTL=1

View File

@ -1,3 +1,4 @@
The hosts <b>moon</b> and <b>sun</b> do mutual TNC measurements over IKEv2-EAP
using the PA-TNC, PB-TNC and PT-EAP protocols. The authentication is based on
X.509 certificates.
using the PA-TNC, PB-TNC and PT-EAP protocols. The IKEv2 EAP-TTLS authentication
is based on X.509 certificates. The TNC measurements of both <b>moon</b> and
<b>sun</b> are successful and the IPsec connection gets established.

View File

@ -1,7 +1,7 @@
moon::cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
sun:: cat /var/log/daemon.log::activating mutual PB-TNC half duplex protocol::YES
moon::cat /var/log/daemon.log::PB-TNC access recommendation is.*Access Allowed::YES
sun:: cat /var/log/daemon.log::PB-TNC access recommendation is.*Access Allowed::YES
moon::cat /var/log/daemon.log::final recommendation is.*allow::YES
sun:: cat /var/log/daemon.log::final recommendation is.*allow::YES
moon::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.1 local-id=moon.strongswan.org remote-host=192.168.0.2 remote-id=sun.strongswan.org initiator=yes.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.1/32] remote-ts=\[192.168.0.2/32]::YES
sun::swanctl --list-sas --raw 2> /dev/null::mutual.*version=2 state=ESTABLISHED local-host=192.168.0.2 local-id=sun.strongswan.org remote-host=192.168.0.1 remote-id=moon.strongswan.org.*encr-alg=AES_CBC encr-keysize=128 integ-alg=HMAC_SHA2_256_128 prf-alg=PRF_HMAC_SHA2_256 dh-group=ECP_256.*child-sas.*mutual.*state=INSTALLED mode=TUNNEL protocol=ESP.*encr-alg=AES_GCM_16 encr-keysize=128.*local-ts=\[192.168.0.2/32] remote-ts=\[192.168.0.1/32]::YES
moon::ping -c 1 192.168.0.2::64 bytes from 192.168.0.2: icmp_req=1::YES

View File

@ -10,8 +10,9 @@ connections {
id = moon.strongswan.org
}
remote {
auth = eap-ttls
id = sun.strongswan.org
auth = eap-ttls
id = sun.strongswan.org
groups = allow
}
children {
mutual {

View File

@ -10,8 +10,9 @@ connections {
id = sun.strongswan.org
}
remote {
auth = eap-ttls
id = moon.strongswan.org
auth = eap-ttls
id = moon.strongswan.org
groups = allow
}
children {
mutual {