Implemented PB-TNC mutual half-duplex protocol

This commit is contained in:
Andreas Steffen 2015-03-22 01:07:31 +01:00
parent c6aed8aa21
commit 7b4a96b2f7
6 changed files with 143 additions and 35 deletions

4
NEWS
View File

@ -52,6 +52,10 @@ strongswan-5.3.0
as seen by the TNC server available to all IMVs. This information can be as seen by the TNC server available to all IMVs. This information can be
forwarded to policy enforcement points (e.g. firewalls or routers). 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 strongswan-5.2.2
---------------- ----------------

View File

@ -44,6 +44,7 @@ METHOD(plugin_t, get_features, int,
PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create), PLUGIN_CALLBACK(tnc_manager_register, tnc_imc_manager_create),
PLUGIN_PROVIDE(CUSTOM, "imc-manager"), PLUGIN_PROVIDE(CUSTOM, "imc-manager"),
PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
PLUGIN_SDEPEND(CUSTOM, "imv-manager"),
PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), PLUGIN_SDEPEND(CERT_DECODE, CERT_X509),
PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY), PLUGIN_SDEPEND(CERT_DECODE, CERT_TRUSTED_PUBKEY),
}; };

View File

@ -80,7 +80,7 @@ struct private_tnccs_20_t {
u_int32_t auth_type; u_int32_t auth_type;
/** /**
* Mutual TNC measurements * Mutual PB-TNC protocol enabled
*/ */
bool mutual; bool mutual;
@ -171,12 +171,12 @@ METHOD(tnccs_t, send_msg, TNC_Result,
METHOD(tls_t, process, status_t, METHOD(tls_t, process, status_t,
private_tnccs_20_t *this, void *buf, size_t buflen) private_tnccs_20_t *this, void *buf, size_t buflen)
{ {
chunk_t data;
pb_tnc_batch_t *batch; pb_tnc_batch_t *batch;
bool from_server, mutual; bool from_server;
status_t status; 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) if (this->is_server && !this->tnc_server)
{ {
this->tnc_server = tnccs_20_server_create(&this->public, _send_msg, this->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
@ -187,25 +187,40 @@ METHOD(tls_t, process, status_t,
return FAILED; return FAILED;
} }
this->tnccs_handler = this->tnc_server; 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); data = chunk_create(buf, buflen);
DBG1(DBG_TNC, "received TNCCS batch (%u bytes)", data.len); DBG1(DBG_TNC, "received TNCCS batch (%u bytes)", data.len);
DBG3(DBG_TNC, "%B", &data); 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 */ /* Parse the header of the received PB-TNC batch */
batch = pb_tnc_batch_create_from_data(data); 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); &from_server);
this->to_server = mutual ? from_server : !this->is_server;
/* Set active TNCCS handler */ this->to_server = this->mutual ? from_server : !this->is_server;
this->tnccs_handler = this->to_server ? this->tnc_client : this->tnc_server;
DBG2(DBG_TNC, "TNC %s is handling the connection", /* 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"); this->to_server ? "client" : "server");
if (status == SUCCESS) if (status == SUCCESS)
@ -219,6 +234,40 @@ METHOD(tls_t, process, status_t,
} }
batch->destroy(batch); 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; return status;
} }
@ -229,10 +278,15 @@ METHOD(tls_t, build, status_t,
if (this->to_server) if (this->to_server)
{ {
DBG2(DBG_TNC, "TNC client is handling outbound connection");
/* Before sending the first PB-TNC batch create TNC client */ /* 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->tnc_client = tnccs_20_client_create(&this->public, _send_msg,
this->max_batch_len, this->max_batch_len,
this->max_msg_len); this->max_msg_len);
@ -241,15 +295,21 @@ METHOD(tls_t, build, status_t,
status = FAILED; status = FAILED;
} }
this->tnccs_handler = this->tnc_client; 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 else
{ {
DBG2(DBG_TNC, "TNC server is handling outbound connection");
/* Before sending the first PB-TNC batch create TNC server */ /* 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->tnc_server = tnccs_20_server_create(&this->public, _send_msg,
this->max_batch_len, this->max_msg_len, this->max_batch_len, this->max_msg_len,
this->eap_transport); this->eap_transport);
@ -258,7 +318,8 @@ METHOD(tls_t, build, status_t,
status = FAILED; status = FAILED;
} }
this->tnccs_handler = this->tnc_server; 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); status = this->tnccs_handler->build(this->tnccs_handler, buf, buflen, msglen);

View File

@ -110,6 +110,11 @@ struct private_tnccs_20_client_t {
*/ */
bool mutual; 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; pb_mutual_capability_msg_t *mutual_msg;
uint32_t protocols; 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; mutual_msg = (pb_mutual_capability_msg_t*)msg;
protocols = mutual_msg->get_protocols(mutual_msg); protocols = mutual_msg->get_protocols(mutual_msg);
if (protocols & PB_MUTUAL_HALF_DUPLEX) if (protocols & PB_MUTUAL_HALF_DUPLEX)
{ {
*mutual = TRUE;
DBG1(DBG_TNC, "activating mutual PB-TNC %N protocol", DBG1(DBG_TNC, "activating mutual PB-TNC %N protocol",
pb_tnc_mutual_protocol_type_names, PB_MUTUAL_HALF_DUPLEX); 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) switch (msg_type.type)
{ {
case PB_ITA_MSG_MUTUAL_CAPABILITY: 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; break;
default: default:
break; break;
@ -636,7 +650,7 @@ METHOD(tnccs_20_handler_t, build, status_t,
} }
METHOD(tnccs_20_handler_t, begin_handshake, void, 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; pb_tnc_msg_t *msg;
char *pref_lang; char *pref_lang;
@ -645,7 +659,9 @@ METHOD(tnccs_20_handler_t, begin_handshake, void,
TNC_CONNECTION_STATE_HANDSHAKE); TNC_CONNECTION_STATE_HANDSHAKE);
/* Announce PB-TNC Mutual Capability if activated */ /* 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)) "%s.plugins.tnccs-20.mutual", FALSE, lib->ns))
{ {
pb_tnc_mutual_protocol_type_t protocols; 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->mutex->lock(this->mutex);
this->messages->insert_last(this->messages, msg); this->messages->insert_last(this->messages, msg);
this->mutex->unlock(this->mutex); this->mutex->unlock(this->mutex);
this->sent_mutual_capability = TRUE;
} }
/* Create PB-TNC Language Preference message */ /* Create PB-TNC Language Preference message */
@ -684,6 +701,12 @@ METHOD(tnccs_20_handler_t, get_mutual, bool,
return this->mutual; 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, METHOD(tnccs_20_handler_t, add_msg, void,
private_tnccs_20_client_t *this, pb_tnc_msg_t *msg) 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, .begin_handshake = _begin_handshake,
.get_send_flag = _get_send_flag, .get_send_flag = _get_send_flag,
.get_mutual = _get_mutual, .get_mutual = _get_mutual,
.get_state = _get_state,
.add_msg = _add_msg, .add_msg = _add_msg,
.handle_errors = _handle_errors, .handle_errors = _handle_errors,
.destroy = _destroy, .destroy = _destroy,

View File

@ -54,8 +54,10 @@ struct tnccs_20_handler_t {
/** /**
* Put the IMCs or IMVs into the handshake state * 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 * 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); 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 * Add a PB-PA message to the handler's message queue
* *

View File

@ -110,6 +110,11 @@ struct private_tnccs_20_server_t {
*/ */
bool mutual; 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, extern void tnccs_20_handle_ietf_error_msg(pb_tnc_msg_t *msg,
bool *fatal_error); bool *fatal_error);
extern void tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg, extern bool tnccs_20_handle_ita_mutual_capability_msg(pb_tnc_msg_t *msg);
bool *mutual);
/** /**
* If the batch type changes then delete all accumulated PB-TNC messages * 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) switch (msg_type.type)
{ {
case PB_ITA_MSG_MUTUAL_CAPABILITY: 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 */ /* Respond with PB-TNC Mutual Capability message if necessary */
if (this->mutual && lib->settings->get_bool(lib->settings, if (this->mutual && !this->sent_mutual_capability)
"%s.plugins.tnccs-20.mutual", FALSE, lib->ns))
{ {
pb_tnc_mutual_protocol_type_t protocols = PB_MUTUAL_HALF_DUPLEX; msg = pb_mutual_capability_msg_create(PB_MUTUAL_HALF_DUPLEX);
msg = pb_mutual_capability_msg_create(protocols);
this->mutex->lock(this->mutex); this->mutex->lock(this->mutex);
this->messages->insert_last(this->messages, msg); this->messages->insert_last(this->messages, msg);
this->mutex->unlock(this->mutex); this->mutex->unlock(this->mutex);
this->sent_mutual_capability = TRUE;
} }
break; break;
default: default:
@ -537,7 +539,7 @@ METHOD(tnccs_20_handler_t, build, status_t,
} }
METHOD(tnccs_20_handler_t, begin_handshake, void, 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; pb_tnc_msg_t *msg;
identification_t *pdp_server; identification_t *pdp_server;
@ -572,6 +574,12 @@ METHOD(tnccs_20_handler_t, get_mutual, bool,
return this->mutual; 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, METHOD(tnccs_20_handler_t, add_msg, void,
private_tnccs_20_server_t *this, pb_tnc_msg_t *msg) 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, .begin_handshake = _begin_handshake,
.get_send_flag = _get_send_flag, .get_send_flag = _get_send_flag,
.get_mutual = _get_mutual, .get_mutual = _get_mutual,
.get_state = _get_state,
.add_msg = _add_msg, .add_msg = _add_msg,
.handle_errors = _handle_errors, .handle_errors = _handle_errors,
.destroy = _destroy, .destroy = _destroy,