summaryrefslogtreecommitdiff
path: root/src/libtls/tls_eap.c
diff options
context:
space:
mode:
authorRené Mayrhofer <rene@mayrhofer.eu.org>2011-05-19 13:37:29 +0200
committerRené Mayrhofer <rene@mayrhofer.eu.org>2011-05-19 13:37:29 +0200
commit0a9d51a49042a68daa15b0c74a2b7f152f52606b (patch)
tree451888dcb17d00e52114f734e846821373fbbd44 /src/libtls/tls_eap.c
parent568905f488e63e28778f87ac0e38d845f45bae79 (diff)
downloadvyos-strongswan-0a9d51a49042a68daa15b0c74a2b7f152f52606b.tar.gz
vyos-strongswan-0a9d51a49042a68daa15b0c74a2b7f152f52606b.zip
Imported Upstream version 4.5.2
Diffstat (limited to 'src/libtls/tls_eap.c')
-rw-r--r--src/libtls/tls_eap.c148
1 files changed, 113 insertions, 35 deletions
diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c
index 8204a3441..685904fdf 100644
--- a/src/libtls/tls_eap.c
+++ b/src/libtls/tls_eap.c
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -41,6 +42,11 @@ struct private_tls_eap_t {
eap_type_t type;
/**
+ * Current value of EAP identifier
+ */
+ u_int8_t identifier;
+
+ /**
* TLS stack
*/
tls_t *tls;
@@ -51,6 +57,13 @@ struct private_tls_eap_t {
bool is_server;
/**
+ * If FALSE include the total length of an EAP message
+ * in the first fragment of fragmented messages only.
+ * If TRUE also include the length in non-fragmented messages.
+ */
+ bool include_length;
+
+ /**
* First fragment of a multi-fragment record?
*/
bool first_fragment;
@@ -75,14 +88,15 @@ struct private_tls_eap_t {
* Flags of an EAP-TLS/TTLS/TNC message
*/
typedef enum {
- EAP_TLS_LENGTH = (1<<7), /* shared with EAP-TTLS/TNC */
- EAP_TLS_MORE_FRAGS = (1<<6), /* shared with EAP-TTLS/TNC */
- EAP_TLS_START = (1<<5), /* shared with EAP-TTLS/TNC */
- EAP_TTLS_VERSION = (0x07), /* shared with EAP-TNC */
+ EAP_TLS_LENGTH = (1<<7), /* shared with EAP-TTLS/TNC/PEAP */
+ EAP_TLS_MORE_FRAGS = (1<<6), /* shared with EAP-TTLS/TNC/PEAP */
+ EAP_TLS_START = (1<<5), /* shared with EAP-TTLS/TNC/PEAP */
+ EAP_TTLS_VERSION = (0x07), /* shared with EAP-TNC/PEAP */
} eap_tls_flags_t;
#define EAP_TTLS_SUPPORTED_VERSION 0
#define EAP_TNC_SUPPORTED_VERSION 1
+#define EAP_PEAP_SUPPORTED_VERSION 0
/**
* EAP-TLS/TTLS packet format
@@ -113,18 +127,19 @@ METHOD(tls_eap_t, initiate, status_t,
case EAP_TNC:
pkt.flags |= EAP_TNC_SUPPORTED_VERSION;
break;
+ case EAP_PEAP:
+ pkt.flags |= EAP_PEAP_SUPPORTED_VERSION;
+ break;
default:
break;
}
htoun16(&pkt.length, sizeof(eap_tls_packet_t));
- do
- { /* start with non-zero random identifier */
- pkt.identifier = random();
- }
- while (!pkt.identifier);
+ pkt.identifier = this->identifier;
- DBG2(DBG_IKE, "sending %N start packet", eap_type_names, this->type);
*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));
+ DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
return FAILED;
@@ -163,8 +178,7 @@ static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
/**
* Build a packet to send
*/
-static status_t build_pkt(private_tls_eap_t *this,
- u_int8_t identifier, chunk_t *out)
+static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
{
char buf[this->frag_size];
eap_tls_packet_t *pkt;
@@ -172,9 +186,13 @@ static status_t build_pkt(private_tls_eap_t *this,
status_t status;
char *kind;
+ if (this->is_server)
+ {
+ this->identifier++;
+ }
pkt = (eap_tls_packet_t*)buf;
pkt->code = this->is_server ? EAP_REQUEST : EAP_RESPONSE;
- pkt->identifier = this->is_server ? identifier + 1 : identifier;
+ pkt->identifier = this->identifier;
pkt->type = this->type;
pkt->flags = 0;
@@ -186,13 +204,15 @@ static status_t build_pkt(private_tls_eap_t *this,
case EAP_TNC:
pkt->flags |= EAP_TNC_SUPPORTED_VERSION;
break;
+ case EAP_PEAP:
+ pkt->flags |= EAP_PEAP_SUPPORTED_VERSION;
+ break;
default:
break;
}
if (this->first_fragment)
{
- pkt->flags |= EAP_TLS_LENGTH;
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);
@@ -210,13 +230,21 @@ static status_t build_pkt(private_tls_eap_t *this,
kind = "further fragment";
if (this->first_fragment)
{
+ pkt->flags |= EAP_TLS_LENGTH;
this->first_fragment = FALSE;
kind = "first fragment";
}
break;
case ALREADY_DONE:
- kind = "packet";
- if (!this->first_fragment)
+ if (this->first_fragment)
+ {
+ if (this->include_length)
+ {
+ pkt->flags |= EAP_TLS_LENGTH;
+ }
+ kind = "packet";
+ }
+ else
{
this->first_fragment = TRUE;
kind = "final fragment";
@@ -225,39 +253,58 @@ static status_t build_pkt(private_tls_eap_t *this,
default:
return status;
}
- DBG2(DBG_TLS, "sending %N %s (%u bytes)",
- eap_type_names, this->type, kind, len);
if (reclen)
{
- htoun32(pkt + 1, reclen);
- len += sizeof(u_int32_t);
- pkt->flags |= EAP_TLS_LENGTH;
+ if (pkt->flags & EAP_TLS_LENGTH)
+ {
+ htoun32(pkt + 1, reclen);
+ len += sizeof(u_int32_t);
+ pkt->flags |= EAP_TLS_LENGTH;
+ }
+ else
+ {
+ /* get rid of the reserved length field */
+ memcpy(buf+sizeof(eap_packet_t),
+ buf+sizeof(eap_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);
+ DBG3(DBG_TLS, "%B", out);
return NEED_MORE;
}
/**
* Send an ack to request next fragment
*/
-static chunk_t create_ack(private_tls_eap_t *this, u_int8_t identifier)
+static chunk_t create_ack(private_tls_eap_t *this)
{
eap_tls_packet_t pkt = {
.code = this->is_server ? EAP_REQUEST : EAP_RESPONSE,
- .identifier = this->is_server ? identifier + 1 : identifier,
.type = this->type,
};
+
+ if (this->is_server)
+ {
+ this->identifier++;
+ }
+ pkt.identifier = this->identifier;
htoun16(&pkt.length, sizeof(pkt));
+
switch (this->type)
{
case EAP_TTLS:
pkt.flags |= EAP_TTLS_SUPPORTED_VERSION;
- break;
+ break;
case EAP_TNC:
pkt.flags |= EAP_TNC_SUPPORTED_VERSION;
break;
+ case EAP_PEAP:
+ pkt.flags |= EAP_PEAP_SUPPORTED_VERSION;
+ break;
default:
break;
}
@@ -274,23 +321,30 @@ METHOD(tls_eap_t, process, status_t,
if (++this->processed > this->max_msg_count)
{
- DBG1(DBG_IKE, "%N packet count exceeded (%d > %d)",
+ DBG1(DBG_TLS, "%N packet count exceeded (%d > %d)",
eap_type_names, this->type,
this->processed, this->max_msg_count);
return FAILED;
}
pkt = (eap_tls_packet_t*)in.ptr;
- if (in.len < sizeof(eap_tls_packet_t) ||
- untoh16(&pkt->length) != in.len)
+ if (in.len < sizeof(eap_tls_packet_t) || untoh16(&pkt->length) != in.len)
{
- DBG1(DBG_IKE, "invalid %N packet length",
- eap_type_names, this->type);
+ DBG1(DBG_TLS, "invalid %N packet length", eap_type_names, this->type);
return FAILED;
}
+
+ /* update EAP identifier */
+ if (!this->is_server)
+ {
+ this->identifier = pkt->identifier;
+ }
+ DBG3(DBG_TLS, "%N payload %B", eap_type_names, this->type, &in);
+
if (pkt->flags & EAP_TLS_START)
{
- if (this->type == EAP_TTLS || this->type == EAP_TNC)
+ if (this->type == EAP_TTLS || this->type == EAP_TNC ||
+ this->type == EAP_PEAP)
{
DBG1(DBG_TLS, "%N version is v%u", eap_type_names, this->type,
pkt->flags & EAP_TTLS_VERSION);
@@ -302,7 +356,7 @@ METHOD(tls_eap_t, process, status_t,
{
DBG2(DBG_TLS, "received %N acknowledgement packet",
eap_type_names, this->type);
- status = build_pkt(this, pkt->identifier, out);
+ status = build_pkt(this, out);
if (status == INVALID_STATE && this->tls->is_complete(this->tls))
{
return SUCCESS;
@@ -320,16 +374,16 @@ METHOD(tls_eap_t, process, status_t,
return status;
}
}
- status = build_pkt(this, pkt->identifier, out);
+ status = build_pkt(this, out);
switch (status)
{
case INVALID_STATE:
- *out = create_ack(this, pkt->identifier);
+ *out = create_ack(this);
return NEED_MORE;
case FAILED:
if (!this->is_server)
{
- *out = create_ack(this, pkt->identifier);
+ *out = create_ack(this);
return NEED_MORE;
}
return FAILED;
@@ -344,6 +398,18 @@ METHOD(tls_eap_t, get_msk, chunk_t,
return this->tls->get_eap_msk(this->tls);
}
+METHOD(tls_eap_t, get_identifier, u_int8_t,
+ private_tls_eap_t *this)
+{
+ return this->identifier;
+}
+
+METHOD(tls_eap_t, set_identifier, void,
+ private_tls_eap_t *this, u_int8_t identifier)
+{
+ this->identifier = identifier;
+}
+
METHOD(tls_eap_t, destroy, void,
private_tls_eap_t *this)
{
@@ -355,7 +421,7 @@ METHOD(tls_eap_t, destroy, void,
* See header
*/
tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
- int max_msg_count)
+ int max_msg_count, bool include_length)
{
private_tls_eap_t *this;
@@ -369,6 +435,8 @@ tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
.initiate = _initiate,
.process = _process,
.get_msk = _get_msk,
+ .get_identifier = _get_identifier,
+ .set_identifier = _set_identifier,
.destroy = _destroy,
},
.type = type,
@@ -376,8 +444,18 @@ tls_eap_t *tls_eap_create(eap_type_t type, tls_t *tls, size_t frag_size,
.first_fragment = TRUE,
.frag_size = frag_size,
.max_msg_count = max_msg_count,
+ .include_length = include_length,
.tls = tls,
);
+ if (this->is_server)
+ {
+ do
+ { /* start with non-zero random identifier */
+ this->identifier = random();
+ }
+ while (!this->identifier);
+ }
+
return &this->public;
}