diff --git a/NEWS b/NEWS index 384f2dcb0..a9dec6ad6 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,13 @@ strongswan-5.8.0 - The openssl plugin supports ChaCha20-Poly1305 when built with OpenSSL 1.1.0. +- The PB-TNC finite state machine according to section 3.2 of RFC 5793 was not + correctly implemented when sending either a CRETRY or SRETRY batch. These + batches can only be sent in the "Decided" state and a CRETRY batch can + immediately carry all messages usually transported by a CDATA batch. It is + currently not possible to send a SRETRY batch since full-duplex mode for + PT-TLS transport is not supported. + strongswan-5.7.2 ---------------- diff --git a/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c b/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c index 43f185440..51ce38453 100644 --- a/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c +++ b/src/libtnccs/plugins/tnccs_20/state_machine/pb_tnc_state_machine.c @@ -134,15 +134,12 @@ METHOD(pb_tnc_state_machine_t, receive_batch, bool, } return FALSE; case PB_STATE_CLIENT_WORKING: - if (this->is_server && type == PB_BATCH_CDATA) + if (this->is_server && + (type == PB_BATCH_CDATA || type == PB_BATCH_CRETRY)) { this->state = PB_STATE_SERVER_WORKING; break; } - if (this->is_server && type == PB_BATCH_CRETRY) - { - break; - } if (type == PB_BATCH_CLOSE) { this->state = PB_STATE_END; diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c index 04e404225..c8fdf0d30 100644 --- a/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c +++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_client.c @@ -538,9 +538,19 @@ METHOD(tnccs_20_handler_t, build, status_t, if (this->request_handshake_retry) { - if (state != PB_STATE_INIT) + if (state == PB_STATE_DECIDED) { + build_retry_batch(this); + + /* Restart the measurements */ + tnc->imcs->notify_connection_change(tnc->imcs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + this->send_msg = TRUE; + this->mutex->unlock(this->mutex); + tnc->imcs->begin_handshake(tnc->imcs, this->connection_id); + this->mutex->lock(this->mutex); + this->send_msg = FALSE; } /* Reset the flag for the next handshake retry request */ @@ -714,7 +724,7 @@ METHOD(tnccs_20_handler_t, add_msg, void, { this->batch_type = PB_BATCH_CDATA; } - if (this->batch_type == PB_BATCH_CDATA) + if (this->batch_type == PB_BATCH_CDATA || this->batch_type == PB_BATCH_CRETRY) { this->messages->insert_last(this->messages, msg); } diff --git a/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c index 32d950297..44889d7e9 100644 --- a/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c +++ b/src/libtnccs/plugins/tnccs_20/tnccs_20_server.c @@ -282,11 +282,6 @@ static void build_retry_batch(private_tnccs_20_server_t *this) return; } change_batch_type(this, PB_BATCH_SRETRY); - - this->recs->clear_recommendation(this->recs); - - /* Handshake will be retried with next incoming CDATA batch */ - this->retry_handshake = TRUE; } METHOD(tnccs_20_handler_t, process, status_t, @@ -307,22 +302,13 @@ METHOD(tnccs_20_handler_t, process, status_t, pb_tnc_msg_t *msg; bool empty = TRUE; - if (batch_type == PB_BATCH_CDATA) + if (batch_type == PB_BATCH_CRETRY || + (batch_type == PB_BATCH_CDATA && this->retry_handshake)) { - /* retry handshake after a previous SRETRY batch */ - if (this->retry_handshake) - { - tnc->imvs->notify_connection_change(tnc->imvs, - this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); - this->retry_handshake = FALSE; - } - } - else if (batch_type == PB_BATCH_CRETRY) - { - /* Send an SRETRY batch in response */ - this->mutex->lock(this->mutex); - build_retry_batch(this); - this->mutex->unlock(this->mutex); + this->recs->clear_recommendation(this->recs); + tnc->imvs->notify_connection_change(tnc->imvs, + this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); + this->retry_handshake = FALSE; } enumerator = batch->create_msg_enumerator(batch); @@ -441,9 +427,12 @@ METHOD(tnccs_20_handler_t, build, status_t, if (this->request_handshake_retry) { - if (state != PB_STATE_INIT) + if (state == PB_STATE_DECIDED) { build_retry_batch(this); + + /* Handshake will be retried with next incoming CDATA batch */ + this->retry_handshake = TRUE; } /* Reset the flag for the next handshake retry request */