diff options
Diffstat (limited to 'src/libcharon/plugins/eap_tnc/eap_tnc.c')
-rw-r--r-- | src/libcharon/plugins/eap_tnc/eap_tnc.c | 85 |
1 files changed, 82 insertions, 3 deletions
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index 839425d59..f9ab74258 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -22,6 +22,7 @@ #include <daemon.h> #include <tncifimv.h> +#include <tncif_names.h> /** * Maximum size of an EAP-TNC message @@ -62,6 +63,63 @@ struct private_eap_tnc_t { }; +/** + * Callback function to get recommendation from TNCCS connection + */ +static bool enforce_recommendation(TNC_IMV_Action_Recommendation rec, + TNC_IMV_Evaluation_Result eval) +{ + char *group; + identification_t *id; + ike_sa_t *ike_sa; + auth_cfg_t *auth; + bool no_access = FALSE; + + DBG1(DBG_TNC, "final recommendation is '%N' and evaluation is '%N'", + TNC_IMV_Action_Recommendation_names, rec, + TNC_IMV_Evaluation_Result_names, eval); + + switch (rec) + { + case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: + group = "allow"; + break; + case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: + group = "isolate"; + break; + case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: + case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: + default: + group = "no access"; + no_access = TRUE; + break; + } + + ike_sa = charon->bus->get_sa(charon->bus); + if (!ike_sa) + { + DBG1(DBG_TNC, "policy enforcement point did not find IKE_SA"); + return FALSE; + } + + id = ike_sa->get_other_id(ike_sa); + DBG0(DBG_TNC, "policy enforced on peer '%Y' is '%s'", id, group); + + if (no_access) + { + return FALSE; + } + else + { + auth = ike_sa->get_auth_cfg(ike_sa, FALSE); + id = identification_create_from_string(group); + auth->add(auth, AUTH_RULE_GROUP, id); + DBG1(DBG_TNC, "policy enforcement point added group membership '%s'", + group); + } + return TRUE; +} + METHOD(eap_method_t, initiate, status_t, private_eap_tnc_t *this, eap_payload_t **out) { @@ -155,6 +213,18 @@ METHOD(eap_method_t, is_mutual, bool, METHOD(eap_method_t, destroy, void, private_eap_tnc_t *this) { + chunk_t pdp_server; + u_int16_t pdp_port; + tls_t *tls; + + pdp_server = this->tnccs->get_pdp_server(this->tnccs, &pdp_port); + if (pdp_server.len) + { + DBG2(DBG_TNC, "TODO: setup PT-TLS connection to %.*s:%u", + pdp_server.len, pdp_server.ptr, pdp_port); + } + tls = &this->tnccs->tls; + tls->destroy(tls); this->tls_eap->destroy(this->tls_eap); free(this); } @@ -180,6 +250,7 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, private_eap_tnc_t *this; int max_msg_count; char* protocol; + tnccs_t *tnccs; tnccs_type_t type; INIT(this, @@ -224,9 +295,17 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, free(this); return NULL; } - this->tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server, - server, peer, TNC_IFT_EAP_1_1); - this->tls_eap = tls_eap_create(EAP_TNC, &this->tnccs->tls, + tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, + is_server, server, peer, TNC_IFT_EAP_1_1, + is_server ? enforce_recommendation : NULL); + if (!tnccs) + { + DBG1(DBG_TNC, "TNCCS protocol '%s' not enabled", protocol); + free(this); + return NULL; + } + this->tnccs = tnccs->get_ref(tnccs); + this->tls_eap = tls_eap_create(EAP_TNC, &tnccs->tls, EAP_TNC_MAX_MESSAGE_LEN, max_msg_count, FALSE); if (!this->tls_eap) |