summaryrefslogtreecommitdiff
path: root/src/libcharon/plugins/tnccs_20/tnccs_20.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/plugins/tnccs_20/tnccs_20.c')
-rw-r--r--src/libcharon/plugins/tnccs_20/tnccs_20.c70
1 files changed, 45 insertions, 25 deletions
diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c
index d53fd8eb7..9e2081d46 100644
--- a/src/libcharon/plugins/tnccs_20/tnccs_20.c
+++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c
@@ -81,12 +81,17 @@ struct private_tnccs_20_t {
bool request_handshake_retry;
/**
+ * SendMessage() by IMC/IMV only allowed if flag is set
+ */
+ bool send_msg;
+
+ /**
* Set of IMV recommendations (TNC Server only)
*/
recommendations_t *recs;
};
-METHOD(tnccs_t, send_msg, void,
+METHOD(tnccs_t, send_msg, TNC_Result,
private_tnccs_20_t* this, TNC_IMCID imc_id, TNC_IMVID imv_id,
TNC_BufferReference msg,
TNC_UInt32 msg_len,
@@ -97,6 +102,14 @@ METHOD(tnccs_t, send_msg, void,
pb_tnc_msg_t *pb_tnc_msg;
pb_tnc_batch_type_t batch_type;
+ if (!this->send_msg)
+ {
+ DBG1(DBG_TNC, "%s %u not allowed to call SendMessage()",
+ this->is_server ? "IMV" : "IMC",
+ this->is_server ? imv_id : imc_id);
+ return TNC_RESULT_ILLEGAL_OPERATION;
+ }
+
msg_sub_type = msg_type & TNC_SUBTYPE_ANY;
msg_vendor_id = (msg_type >> 8) & TNC_VENDORID_ANY;
@@ -119,6 +132,7 @@ METHOD(tnccs_t, send_msg, void,
pb_tnc_msg->destroy(pb_tnc_msg);
}
this->mutex->unlock(this->mutex);
+ return TNC_RESULT_SUCCESS;
}
/**
@@ -145,6 +159,7 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
DBG2(DBG_TNC, "handling PB-PA message type 0x%08x", msg_type);
+ this->send_msg = TRUE;
if (this->is_server)
{
charon->imvs->receive_message(charon->imvs,
@@ -155,6 +170,7 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
charon->imcs->receive_message(charon->imcs,
this->connection_id, msg_body.ptr, msg_body.len,msg_type);
}
+ this->send_msg = FALSE;
break;
}
case PB_MSG_ASSESSMENT_RESULT:
@@ -289,14 +305,21 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg)
*/
static void build_retry_batch(private_tnccs_20_t *this)
{
+ pb_tnc_batch_type_t batch_retry_type;
+
+ batch_retry_type = this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY;
if (this->batch)
{
+ if (this->batch->get_type(this->batch) == batch_retry_type)
+ {
+ /* retry batch has already been created */
+ return;
+ }
DBG1(DBG_TNC, "cancelling PB-TNC %N batch",
pb_tnc_batch_type_names, this->batch->get_type(this->batch));
this->batch->destroy(this->batch);
}
- this->batch = pb_tnc_batch_create(this->is_server,
- this->is_server ? PB_BATCH_SRETRY : PB_BATCH_CRETRY);
+ this->batch = pb_tnc_batch_create(this->is_server, batch_retry_type);
}
METHOD(tls_t, process, status_t,
@@ -319,6 +342,8 @@ METHOD(tls_t, process, status_t,
}
charon->imvs->notify_connection_change(charon->imvs,
this->connection_id, TNC_CONNECTION_STATE_CREATE);
+ charon->imvs->notify_connection_change(charon->imvs,
+ this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
}
data = chunk_create(buf, buflen);
@@ -349,7 +374,9 @@ METHOD(tls_t, process, status_t,
/* Restart the measurements */
charon->imcs->notify_connection_change(charon->imcs,
this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
+ this->send_msg = TRUE;
charon->imcs->begin_handshake(charon->imcs, this->connection_id);
+ this->send_msg = FALSE;
}
enumerator = batch->create_msg_enumerator(batch);
@@ -376,6 +403,7 @@ METHOD(tls_t, process, status_t,
}
}
+ this->send_msg = TRUE;
if (this->is_server)
{
charon->imvs->batch_ending(charon->imvs, this->connection_id);
@@ -384,6 +412,7 @@ METHOD(tls_t, process, status_t,
{
charon->imcs->batch_ending(charon->imcs, this->connection_id);
}
+ this->send_msg = FALSE;
}
switch (status)
@@ -463,6 +492,7 @@ METHOD(tls_t, build, status_t,
private_tnccs_20_t *this, void *buf, size_t *buflen, size_t *msglen)
{
status_t status;
+ pb_tnc_state_t state;
/* Initialize the connection */
if (!this->is_server && !this->connection_id)
@@ -491,11 +521,14 @@ METHOD(tls_t, build, status_t,
this->connection_id, TNC_CONNECTION_STATE_CREATE);
charon->imcs->notify_connection_change(charon->imcs,
this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
+ this->send_msg = TRUE;
charon->imcs->begin_handshake(charon->imcs, this->connection_id);
+ this->send_msg = FALSE;
}
- if (this->is_server && this->fatal_error &&
- this->state_machine->get_state(this->state_machine) == PB_STATE_END)
+ state = this->state_machine->get_state(this->state_machine);
+
+ if (this->is_server && this->fatal_error && state == PB_STATE_END)
{
DBG1(DBG_TNC, "a fatal PB-TNC error occurred, terminating connection");
return FAILED;
@@ -506,7 +539,10 @@ METHOD(tls_t, build, status_t,
if (this->request_handshake_retry)
{
- build_retry_batch(this);
+ if (state != PB_STATE_INIT)
+ {
+ build_retry_batch(this);
+ }
/* Reset the flag for the next handshake retry request */
this->request_handshake_retry = FALSE;
@@ -514,9 +550,6 @@ METHOD(tls_t, build, status_t,
if (!this->batch)
{
- pb_tnc_state_t state;
-
- state = this->state_machine->get_state(this->state_machine);
if (this->is_server)
{
if (state == PB_STATE_SERVER_WORKING)
@@ -606,11 +639,7 @@ METHOD(tls_t, is_complete, bool,
if (this->recs && this->recs->have_recommendation(this->recs, &rec, &eval))
{
- DBG2(DBG_TNC, "Final recommendation is '%N' and evaluation is '%N'",
- TNC_IMV_Action_Recommendation_names, rec,
- TNC_IMV_Evaluation_Result_names, eval);
-
- return charon->imvs->enforce_recommendation(charon->imvs, rec);
+ return charon->imvs->enforce_recommendation(charon->imvs, rec, eval);
}
else
{
@@ -627,17 +656,8 @@ METHOD(tls_t, get_eap_msk, chunk_t,
METHOD(tls_t, destroy, void,
private_tnccs_20_t *this)
{
- if (this->is_server)
- {
- charon->imvs->notify_connection_change(charon->imvs,
- this->connection_id, TNC_CONNECTION_STATE_DELETE);
- }
- else
- {
- charon->imcs->notify_connection_change(charon->imcs,
- this->connection_id, TNC_CONNECTION_STATE_DELETE);
- }
- charon->tnccs->remove_connection(charon->tnccs, this->connection_id);
+ charon->tnccs->remove_connection(charon->tnccs, this->connection_id,
+ this->is_server);
this->state_machine->destroy(this->state_machine);
this->mutex->destroy(this->mutex);
DESTROY_IF(this->batch);