tests: TNC testing

This implements minimal IMC and IMV to allow TNC testing with PEAP (SoH)
and TTLS/FAST with EAP-TNC.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-05-17 00:47:37 +03:00
parent 10b58b5029
commit dbd1e184e3
11 changed files with 671 additions and 0 deletions

View file

@ -32,10 +32,43 @@ typedef TNC_Result (*TNC_TNCS_BindFunctionPointer)(
TNC_IMVID imvID,
char *functionName,
void **pOutfunctionPointer);
typedef TNC_Result (*TNC_TNCS_ReportMessageTypesPointer)(
TNC_IMVID imvID,
TNC_MessageTypeList supportedTypes,
TNC_UInt32 typeCount);
typedef TNC_Result (*TNC_TNCS_SendMessagePointer)(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_BufferReference message,
TNC_UInt32 messageLength,
TNC_MessageType messageType);
typedef TNC_Result (*TNC_TNCS_RequestHandshakeRetryPointer)(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_RetryReason reason);
typedef TNC_Result (*TNC_TNCS_ProvideRecommendationPointer)(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_IMV_Action_Recommendation recommendation,
TNC_IMV_Evaluation_Result evaluation);
typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)(
TNC_IMCID imcID,
char *functionName,
void **pOutfunctionPointer);
typedef TNC_Result (*TNC_TNCC_SendMessagePointer)(
TNC_IMCID imcID,
TNC_ConnectionID connectionID,
TNC_BufferReference message,
TNC_UInt32 messageLength,
TNC_MessageType messageType);
typedef TNC_Result (*TNC_TNCC_ReportMessageTypesPointer)(
TNC_IMCID imcID,
TNC_MessageTypeList supportedTypes,
TNC_UInt32 typeCount);
typedef TNC_Result (*TNC_TNCC_RequestHandshakeRetryPointer)(
TNC_IMCID imcID,
TNC_ConnectionID connectionID,
TNC_RetryReason reason);
#define TNC_IFIMV_VERSION_1 1
#define TNC_IFIMC_VERSION_1 1

View file

@ -22,3 +22,7 @@ make -j8
cd ../mac80211_hwsim/tools
make clean
make -j8
cd ../../tests/hwsim/tnc
make clean
make -j8
cd ..

View file

@ -29,6 +29,7 @@ CONFIG_EAP_VENDOR_TEST=y
CONFIG_EAP_FAST=y
CONFIG_EAP_IKEV2=y
CONFIG_EAP_TNC=y
CFLAGS += -DTNC_CONFIG_FILE=\"tnc/tnc_config\"
CONFIG_EAP_UNAUTH_TLS=y
ifeq ($(CONFIG_TLS), openssl)
CONFIG_EAP_PWD=y

View file

@ -27,6 +27,7 @@ CONFIG_EAP_GPSK=y
CONFIG_EAP_GPSK_SHA256=y
CONFIG_EAP_EKE=y
CONFIG_EAP_TNC=y
CFLAGS += -DTNC_CONFIG_FILE=\"tnc/tnc_config\"
CONFIG_EAP_FAST=y
CONFIG_EAP_IKEV2=y

93
tests/hwsim/test_tnc.py Normal file
View file

@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
# TNC tests
# Copyright (c) 2014, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import os.path
import hostapd
from test_ap_eap import int_eap_server_params
def test_tnc_peap_soh(dev, apdev):
"""TNC PEAP-SoH"""
params = int_eap_server_params()
params["tnc"] = "1"
hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
eap="PEAP", identity="user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 tnc=soh cryptobinding=0",
phase2="auth=MSCHAPV2",
wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
if ev is None:
raise Exception("Connection timed out")
dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
eap="PEAP", identity="user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 tnc=soh1 cryptobinding=1",
phase2="auth=MSCHAPV2",
wait_connect=False)
ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
if ev is None:
raise Exception("Connection timed out")
dev[2].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
eap="PEAP", identity="user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 tnc=soh2 cryptobinding=2",
phase2="auth=MSCHAPV2",
wait_connect=False)
ev = dev[2].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
if ev is None:
raise Exception("Connection timed out")
def test_tnc_ttls(dev, apdev):
"""TNC TTLS"""
params = int_eap_server_params()
params["tnc"] = "1"
hostapd.add_ap(apdev[0]['ifname'], params)
if not os.path.exists("tnc/libhostap_imc.so"):
logger.info("No IMC installed - skip")
return "skip"
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
eap="TTLS", identity="DOMAIN\mschapv2 user",
anonymous_identity="ttls", password="password",
phase2="auth=MSCHAPV2",
ca_cert="auth_serv/ca.pem",
wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
if ev is None:
raise Exception("Connection timed out")
def test_tnc_fast(dev, apdev):
"""TNC FAST"""
params = int_eap_server_params()
params["tnc"] = "1"
params["pac_opaque_encr_key"] ="000102030405060708090a0b0c0d0e00"
params["eap_fast_a_id"] = "101112131415161718191a1b1c1d1e00"
params["eap_fast_a_id_info"] = "test server2"
hostapd.add_ap(apdev[0]['ifname'], params)
if not os.path.exists("tnc/libhostap_imc.so"):
logger.info("No IMC installed - skip")
return "skip"
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
eap="FAST", identity="user",
anonymous_identity="FAST", password="password",
phase2="auth=GTC",
phase1="fast_provisioning=2",
pac_file="blob://fast_pac_auth_tnc",
ca_cert="auth_serv/ca.pem",
wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
if ev is None:
raise Exception("Connection timed out")

11
tests/hwsim/tnc/Makefile Normal file
View file

@ -0,0 +1,11 @@
CFLAGS += -I$(abspath ../../../src)
CFLAGS += -I$(abspath ../../../src/utils)
ALL=libhostap_imc.so libhostap_imv.so libhostap2_imc.so libhostap2_imv.so
all: $(ALL)
lib%.so: %.c
$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $<
clean:
rm -f $(ALL)

View file

@ -0,0 +1,183 @@
/*
* Example IMC for TNC testing
* Copyright (c) 2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "common/tnc.h"
static int initialized = 0;
static TNC_IMCID my_id = -1;
static TNC_TNCC_SendMessagePointer send_message = NULL;
static TNC_TNCC_ReportMessageTypesPointer report_message_types = NULL;
static TNC_TNCC_RequestHandshakeRetryPointer request_retry = NULL;
static TNC_MessageType message_types[] =
{
(TNC_VENDORID_ANY << 8) | TNC_SUBTYPE_ANY
};
TNC_Result TNC_IMC_Initialize(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_Version minVersion,
/*in*/ TNC_Version maxVersion,
/*out*/ TNC_Version *pOutActualVersion)
{
wpa_printf(MSG_INFO,
"IMC(hostap2) %s(imcID=%u, minVersion=%u, maxVersion=%u)",
__func__, (unsigned) imcID, (unsigned) minVersion,
(unsigned) maxVersion);
if (initialized)
return TNC_RESULT_ALREADY_INITIALIZED;
if (minVersion < TNC_IFIMC_VERSION_1 ||
maxVersion > TNC_IFIMC_VERSION_1)
return TNC_RESULT_NO_COMMON_VERSION;
if (!pOutActualVersion)
return TNC_RESULT_INVALID_PARAMETER;
*pOutActualVersion = TNC_IFIMC_VERSION_1;
my_id = imcID;
initialized = 1;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_BeginHandshake(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_ConnectionID connectionID)
{
char *msg = "hello";
TNC_Result res;
wpa_printf(MSG_INFO, "IMC(hostap2) %s(imcID=%u, connectionID=%u)",
__func__, (unsigned) imcID, (unsigned) connectionID);
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imcID != my_id)
return TNC_RESULT_INVALID_PARAMETER;
if (!send_message)
return TNC_RESULT_FATAL;
res = send_message(imcID, connectionID, msg, os_strlen(msg), 1);
if (res != TNC_RESULT_SUCCESS)
return res;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_ProvideBindFunction(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_TNCC_BindFunctionPointer bindFunction)
{
TNC_Result res;
wpa_printf(MSG_INFO, "IMC(hostap2) %s(imcID=%u)",
__func__, (unsigned) imcID);
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imcID != my_id || !bindFunction)
return TNC_RESULT_INVALID_PARAMETER;
if (bindFunction(imcID, "TNC_TNCC_SendMessage",
(void **) &send_message) != TNC_RESULT_SUCCESS ||
!send_message)
return TNC_RESULT_FATAL;
if (bindFunction(imcID, "TNC_TNCC_ReportMessageTypes",
(void **) &report_message_types) !=
TNC_RESULT_SUCCESS ||
!report_message_types)
return TNC_RESULT_FATAL;
if (bindFunction(imcID, "TNC_TNCC_RequestHandshakeRetry",
(void **) &request_retry) != TNC_RESULT_SUCCESS ||
!request_retry)
return TNC_RESULT_FATAL;
res = report_message_types(imcID, message_types,
ARRAY_SIZE(message_types));
if (res != TNC_RESULT_SUCCESS)
return res;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_NotifyConnectionChange(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_ConnectionID connectionID,
/*in*/ TNC_ConnectionState newState)
{
wpa_printf(MSG_INFO,
"IMC(hostap2) %s(imcID=%u, connectionID=%u, newState=%u)",
__func__, (unsigned) imcID, (unsigned) connectionID,
(unsigned) newState);
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_ReceiveMessage(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_ConnectionID connectionID,
/*in*/ TNC_BufferReference message,
/*in*/ TNC_UInt32 messageLength,
/*in*/ TNC_MessageType messageType)
{
TNC_Result res;
wpa_printf(MSG_INFO,
"IMC(hostap2) %s(imcID=%u, connectionID=%u, messageType=%u)",
__func__, (unsigned) imcID, (unsigned) connectionID,
(unsigned) messageType);
wpa_hexdump_ascii(MSG_INFO, "IMC(hostap2) message",
message, messageLength);
if (messageType == 1 && messageLength == 5 &&
os_memcmp(message, "hello", 5) == 0) {
char *msg = "i'm fine";
res = send_message(imcID, connectionID, msg, os_strlen(msg), 1);
if (res != TNC_RESULT_SUCCESS)
return res;
}
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_BatchEnding(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_ConnectionID connectionID)
{
wpa_printf(MSG_INFO, "IMC(hostap2) %s(imcID=%u, connectionID=%u)",
__func__, (unsigned) imcID, (unsigned) connectionID);
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_Terminate(
/*in*/ TNC_IMCID imcID)
{
wpa_printf(MSG_INFO, "IMC(hostap2) %s(imcID=%u)",
__func__, (unsigned) imcID);
return TNC_RESULT_SUCCESS;
}

View file

@ -0,0 +1,203 @@
/*
* Example IMV for TNC testing
* Copyright (c) 2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "common/tnc.h"
static int initialized = 0;
static TNC_IMVID my_id = -1;
static TNC_TNCS_ReportMessageTypesPointer report_message_types = NULL;
static TNC_TNCS_SendMessagePointer send_message = NULL;
static TNC_TNCS_RequestHandshakeRetryPointer request_retry = NULL;
TNC_TNCS_ProvideRecommendationPointer provide_recomm = NULL;
static TNC_MessageType message_types[] =
{
(TNC_VENDORID_ANY << 8) | TNC_SUBTYPE_ANY
};
TNC_Result TNC_IMV_Initialize(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_Version minVersion,
/*in*/ TNC_Version maxVersion,
/*out*/ TNC_Version *pOutActualVersion)
{
wpa_printf(MSG_INFO,
"IMV(hostap2) %s(imvID=%u, minVersion=%u, maxVersion=%u)",
__func__, (unsigned) imvID, (unsigned) minVersion,
(unsigned) maxVersion);
if (initialized)
return TNC_RESULT_ALREADY_INITIALIZED;
if (minVersion < TNC_IFIMV_VERSION_1 ||
maxVersion > TNC_IFIMV_VERSION_1)
return TNC_RESULT_NO_COMMON_VERSION;
if (!pOutActualVersion)
return TNC_RESULT_INVALID_PARAMETER;
*pOutActualVersion = TNC_IFIMV_VERSION_1;
initialized = 1;
my_id = imvID;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_NotifyConnectionChange(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_ConnectionID connectionID,
/*in*/ TNC_ConnectionState newState)
{
wpa_printf(MSG_INFO,
"IMV(hostap2) %s(imvID=%u, connectionID=%u, newState=%u)",
__func__, (unsigned) imvID, (unsigned) connectionID,
(unsigned) newState);
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imvID != my_id)
return TNC_RESULT_INVALID_PARAMETER;
/* TODO: call TNC_TNCS_ProvideRecommendation */
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_ReceiveMessage(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_ConnectionID connectionID,
/*in*/ TNC_BufferReference message,
/*in*/ TNC_UInt32 messageLength,
/*in*/ TNC_MessageType messageType)
{
TNC_Result res;
wpa_printf(MSG_INFO,
"IMV(hostap2) %s(imvID=%u, connectionID=%u, messageType=%u)",
__func__, (unsigned) imvID, (unsigned) connectionID,
(unsigned) messageType);
wpa_hexdump_ascii(MSG_INFO, "IMV(hostap2) message",
message, messageLength);
if (!send_message)
return TNC_RESULT_FATAL;
if (messageType == 1 && messageLength == 5 &&
os_memcmp(message, "hello", 5) == 0) {
char *msg = "hello";
res = send_message(imvID, connectionID, msg, os_strlen(msg), 1);
if (res != TNC_RESULT_SUCCESS)
return res;
}
if (messageType == 1 && messageLength == 8 &&
os_memcmp(message, "i'm fine", 8) == 0) {
if (!provide_recomm)
return TNC_RESULT_FATAL;
res = provide_recomm(imvID, connectionID,
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
TNC_IMV_EVALUATION_RESULT_COMPLIANT);
if (res != TNC_RESULT_SUCCESS)
return res;
}
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_SolicitRecommendation(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_ConnectionID connectionID)
{
wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u, connectionID=%u)",
__func__, (unsigned) imvID, (unsigned) connectionID);
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imvID != my_id)
return TNC_RESULT_INVALID_PARAMETER;
/* TODO: call TNC_TNCS_ProvideRecommendation */
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_BatchEnding(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_ConnectionID connectionID)
{
wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u, connectionID=%u)",
__func__, (unsigned) imvID, (unsigned) connectionID);
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_Terminate(
/*in*/ TNC_IMVID imvID)
{
wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u)",
__func__, (unsigned) imvID);
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_ProvideBindFunction(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_TNCS_BindFunctionPointer bindFunction)
{
TNC_Result res;
wpa_printf(MSG_INFO, "IMV(hostap2) %s(imvID=%u)",
__func__, (unsigned) imvID);
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imvID != my_id || !bindFunction)
return TNC_RESULT_INVALID_PARAMETER;
if (bindFunction(imvID, "TNC_TNCS_ReportMessageTypes",
(void **) &report_message_types) !=
TNC_RESULT_SUCCESS ||
!report_message_types)
return TNC_RESULT_FATAL;
if (bindFunction(imvID, "TNC_TNCS_SendMessage",
(void **) &send_message) != TNC_RESULT_SUCCESS ||
!send_message)
return TNC_RESULT_FATAL;
if (bindFunction(imvID, "TNC_TNCS_RequestHandshakeRetry",
(void **) &request_retry) != TNC_RESULT_SUCCESS ||
!request_retry)
return TNC_RESULT_FATAL;
if (bindFunction(imvID, "TNC_TNCS_ProvideRecommendation",
(void **) &provide_recomm) != TNC_RESULT_SUCCESS ||
!provide_recomm)
return TNC_RESULT_FATAL;
res = report_message_types(imvID, message_types,
ARRAY_SIZE(message_types));
if (res != TNC_RESULT_SUCCESS)
return res;
return TNC_RESULT_SUCCESS;
}

View file

@ -0,0 +1,72 @@
/*
* Minimal example IMC for TNC testing
* Copyright (c) 2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "common/tnc.h"
static int initialized = 0;
static TNC_IMCID my_id = -1;
TNC_Result TNC_IMC_Initialize(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_Version minVersion,
/*in*/ TNC_Version maxVersion,
/*out*/ TNC_Version *pOutActualVersion)
{
wpa_printf(MSG_INFO, "IMC(hostap) %s", __func__);
if (initialized)
return TNC_RESULT_ALREADY_INITIALIZED;
if (minVersion < TNC_IFIMC_VERSION_1 ||
maxVersion > TNC_IFIMC_VERSION_1)
return TNC_RESULT_NO_COMMON_VERSION;
if (!pOutActualVersion)
return TNC_RESULT_INVALID_PARAMETER;
*pOutActualVersion = TNC_IFIMC_VERSION_1;
my_id = imcID;
initialized = 1;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_BeginHandshake(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_ConnectionID connectionID)
{
wpa_printf(MSG_INFO, "IMC(hostap) %s", __func__);
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imcID != my_id)
return TNC_RESULT_INVALID_PARAMETER;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMC_ProvideBindFunction(
/*in*/ TNC_IMCID imcID,
/*in*/ TNC_TNCC_BindFunctionPointer bindFunction)
{
wpa_printf(MSG_INFO, "IMC(hostap) %s", __func__);
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imcID != my_id)
return TNC_RESULT_INVALID_PARAMETER;
return TNC_RESULT_SUCCESS;
}

View file

@ -0,0 +1,66 @@
/*
* Minimal example IMV for TNC testing
* Copyright (c) 2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "common/tnc.h"
static int initialized = 0;
static TNC_IMVID my_id = -1;
TNC_Result TNC_IMV_Initialize(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_Version minVersion,
/*in*/ TNC_Version maxVersion,
/*out*/ TNC_Version *pOutActualVersion)
{
if (initialized)
return TNC_RESULT_ALREADY_INITIALIZED;
if (minVersion < TNC_IFIMV_VERSION_1 ||
maxVersion > TNC_IFIMV_VERSION_1)
return TNC_RESULT_NO_COMMON_VERSION;
if (!pOutActualVersion)
return TNC_RESULT_INVALID_PARAMETER;
*pOutActualVersion = TNC_IFIMV_VERSION_1;
initialized = 1;
my_id = imvID;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_SolicitRecommendation(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_ConnectionID connectionID)
{
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imvID != my_id)
return TNC_RESULT_INVALID_PARAMETER;
return TNC_RESULT_SUCCESS;
}
TNC_Result TNC_IMV_ProvideBindFunction(
/*in*/ TNC_IMVID imvID,
/*in*/ TNC_TNCS_BindFunctionPointer bindFunction)
{
if (!initialized)
return TNC_RESULT_NOT_INITIALIZED;
if (imvID != my_id)
return TNC_RESULT_INVALID_PARAMETER;
return TNC_RESULT_SUCCESS;
}

View file

@ -0,0 +1,4 @@
IMC "hostap IMC" tnc/libhostap_imc.so
IMV "hostap IMV" tnc/libhostap_imv.so
IMC "hostap2 IMC" tnc/libhostap2_imc.so
IMV "hostap2 IMV" tnc/libhostap2_imv.so