diff --git a/NEWS b/NEWS index e6efa66f9..81a7fc5fc 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,10 @@ strongswan-5.3.0 as seen by the TNC server available to all IMVs. This information can be forwarded to policy enforcement points (e.g. firewalls or routers). +- The new mutual tnccs-20 plugin parameter activates mutual TNC measurements + in PB-TNC half-duplex mode between two endpoints over either a PT-EAP or + PT-TLS transport medium. + strongswan-5.2.2 ---------------- diff --git a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c index 859dded79..ce5b48133 100644 --- a/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c +++ b/src/libtnccs/plugins/tnc_imc/tnc_imc_plugin.c @@ -44,6 +44,7 @@ METHOD(plugin_t, get_features, int, PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create), PLUGIN_PROVIDE(CUSTOM, "imc-manager"), PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), + PLUGIN_SDEPEND(CUSTOM, "imv-manager"), PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY), }; diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20.c b/src/libtnccs/plugins/tnccs_20/tnccs_20.c index 33b012880..3d8615ce0 100644 --- a/src/libtnccs/plugins/tnccs_20/tnccs_20.c +++ b/src/libtnccs/plugins/tnccs_20/tnccs_20.c @@ -80,7 +80,7 @@ struct private_tnccs_20_t { u_int32_t auth_type; /** - * Mutual TNC measurements + * Mutual PB-TNC protocol enabled */ bool mutual; @@ -171,12 +171,12 @@ METHOD(tnccs_t, send_msg, TNC_Result, METHOD(tls_t, process, status_t, private_tnccs_20_t *this, void *buf, size_t buflen) { - chunk_t data; pb_tnc_batch_t *batch; - bool from_server, mutual; + bool from_server; status_t status; + chunk_t data; - /* On arrival of first PB-TNC batch create TNC server */ + /* On arrival of first batch from TNC client create TNC server */ if (this->is_server && !this->tnc_server) { this->tnc_server = tnccs_20_server_create(&this->public, _send_msg, @@ -187,25 +187,40 @@ METHOD(tls_t, process, status_t, return FAILED; } this->tnccs_handler = this->tnc_server; - this->tnccs_handler->begin_handshake(this->tnccs_handler); + this->tnccs_handler->begin_handshake(this->tnccs_handler, FALSE); } data = chunk_create(buf, buflen); DBG1(DBG_TNC, "received TNCCS batch (%u bytes)", data.len); DBG3(DBG_TNC, "%B", &data); - /* Has a mutual connection been established? */ - mutual = this->tnc_client && this->tnc_server; - /* Parse the header of the received PB-TNC batch */ batch = pb_tnc_batch_create_from_data(data); - status = batch->process_header(batch, !mutual, this->is_server, + status = batch->process_header(batch, !this->mutual, this->is_server, &from_server); - this->to_server = mutual ? from_server : !this->is_server; - /* Set active TNCCS handler */ - this->tnccs_handler = this->to_server ? this->tnc_client : this->tnc_server; - DBG2(DBG_TNC, "TNC %s is handling the connection", + this->to_server = this->mutual ? from_server : !this->is_server; + + /* In the mutual case, first batch from TNC server requires a TNC client */ + if (this->to_server && !this->tnc_client) + { + this->tnc_client = tnccs_20_client_create(&this->public, _send_msg, + this->max_batch_len, this->max_msg_len); + if (!this->tnc_client) + { + batch->destroy(batch); + return FAILED; + } + this->tnccs_handler = this->tnc_client; + this->tnccs_handler->begin_handshake(this->tnccs_handler, this->mutual); + } + else + { + /* Set active TNCCS handler for processing */ + this->tnccs_handler = this->to_server ? this->tnc_client : + this->tnc_server; + } + DBG2(DBG_TNC, "TNC %s is handling inbound connection", this->to_server ? "client" : "server"); if (status == SUCCESS) @@ -219,6 +234,40 @@ METHOD(tls_t, process, status_t, } batch->destroy(batch); + /* Has a mutual connection been established? */ + this->mutual = this->is_server ? + this->tnc_server->get_mutual(this->tnc_server) : + this->tnc_client->get_mutual(this->tnc_client); + + if (this->mutual && !this->is_server) + { + pb_tnc_state_t client_state, server_state; + + client_state = !this->tnc_client ? PB_STATE_INIT : + this->tnc_client->get_state(this->tnc_client); + server_state = !this->tnc_server ? PB_STATE_INIT : + this->tnc_server->get_state(this->tnc_server); + + /* In half-duplex mutual mode toggle the direction on the client side */ + if ((!this->to_server && client_state != PB_STATE_DECIDED) || + ( this->to_server && server_state != PB_STATE_END)) + { + this->to_server = !this->to_server; + } + else if (client_state == PB_STATE_DECIDED && + server_state == PB_STATE_END) + { + /* Cause the final CLOSE batch to be sent to the TNC server */ + this->to_server = TRUE; + } + + /* Suppress a successful CLOSE batch coming from the TNC server */ + if (status == SUCCESS) + { + status = NEED_MORE; + } + } + return status; } @@ -229,10 +278,15 @@ METHOD(tls_t, build, status_t, if (this->to_server) { + DBG2(DBG_TNC, "TNC client is handling outbound connection"); + /* Before sending the first PB-TNC batch create TNC client */ - if (!this->tnc_client) + if (this->tnc_client) + { + this->tnccs_handler = this->tnc_client; + } + else { - DBG2(DBG_TNC, "TNC client is handling the connection"); this->tnc_client = tnccs_20_client_create(&this->public, _send_msg, this->max_batch_len, this->max_msg_len); @@ -241,15 +295,21 @@ METHOD(tls_t, build, status_t, status = FAILED; } this->tnccs_handler = this->tnc_client; - this->tnccs_handler->begin_handshake(this->tnccs_handler); + this->tnccs_handler->begin_handshake(this->tnccs_handler, + this->mutual); } } else { + DBG2(DBG_TNC, "TNC server is handling outbound connection"); + /* Before sending the first PB-TNC batch create TNC server */ - if (!this->tnc_server) + if (this->tnc_server) + { + this->tnccs_handler = this->tnc_server; + } + else { - DBG2(DBG_TNC, "TNC server is handling the connection"); this->tnc_server = tnccs_20_server_create(&this->public, _send_msg, this->max_batch_len, this->max_msg_len, this->eap_transport); @@ -258,7 +318,8 @@ METHOD(tls_t, build, status_t, status = FAILED; } this->tnccs_handler = this->tnc_server; - this->tnccs_handler->begin_handshake(this->tnccs_handler); + this->tnccs_handler->begin_handshake(this->tnccs_handler, + this->mutual); } } status = this->tnccs_handler->build(this->tnccs_handler, buf, buflen, msglen); diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c index 4fd27a729..9bfadcb66 100644 --- a/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c +++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c @@ -110,6 +110,11 @@ struct private_tnccs_20_client_t { */ bool mutual; + /** + * Mutual Capability message sent + */ + bool sent_mutual_capability; + }; /** @@ -166,20 +171,29 @@ void tnccs_20_handle_ietf_error_msg(pb_tnc_msg_t *msg, bool *fatal_error) } } -void tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg, bool *mutual) +bool tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg) { pb_mutual_capability_msg_t *mutual_msg; uint32_t protocols; + if (!lib->settings->get_bool(lib->settings, + "%s.plugins.tnccs-20.mutual", FALSE, lib->ns)) + { + /* PB-TNC mutual capability disabled, ignore message */ + return FALSE; + } + mutual_msg = (pb_mutual_capability_msg_t*)msg; protocols = mutual_msg->get_protocols(mutual_msg); if (protocols & PB_MUTUAL_HALF_DUPLEX) { - *mutual = TRUE; DBG1(DBG_TNC, "activating mutual PB-TNC %N protocol", pb_tnc_mutual_protocol_type_names, PB_MUTUAL_HALF_DUPLEX); + return TRUE; } + + return FALSE; } /** @@ -396,7 +410,7 @@ static void handle_ita_message(private_tnccs_20_client_t *this, pb_tnc_msg_t *ms switch (msg_type.type) { case PB_ITA_MSG_MUTUAL_CAPABILITY: - tnccs_20_handle_ita_mutual_capability_msg(msg, &this->mutual); + this->mutual = tnccs_20_handle_ita_mutual_capability_msg(msg); break; default: break; @@ -636,7 +650,7 @@ METHOD(tnccs_20_handler_t, build, status_t, } METHOD(tnccs_20_handler_t, begin_handshake, void, - private_tnccs_20_client_t *this) + private_tnccs_20_client_t *this, bool mutual) { pb_tnc_msg_t *msg; char *pref_lang; @@ -645,7 +659,9 @@ METHOD(tnccs_20_handler_t, begin_handshake, void, TNC_CONNECTION_STATE_HANDSHAKE); /* Announce PB-TNC Mutual Capability if activated */ - if (lib->settings->get_bool(lib->settings, + this->sent_mutual_capability = mutual; + + if (!mutual && lib->settings->get_bool(lib->settings, "%s.plugins.tnccs-20.mutual", FALSE, lib->ns)) { pb_tnc_mutual_protocol_type_t protocols; @@ -657,6 +673,7 @@ METHOD(tnccs_20_handler_t, begin_handshake, void, this->mutex->lock(this->mutex); this->messages->insert_last(this->messages, msg); this->mutex->unlock(this->mutex); + this->sent_mutual_capability = TRUE; } /* Create PB-TNC Language Preference message */ @@ -684,6 +701,12 @@ METHOD(tnccs_20_handler_t, get_mutual, bool, return this->mutual; } +METHOD(tnccs_20_handler_t, get_state, pb_tnc_state_t, + private_tnccs_20_client_t *this) +{ + return this->state_machine->get_state(this->state_machine); +} + METHOD(tnccs_20_handler_t, add_msg, void, private_tnccs_20_client_t *this, pb_tnc_msg_t *msg) { @@ -761,6 +784,7 @@ tnccs_20_handler_t* tnccs_20_client_create(tnccs_t *tnccs, .begin_handshake = _begin_handshake, .get_send_flag = _get_send_flag, .get_mutual = _get_mutual, + .get_state = _get_state, .add_msg = _add_msg, .handle_errors = _handle_errors, .destroy = _destroy, diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h b/src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h index 1e6da8798..45df32fc7 100644 --- a/src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h +++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_handler.h @@ -54,8 +54,10 @@ struct tnccs_20_handler_t { /** * Put the IMCs or IMVs into the handshake state + * + * @param mutual TRUE if PB-TNC mutual mode is already established */ - void (*begin_handshake)(tnccs_20_handler_t *this); + void (*begin_handshake)(tnccs_20_handler_t *this, bool mutual); /** * Indicates if IMCs or IMVs are allowed to send PA-TNC messages @@ -71,6 +73,13 @@ struct tnccs_20_handler_t { */ bool (*get_mutual)(tnccs_20_handler_t *this); + /** + * Get state of the PB-TNC protocol + * + * @return PB-TNC state + */ + pb_tnc_state_t (*get_state)(tnccs_20_handler_t *this); + /** * Add a PB-PA message to the handler's message queue * diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c index aacb5aa5f..c75ecdc39 100644 --- a/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c +++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c @@ -110,6 +110,11 @@ struct private_tnccs_20_server_t { */ bool mutual; + /** + * Mutual Capability message sent + */ + bool sent_mutual_capability; + }; /** @@ -117,8 +122,7 @@ struct private_tnccs_20_server_t { */ extern void tnccs_20_handle_ietf_error_msg(pb_tnc_msg_t *msg, bool *fatal_error); -extern void tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg, - bool *mutual); +extern bool tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg); /** * If the batch type changes then delete all accumulated PB-TNC messages @@ -224,18 +228,16 @@ static void handle_ita_message(private_tnccs_20_server_t *this, pb_tnc_msg_t *ms switch (msg_type.type) { case PB_ITA_MSG_MUTUAL_CAPABILITY: - tnccs_20_handle_ita_mutual_capability_msg(msg, &this->mutual); + this->mutual = tnccs_20_handle_ita_mutual_capability_msg(msg); - /* Respond with PB-TNC Mutual Capability message if activated */ - if (this->mutual && lib->settings->get_bool(lib->settings, - "%s.plugins.tnccs-20.mutual", FALSE, lib->ns)) + /* Respond with PB-TNC Mutual Capability message if necessary */ + if (this->mutual && !this->sent_mutual_capability) { - pb_tnc_mutual_protocol_type_t protocols = PB_MUTUAL_HALF_DUPLEX; - - msg = pb_mutual_capability_msg_create(protocols); + msg = pb_mutual_capability_msg_create(PB_MUTUAL_HALF_DUPLEX); this->mutex->lock(this->mutex); this->messages->insert_last(this->messages, msg); this->mutex->unlock(this->mutex); + this->sent_mutual_capability = TRUE; } break; default: @@ -537,7 +539,7 @@ METHOD(tnccs_20_handler_t, build, status_t, } METHOD(tnccs_20_handler_t, begin_handshake, void, - private_tnccs_20_server_t *this) + private_tnccs_20_server_t *this, bool mutual) { pb_tnc_msg_t *msg; identification_t *pdp_server; @@ -572,6 +574,12 @@ METHOD(tnccs_20_handler_t, get_mutual, bool, return this->mutual; } +METHOD(tnccs_20_handler_t, get_state, pb_tnc_state_t, + private_tnccs_20_server_t *this) +{ + return this->state_machine->get_state(this->state_machine); +} + METHOD(tnccs_20_handler_t, add_msg, void, private_tnccs_20_server_t *this, pb_tnc_msg_t *msg) { @@ -648,6 +656,7 @@ tnccs_20_handler_t* tnccs_20_server_create(tnccs_t *tnccs, .begin_handshake = _begin_handshake, .get_send_flag = _get_send_flag, .get_mutual = _get_mutual, + .get_state = _get_state, .add_msg = _add_msg, .handle_errors = _handle_errors, .destroy = _destroy,