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.c113
1 files changed, 68 insertions, 45 deletions
diff --git a/src/libtls/tls_eap.c b/src/libtls/tls_eap.c
index 68cebb994..ebe5bc3a8 100644
--- a/src/libtls/tls_eap.c
+++ b/src/libtls/tls_eap.c
@@ -47,7 +47,7 @@ struct private_tls_eap_t {
/**
* Current value of EAP identifier
*/
- u_int8_t identifier;
+ uint8_t identifier;
/**
* TLS stack
@@ -60,6 +60,11 @@ struct private_tls_eap_t {
bool is_server;
/**
+ * Supported version of the EAP tunnel protocol
+ */
+ uint8_t supported_version;
+
+ /**
* 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.
@@ -94,22 +99,24 @@ typedef enum {
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_TTLS_VERSION = (0x07), /* shared with EAP-TNC/PEAP/PT-EAP */
+ EAP_PT_START = (1<<7) /* PT-EAP only */
} eap_tls_flags_t;
-#define EAP_TTLS_SUPPORTED_VERSION 0
-#define EAP_TNC_SUPPORTED_VERSION 1
-#define EAP_PEAP_SUPPORTED_VERSION 0
+#define EAP_TTLS_SUPPORTED_VERSION 0
+#define EAP_TNC_SUPPORTED_VERSION 1
+#define EAP_PEAP_SUPPORTED_VERSION 0
+#define EAP_PT_EAP_SUPPORTED_VERSION 1
/**
* EAP-TLS/TTLS packet format
*/
typedef struct __attribute__((packed)) {
- u_int8_t code;
- u_int8_t identifier;
- u_int16_t length;
- u_int8_t type;
- u_int8_t flags;
+ uint8_t code;
+ uint8_t identifier;
+ uint16_t length;
+ uint8_t type;
+ uint8_t flags;
} eap_tls_packet_t;
METHOD(tls_eap_t, initiate, status_t,
@@ -120,18 +127,18 @@ METHOD(tls_eap_t, initiate, status_t,
eap_tls_packet_t pkt = {
.type = this->type,
.code = EAP_REQUEST,
- .flags = EAP_TLS_START,
+ .flags = this->supported_version
};
switch (this->type)
{
+ case EAP_TLS:
case EAP_TTLS:
- pkt.flags |= EAP_TTLS_SUPPORTED_VERSION;
- break;
case EAP_TNC:
- pkt.flags |= EAP_TNC_SUPPORTED_VERSION;
- break;
case EAP_PEAP:
- pkt.flags |= EAP_PEAP_SUPPORTED_VERSION;
+ pkt.flags |= EAP_TLS_START;
+ break;
+ case EAP_PT_EAP:
+ pkt.flags |= EAP_PT_START;
break;
default:
break;
@@ -153,13 +160,25 @@ METHOD(tls_eap_t, initiate, status_t,
*/
static status_t process_pkt(private_tls_eap_t *this, eap_tls_packet_t *pkt)
{
- u_int16_t pkt_len;
- u_int32_t msg_len;
+ uint8_t version;
+ uint16_t pkt_len;
+ uint32_t msg_len;
size_t msg_len_offset = 0;
+ /* EAP-TLS doesn't have a version field */
+ if (this->type != EAP_TLS)
+ {
+ version = pkt->flags & EAP_TTLS_VERSION;
+ if (version != this->supported_version)
+ {
+ DBG1(DBG_TLS, "received %N packet with unsupported version v%u",
+ eap_type_names, this->type, version);
+ return FAILED;
+ }
+ }
pkt_len = untoh16(&pkt->length);
- if (pkt->flags & EAP_TLS_LENGTH)
+ if (this->type != EAP_PT_EAP && (pkt->flags & EAP_TLS_LENGTH))
{
if (pkt_len < sizeof(eap_tls_packet_t) + sizeof(msg_len))
{
@@ -200,27 +219,12 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
pkt->code = this->is_server ? EAP_REQUEST : EAP_RESPONSE;
pkt->identifier = this->identifier;
pkt->type = this->type;
- pkt->flags = 0;
-
- switch (this->type)
- {
- case EAP_TTLS:
- pkt->flags |= EAP_TTLS_SUPPORTED_VERSION;
- break;
- case EAP_TNC:
- pkt->flags |= EAP_TNC_SUPPORTED_VERSION;
- break;
- case EAP_PEAP:
- pkt->flags |= EAP_PEAP_SUPPORTED_VERSION;
- break;
- default:
- break;
- }
+ pkt->flags = this->supported_version;
if (this->first_fragment)
{
- len = sizeof(buf) - sizeof(eap_tls_packet_t) - sizeof(u_int32_t);
- msg_len_offset = sizeof(u_int32_t);
+ len = sizeof(buf) - sizeof(eap_tls_packet_t) - sizeof(uint32_t);
+ msg_len_offset = sizeof(uint32_t);
}
else
{
@@ -251,7 +255,7 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
}
kind = "packet";
}
- else if (this->type != EAP_TNC)
+ else if (this->type != EAP_TNC && this->type != EAP_PT_EAP)
{
this->first_fragment = TRUE;
kind = "final fragment";
@@ -269,14 +273,14 @@ static status_t build_pkt(private_tls_eap_t *this, chunk_t *out)
if (pkt->flags & EAP_TLS_LENGTH)
{
htoun32(pkt + 1, reclen);
- len += sizeof(u_int32_t);
+ len += sizeof(uint32_t);
pkt->flags |= EAP_TLS_LENGTH;
}
else
{
/* get rid of the reserved length field */
memmove(buf + sizeof(eap_tls_packet_t),
- buf + sizeof(eap_tls_packet_t) + sizeof(u_int32_t), len);
+ buf + sizeof(eap_tls_packet_t) + sizeof(uint32_t), len);
}
}
len += sizeof(eap_tls_packet_t);
@@ -352,10 +356,11 @@ METHOD(tls_eap_t, process, status_t,
}
DBG3(DBG_TLS, "%N payload %B", eap_type_names, this->type, &in);
- if (pkt->flags & EAP_TLS_START)
+ if ((this->type == EAP_PT_EAP && (pkt->flags & EAP_PT_START)) ||
+ (pkt->flags & EAP_TLS_START))
{
if (this->type == EAP_TTLS || this->type == EAP_TNC ||
- this->type == EAP_PEAP)
+ this->type == EAP_PEAP || this->type == EAP_PT_EAP)
{
DBG1(DBG_TLS, "%N version is v%u", eap_type_names, this->type,
pkt->flags & EAP_TTLS_VERSION);
@@ -409,14 +414,14 @@ 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,
+METHOD(tls_eap_t, get_identifier, uint8_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)
+ private_tls_eap_t *this, uint8_t identifier)
{
this->identifier = identifier;
}
@@ -452,13 +457,31 @@ 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 = (type != EAP_TNC),
+ .first_fragment = (type != EAP_TNC && type != EAP_PT_EAP),
.frag_size = frag_size,
.max_msg_count = max_msg_count,
.include_length = include_length,
.tls = tls,
);
+ switch (type)
+ {
+ case EAP_TTLS:
+ this->supported_version = EAP_TTLS_SUPPORTED_VERSION;
+ break;
+ case EAP_TNC:
+ this->supported_version = EAP_TNC_SUPPORTED_VERSION;
+ break;
+ case EAP_PEAP:
+ this->supported_version = EAP_PEAP_SUPPORTED_VERSION;
+ break;
+ case EAP_PT_EAP:
+ this->supported_version = EAP_PT_EAP_SUPPORTED_VERSION;
+ break;
+ default:
+ break;
+ }
+
if (this->is_server)
{
do