diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2014-05-11 20:49:21 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2014-05-12 06:59:21 +0200 |
commit | 8d59090349cb95e624c134533283a68ae95b8476 (patch) | |
tree | 5792eece918b78c2c6ab21475332e0a27bf2051e /src/libtls | |
parent | ab21875f508a3e7ef3a36d5dbddb367b3f34f1df (diff) | |
download | strongswan-8d59090349cb95e624c134533283a68ae95b8476.tar.bz2 strongswan-8d59090349cb95e624c134533283a68ae95b8476.tar.xz |
Implemented PT-EAP protocol (RFC 7171)
Diffstat (limited to 'src/libtls')
-rw-r--r-- | src/libtls/tls_eap.c | 113 | ||||
-rw-r--r-- | src/libtls/tls_eap.h | 4 |
2 files changed, 70 insertions, 47 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 diff --git a/src/libtls/tls_eap.h b/src/libtls/tls_eap.h index c7da832cb..f3fbba078 100644 --- a/src/libtls/tls_eap.h +++ b/src/libtls/tls_eap.h @@ -66,7 +66,7 @@ struct tls_eap_t { * * @return identifier */ - u_int8_t (*get_identifier)(tls_eap_t *this); + uint8_t (*get_identifier)(tls_eap_t *this); /** * Set the EAP identifier to a deterministic value, overwriting @@ -74,7 +74,7 @@ struct tls_eap_t { * * @param identifier EAP identifier */ - void (*set_identifier) (tls_eap_t *this, u_int8_t identifier); + void (*set_identifier) (tls_eap_t *this, uint8_t identifier); /** * Destroy a tls_eap_t. |