summaryrefslogtreecommitdiff
path: root/src/libtls/tls_eap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libtls/tls_eap.c')
-rw-r--r--src/libtls/tls_eap.c59
1 files changed, 35 insertions, 24 deletions
diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c
index 685904fdf..928aadcb3 100644
--- a/src/libtls/tls_eap.c
+++ b/src/libtls/tls_eap.c
@@ -21,8 +21,11 @@
#include <debug.h>
#include <library.h>
-/** Size limit for a single TLS message */
-#define MAX_TLS_MESSAGE_LEN 65536
+/**
+ * Size limit for a TLS message allowing for worst-case protection overhead
+ * according to section 6.2.3. "Payload Protection" of RFC 5246 TLS 1.2
+ */
+#define TLS_MAX_MESSAGE_LEN 4 * (TLS_MAX_FRAGMENT_LEN + 2048)
typedef struct private_tls_eap_t private_tls_eap_t;
@@ -79,7 +82,7 @@ struct private_tls_eap_t {
int processed;
/**
- * Maximum number of processed EAP messages/fragments
+ * Maximum number of processed EAP messages/fragments
*/
int max_msg_count;
};
@@ -138,7 +141,7 @@ METHOD(tls_eap_t, initiate, status_t,
*out = chunk_clone(chunk_from_thing(pkt));
DBG2(DBG_TLS, "sending %N start packet (%u bytes)",
- eap_type_names, this->type, sizeof(eap_tls_packet_t));
+ eap_type_names, this->type, sizeof(eap_tls_packet_t));
DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
@@ -150,10 +153,12 @@ METHOD(tls_eap_t, initiate, status_t,
*/
static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
{
- u_int32_t msg_len;
u_int16_t pkt_len;
+ u_int32_t msg_len;
+ size_t msg_len_offset = 0;
pkt_len = untoh16(&pkt->length);
+
if (pkt->flags & EAP_TLS_LENGTH)
{
if (pkt_len < sizeof(eap_tls_packet_t) + sizeof(msg_len))
@@ -163,16 +168,17 @@ static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
}
msg_len = untoh32(pkt + 1);
if (msg_len < pkt_len - sizeof(eap_tls_packet_t) - sizeof(msg_len) ||
- msg_len > MAX_TLS_MESSAGE_LEN)
+ msg_len > TLS_MAX_MESSAGE_LEN)
{
- DBG1(DBG_TLS, "invalid %N packet length", eap_type_names, this->type);
+ DBG1(DBG_TLS, "invalid %N packet length (%u bytes)", eap_type_names,
+ this->type, msg_len);
return FAILED;
}
- return this->tls->process(this->tls, (char*)(pkt + 1) + sizeof(msg_len),
- pkt_len - sizeof(eap_tls_packet_t) - sizeof(msg_len));
+ msg_len_offset = sizeof(msg_len);
}
- return this->tls->process(this->tls, (char*)(pkt + 1),
- pkt_len - sizeof(eap_tls_packet_t));
+
+ return this->tls->process(this->tls, (char*)(pkt + 1) + msg_len_offset,
+ pkt_len - sizeof(eap_tls_packet_t) - msg_len_offset);
}
/**
@@ -182,7 +188,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
{
char buf[this->frag_size];
eap_tls_packet_t *pkt;
- size_t len, reclen;
+ size_t len, reclen, msg_len_offset;
status_t status;
char *kind;
@@ -214,15 +220,16 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
if (this->first_fragment)
{
len = sizeof(buf) - sizeof(eap_tls_packet_t) - sizeof(u_int32_t);
- status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t) +
- sizeof(u_int32_t), &len, &reclen);
+ msg_len_offset = sizeof(u_int32_t);
}
else
{
len = sizeof(buf) - sizeof(eap_tls_packet_t);
- status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t),
- &len, &reclen);
+ msg_len_offset = 0;
}
+ status = this->tls->build(this->tls, buf + sizeof(eap_tls_packet_t) +
+ msg_len_offset, &len, &reclen);
+
switch (status)
{
case NEED_MORE:
@@ -230,7 +237,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
kind = "further fragment";
if (this->first_fragment)
{
- pkt->flags |= EAP_TLS_LENGTH;
+ pkt->flags |= EAP_TLS_LENGTH;
this->first_fragment = FALSE;
kind = "first fragment";
}
@@ -244,11 +251,15 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
}
kind = "packet";
}
- else
+ else if (this->type != EAP_TNC)
{
this->first_fragment = TRUE;
kind = "final fragment";
}
+ else
+ {
+ kind = "packet";
+ }
break;
default:
return status;
@@ -256,7 +267,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
if (reclen)
{
if (pkt->flags & EAP_TLS_LENGTH)
- {
+ {
htoun32(pkt + 1, reclen);
len += sizeof(u_int32_t);
pkt->flags |= EAP_TLS_LENGTH;
@@ -264,15 +275,15 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
else
{
/* get rid of the reserved length field */
- memcpy(buf+sizeof(eap_packet_t),
- buf+sizeof(eap_packet_t)+sizeof(u_int32_t), len);
+ memmove(buf + sizeof(eap_tls_packet_t),
+ buf + sizeof(eap_tls_packet_t) + sizeof(u_int32_t), len);
}
}
len += sizeof(eap_tls_packet_t);
htoun16(&pkt->length, len);
*out = chunk_clone(chunk_create(buf, len));
DBG2(DBG_TLS, "sending %N %s (%u bytes)",
- eap_type_names, this->type, kind, len);
+ eap_type_names, this->type, kind, len);
DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
@@ -319,7 +330,7 @@ METHOD(tls_eap_t, process, status_t,
eap_tls_packet_t *pkt;
status_t status;
- if (++this->processed > this->max_msg_count)
+ if (this->max_msg_count && ++this->processed > this->max_msg_count)
{
DBG1(DBG_TLS, "%N packet count exceeded (%d > %d)",
eap_type_names, this->type,
@@ -441,7 +452,7 @@ tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
},
.type = type,
.is_server = tls->is_server(tls),
- .first_fragment = TRUE,
+ .first_fragment = (type != EAP_TNC),
.frag_size = frag_size,
.max_msg_count = max_msg_count,
.include_length = include_length,