Implemented PT-EAP protocol (RFC 7171)
This commit is contained in:
+68
-45
@@ -47,7 +47,7 @@ struct private_tls_eap_t {
|
||||
/**
|
||||
* Current value of EAP identifier
|
||||
*/
|
||||
u_int8_t identifier;
|
||||
uint8_t identifier;
|
||||
|
||||
/**
|
||||
* TLS stack
|
||||
@@ -59,6 +59,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.
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user