aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libtls/tls.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/src/libtls/tls.c b/src/libtls/tls.c
index 61787e366..34de7cc42 100644
--- a/src/libtls/tls.c
+++ b/src/libtls/tls.c
@@ -55,6 +55,15 @@ ENUM_NEXT(tls_handshake_type_names, TLS_FINISHED, TLS_FINISHED, TLS_CLIENT_KEY_E
"Finished");
ENUM_END(tls_handshake_type_names, TLS_FINISHED);
+/**
+ * TLS record
+ */
+typedef struct __attribute__((packed)) {
+ u_int8_t type;
+ u_int16_t version;
+ u_int16_t length;
+ char data[];
+} tls_record_t;
typedef struct private_tls_t private_tls_t;
@@ -147,17 +156,17 @@ struct private_tls_t {
* Number of bytes processed from output buffer
*/
size_t outpos;
-};
-/**
- * TLS record
- */
-typedef struct __attribute__((packed)) {
- u_int8_t type;
- u_int16_t version;
- u_int16_t length;
- char data[];
-} tls_record_t;
+ /**
+ * Partial TLS record header received
+ */
+ tls_record_t head;
+
+ /**
+ * Position in partially received record header
+ */
+ size_t headpos;
+};
METHOD(tls_t, process, status_t,
private_tls_t *this, void *buf, size_t buflen)
@@ -166,12 +175,32 @@ METHOD(tls_t, process, status_t,
status_t status;
u_int len;
+ if (this->headpos)
+ { /* have a partial TLS record header, try to complete it */
+ len = min(buflen, sizeof(this->head) - this->headpos);
+ memcpy(((char*)&this->head) + this->headpos, buf, len);
+ this->headpos += len;
+ buflen -= len;
+ buf += len;
+ if (this->headpos == sizeof(this->head))
+ { /* header complete, allocate space with new header */
+ len = untoh16(&this->head.length);
+ this->input = chunk_alloc(len + sizeof(tls_record_t));
+ memcpy(this->input.ptr, &this->head, sizeof(this->head));
+ this->inpos = sizeof(this->head);
+ this->headpos = 0;
+ }
+ }
+
while (buflen)
{
if (this->input.len == 0)
{
if (buflen < sizeof(tls_record_t))
{
+ DBG2(DBG_TLS, "received incomplete TLS record header");
+ memcpy(&this->head, buf, buflen);
+ this->headpos = buflen;
break;
}
while (TRUE)
@@ -226,11 +255,6 @@ METHOD(tls_t, process, status_t,
}
}
}
- if (buflen != 0)
- {
- DBG1(DBG_TLS, "received incomplete TLS record header");
- return FAILED;
- }
return NEED_MORE;
}