Corrected use of PB-TNC CRETRY and SRETRY batches

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. strongSwan currently is not able to send a SRETRY
batch since full-duplex mode for PT-TLS isn't supported yet.
This commit is contained in:
Andreas Steffen 2019-03-29 15:33:24 +01:00
parent 35b82000f1
commit 6fcb3baae8
4 changed files with 31 additions and 28 deletions

7
NEWS
View File

@ -3,6 +3,13 @@ strongswan-5.8.0
- The openssl plugin supports ChaCha20-Poly1305 when built with OpenSSL 1.1.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 strongswan-5.7.2
---------------- ----------------

View File

@ -134,15 +134,12 @@ METHOD(pb_tnc_state_machine_t, receive_batch, bool,
} }
return FALSE; return FALSE;
case PB_STATE_CLIENT_WORKING: 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; this->state = PB_STATE_SERVER_WORKING;
break; break;
} }
if (this->is_server && type == PB_BATCH_CRETRY)
{
break;
}
if (type == PB_BATCH_CLOSE) if (type == PB_BATCH_CLOSE)
{ {
this->state = PB_STATE_END; this->state = PB_STATE_END;

View File

@ -538,9 +538,19 @@ METHOD(tnccs_20_handler_t, build, status_t,
if (this->request_handshake_retry) if (this->request_handshake_retry)
{ {
if (state != PB_STATE_INIT) if (state == PB_STATE_DECIDED)
{ {
build_retry_batch(this); 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 */ /* 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; 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); this->messages->insert_last(this->messages, msg);
} }

View File

@ -282,11 +282,6 @@ static void build_retry_batch(private_tnccs_20_server_t *this)
return; return;
} }
change_batch_type(this, PB_BATCH_SRETRY); 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, METHOD(tnccs_20_handler_t, process, status_t,
@ -307,23 +302,14 @@ METHOD(tnccs_20_handler_t, process, status_t,
pb_tnc_msg_t *msg; pb_tnc_msg_t *msg;
bool empty = TRUE; 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)
{ {
this->recs->clear_recommendation(this->recs);
tnc->imvs->notify_connection_change(tnc->imvs, tnc->imvs->notify_connection_change(tnc->imvs,
this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE); this->connection_id, TNC_CONNECTION_STATE_HANDSHAKE);
this->retry_handshake = FALSE; 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);
}
enumerator = batch->create_msg_enumerator(batch); enumerator = batch->create_msg_enumerator(batch);
while (enumerator->enumerate(enumerator, &msg)) while (enumerator->enumerate(enumerator, &msg))
@ -441,9 +427,12 @@ METHOD(tnccs_20_handler_t, build, status_t,
if (this->request_handshake_retry) if (this->request_handshake_retry)
{ {
if (state != PB_STATE_INIT) if (state == PB_STATE_DECIDED)
{ {
build_retry_batch(this); 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 */ /* Reset the flag for the next handshake retry request */