Refactored fragment building, use correct TLS content type for non-first fragments

This commit is contained in:
Martin Willi
2010-08-25 18:04:59 +02:00
parent dfde6570c7
commit ee88ddd6aa
+82 -67
View File
@@ -83,6 +83,11 @@ struct private_tls_fragmentation_t {
*/
chunk_t output;
/**
* Type of data in output buffer
*/
tls_content_type_t output_type;
/**
* Upper layer application data protocol
*/
@@ -288,12 +293,77 @@ static bool check_alerts(private_tls_fragmentation_t *this, chunk_t *data)
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,
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;
switch (this->state)
@@ -318,81 +388,26 @@ METHOD(tls_fragmentation_t, build, status_t,
*data = chunk_clone(chunk_from_chars(0x01));
return NEED_MORE;
}
if (!this->output.len)
{
msg = tls_writer_create(64);
if (this->handshake->finished(this->handshake))
if (!this->handshake->finished(this->handshake))
{
if (this->application)
{
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;
}
}
status = build_handshake(this);
}
else
else if (this->application)
{
do
{
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);
status = build_application(this);
}
msg->destroy(msg);
if (status != INVALID_STATE)
if (check_alerts(this, data))
{
return status;
this->state = ALERT_SENDING;
*type = TLS_ALERT;
return NEED_MORE;
}
}
if (this->output.len)
{
*type = this->output_type;
if (this->output.len <= MAX_TLS_FRAGMENT_LEN)
{
*data = this->output;