Refactored fragment building, use correct TLS content type for non-first fragments
This commit is contained in:
@@ -83,6 +83,11 @@ struct private_tls_fragmentation_t {
|
|||||||
*/
|
*/
|
||||||
chunk_t output;
|
chunk_t output;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of data in output buffer
|
||||||
|
*/
|
||||||
|
tls_content_type_t output_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upper layer application data protocol
|
* Upper layer application data protocol
|
||||||
*/
|
*/
|
||||||
@@ -288,12 +293,77 @@ static bool check_alerts(private_tls_fragmentation_t *this, chunk_t *data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build hanshake message
|
||||||
|
*/
|
||||||
|
static status_t build_handshake(private_tls_fragmentation_t *this)
|
||||||
|
{
|
||||||
|
tls_writer_t *hs, *msg;
|
||||||
|
tls_handshake_type_t type;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
msg = tls_writer_create(64);
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
hs = tls_writer_create(64);
|
||||||
|
status = this->handshake->build(this->handshake, &type, hs);
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
msg->write_uint8(msg, type);
|
||||||
|
msg->write_data24(msg, hs->get_buf(hs));
|
||||||
|
DBG2(DBG_TLS, "sending TLS %N message (%u bytes)",
|
||||||
|
tls_handshake_type_names, type, 4 + hs->get_buf(hs).len);
|
||||||
|
hs->destroy(hs);
|
||||||
|
continue;
|
||||||
|
case INVALID_STATE:
|
||||||
|
this->output_type = TLS_HANDSHAKE;
|
||||||
|
this->output = chunk_clone(msg->get_buf(msg));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hs->destroy(hs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
msg->destroy(msg);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static status_t build_application(private_tls_fragmentation_t *this)
|
||||||
|
{
|
||||||
|
tls_writer_t *msg;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
msg = tls_writer_create(64);
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
status = this->application->build(this->application, msg);
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case NEED_MORE:
|
||||||
|
continue;
|
||||||
|
case INVALID_STATE:
|
||||||
|
this->output_type = TLS_APPLICATION_DATA;
|
||||||
|
this->output = chunk_clone(msg->get_buf(msg));
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
this->application_finished = TRUE;
|
||||||
|
break;
|
||||||
|
case FAILED:
|
||||||
|
default:
|
||||||
|
this->alert->add(this->alert, TLS_FATAL, TLS_CLOSE_NOTIFY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
msg->destroy(msg);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(tls_fragmentation_t, build, status_t,
|
METHOD(tls_fragmentation_t, build, status_t,
|
||||||
private_tls_fragmentation_t *this, tls_content_type_t *type, chunk_t *data)
|
private_tls_fragmentation_t *this, tls_content_type_t *type, chunk_t *data)
|
||||||
{
|
{
|
||||||
chunk_t hs_data;
|
|
||||||
tls_handshake_type_t hs_type;
|
|
||||||
tls_writer_t *writer, *msg;
|
|
||||||
status_t status = INVALID_STATE;
|
status_t status = INVALID_STATE;
|
||||||
|
|
||||||
switch (this->state)
|
switch (this->state)
|
||||||
@@ -318,81 +388,26 @@ METHOD(tls_fragmentation_t, build, status_t,
|
|||||||
*data = chunk_clone(chunk_from_chars(0x01));
|
*data = chunk_clone(chunk_from_chars(0x01));
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->output.len)
|
if (!this->output.len)
|
||||||
{
|
{
|
||||||
msg = tls_writer_create(64);
|
if (!this->handshake->finished(this->handshake))
|
||||||
|
|
||||||
if (this->handshake->finished(this->handshake))
|
|
||||||
{
|
{
|
||||||
if (this->application)
|
status = build_handshake(this);
|
||||||
{
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
status = this->application->build(this->application, msg);
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case NEED_MORE:
|
|
||||||
continue;
|
|
||||||
case INVALID_STATE:
|
|
||||||
*type = TLS_APPLICATION_DATA;
|
|
||||||
this->output = chunk_clone(msg->get_buf(msg));
|
|
||||||
break;
|
|
||||||
case SUCCESS:
|
|
||||||
this->application_finished = TRUE;
|
|
||||||
return SUCCESS;
|
|
||||||
case FAILED:
|
|
||||||
default:
|
|
||||||
this->alert->add(this->alert, TLS_FATAL,
|
|
||||||
TLS_CLOSE_NOTIFY);
|
|
||||||
if (check_alerts(this, data))
|
|
||||||
{
|
|
||||||
this->state = ALERT_SENDING;
|
|
||||||
*type = TLS_ALERT;
|
|
||||||
msg->destroy(msg);
|
|
||||||
return NEED_MORE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else if (this->application)
|
||||||
{
|
{
|
||||||
do
|
status = build_application(this);
|
||||||
{
|
|
||||||
writer = tls_writer_create(64);
|
|
||||||
status = this->handshake->build(this->handshake, &hs_type, writer);
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case NEED_MORE:
|
|
||||||
hs_data = writer->get_buf(writer);
|
|
||||||
msg->write_uint8(msg, hs_type);
|
|
||||||
msg->write_data24(msg, hs_data);
|
|
||||||
DBG2(DBG_TLS, "sending TLS %N message (%u bytes)",
|
|
||||||
tls_handshake_type_names, hs_type, 4 + hs_data.len);
|
|
||||||
break;
|
|
||||||
case INVALID_STATE:
|
|
||||||
*type = TLS_HANDSHAKE;
|
|
||||||
this->output = chunk_clone(msg->get_buf(msg));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
writer->destroy(writer);
|
|
||||||
}
|
|
||||||
while (status == NEED_MORE);
|
|
||||||
}
|
}
|
||||||
|
if (check_alerts(this, data))
|
||||||
msg->destroy(msg);
|
|
||||||
if (status != INVALID_STATE)
|
|
||||||
{
|
{
|
||||||
return status;
|
this->state = ALERT_SENDING;
|
||||||
|
*type = TLS_ALERT;
|
||||||
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->output.len)
|
if (this->output.len)
|
||||||
{
|
{
|
||||||
|
*type = this->output_type;
|
||||||
if (this->output.len <= MAX_TLS_FRAGMENT_LEN)
|
if (this->output.len <= MAX_TLS_FRAGMENT_LEN)
|
||||||
{
|
{
|
||||||
*data = this->output;
|
*data = this->output;
|
||||||
|
|||||||
Reference in New Issue
Block a user