mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-01-20 17:54:05 +01:00
eap-tls-common: Add support for fragmented response
This commit is contained in:
parent
718f967d17
commit
c35c91ad20
@ -98,6 +98,11 @@ struct eap_tls_state {
|
|||||||
struct databuf *tx_pdu_buf;
|
struct databuf *tx_pdu_buf;
|
||||||
struct databuf *rx_pdu_buf;
|
struct databuf *rx_pdu_buf;
|
||||||
|
|
||||||
|
size_t tx_frag_offset;
|
||||||
|
size_t tx_frag_last_len;
|
||||||
|
|
||||||
|
bool expecting_frag_ack:1;
|
||||||
|
|
||||||
char *ca_cert;
|
char *ca_cert;
|
||||||
char *client_cert;
|
char *client_cert;
|
||||||
char *client_key;
|
char *client_key;
|
||||||
@ -109,12 +114,16 @@ struct eap_tls_state {
|
|||||||
static void __eap_tls_common_state_reset(struct eap_tls_state *eap_tls)
|
static void __eap_tls_common_state_reset(struct eap_tls_state *eap_tls)
|
||||||
{
|
{
|
||||||
eap_tls->version_negotiated = EAP_TLS_VERSION_NOT_NEGOTIATED;
|
eap_tls->version_negotiated = EAP_TLS_VERSION_NOT_NEGOTIATED;
|
||||||
|
eap_tls->expecting_frag_ack = false;
|
||||||
|
|
||||||
if (eap_tls->tunnel) {
|
if (eap_tls->tunnel) {
|
||||||
l_tls_free(eap_tls->tunnel);
|
l_tls_free(eap_tls->tunnel);
|
||||||
eap_tls->tunnel = NULL;
|
eap_tls->tunnel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eap_tls->tx_frag_offset = 0;
|
||||||
|
eap_tls->tx_frag_last_len = 0;
|
||||||
|
|
||||||
if (eap_tls->plain_buf) {
|
if (eap_tls->plain_buf) {
|
||||||
databuf_free(eap_tls->plain_buf);
|
databuf_free(eap_tls->plain_buf);
|
||||||
eap_tls->plain_buf = NULL;
|
eap_tls->plain_buf = NULL;
|
||||||
@ -215,17 +224,55 @@ static bool eap_tls_validate_version(struct eap_state *eap,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void eap_tls_send_fragment(struct eap_state *eap)
|
||||||
|
{
|
||||||
|
struct eap_tls_state *eap_tls = eap_get_data(eap);
|
||||||
|
size_t mtu = eap_get_mtu(eap);
|
||||||
|
uint8_t buf[mtu];
|
||||||
|
size_t len = eap_tls->tx_pdu_buf->len - eap_tls->tx_frag_offset;
|
||||||
|
size_t header_len = EAP_TLS_HEADER_LEN;
|
||||||
|
|
||||||
|
buf[EAP_TLS_HEADER_OCTET_FLAGS] = eap_tls->version_negotiated;
|
||||||
|
|
||||||
|
if (len > mtu - EAP_TLS_HEADER_LEN) {
|
||||||
|
len = mtu - EAP_TLS_HEADER_LEN;
|
||||||
|
buf[EAP_TLS_HEADER_OCTET_FLAGS] |= EAP_TLS_FLAG_M;
|
||||||
|
eap_tls->expecting_frag_ack = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eap_tls->tx_frag_offset) {
|
||||||
|
buf[EAP_TLS_HEADER_OCTET_FLAGS] |= EAP_TLS_FLAG_L;
|
||||||
|
l_put_be32(eap_tls->tx_pdu_buf->len,
|
||||||
|
&buf[EAP_TLS_HEADER_OCTET_FRAG_LEN]);
|
||||||
|
len -= 4;
|
||||||
|
header_len += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf + header_len,
|
||||||
|
eap_tls->tx_pdu_buf->data + eap_tls->tx_frag_offset, len);
|
||||||
|
eap_send_response(eap, eap_get_method_type(eap), buf, header_len + len);
|
||||||
|
|
||||||
|
eap_tls->tx_frag_last_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
static void eap_tls_send_response(struct eap_state *eap,
|
static void eap_tls_send_response(struct eap_state *eap,
|
||||||
const uint8_t *pdu, size_t pdu_len)
|
const uint8_t *pdu, size_t pdu_len)
|
||||||
{
|
{
|
||||||
struct eap_tls_state *eap_tls = eap_get_data(eap);
|
struct eap_tls_state *eap_tls = eap_get_data(eap);
|
||||||
size_t msg_len = EAP_TLS_HEADER_LEN + pdu_len;
|
size_t msg_len = EAP_TLS_HEADER_LEN + pdu_len;
|
||||||
|
|
||||||
|
if (msg_len <= eap_get_mtu(eap)) {
|
||||||
uint8_t buf[msg_len];
|
uint8_t buf[msg_len];
|
||||||
|
|
||||||
buf[EAP_TLS_HEADER_OCTET_FLAGS] = eap_tls->version_negotiated;
|
buf[EAP_TLS_HEADER_OCTET_FLAGS] = eap_tls->version_negotiated;
|
||||||
memcpy(buf + EAP_TLS_HEADER_LEN, pdu, pdu_len);
|
memcpy(buf + EAP_TLS_HEADER_LEN, pdu, pdu_len);
|
||||||
|
|
||||||
eap_send_response(eap, eap_get_method_type(eap), buf, msg_len);
|
eap_send_response(eap, eap_get_method_type(eap), buf, msg_len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
eap_tls->tx_frag_offset = 0;
|
||||||
|
eap_tls_send_fragment(eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eap_tls_common_send_empty_response(struct eap_state *eap)
|
static void eap_tls_common_send_empty_response(struct eap_state *eap)
|
||||||
@ -334,6 +381,26 @@ static void eap_tls_send_fragmented_request_ack(struct eap_state *eap)
|
|||||||
eap_tls_common_send_empty_response(eap);
|
eap_tls_common_send_empty_response(eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool eap_tls_handle_fragmented_response_ack(struct eap_state *eap,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
struct eap_tls_state *eap_tls = eap_get_data(eap);
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!eap_tls->tx_frag_last_len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
eap_tls->tx_frag_offset += eap_tls->tx_frag_last_len;
|
||||||
|
eap_tls->tx_frag_last_len = 0;
|
||||||
|
eap_tls->expecting_frag_ack = false;
|
||||||
|
|
||||||
|
eap_tls_send_fragment(eap);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int eap_tls_handle_fragmented_request(struct eap_state *eap,
|
static int eap_tls_handle_fragmented_request(struct eap_state *eap,
|
||||||
const uint8_t *pkt,
|
const uint8_t *pkt,
|
||||||
size_t len,
|
size_t len,
|
||||||
@ -431,6 +498,13 @@ void eap_tls_common_handle_request(struct eap_state *eap,
|
|||||||
pkt += 1;
|
pkt += 1;
|
||||||
len -= 1;
|
len -= 1;
|
||||||
|
|
||||||
|
if (eap_tls->expecting_frag_ack) {
|
||||||
|
if (!eap_tls_handle_fragmented_response_ack(eap, len))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (flags_version & EAP_TLS_FLAG_L || eap_tls->rx_pdu_buf) {
|
if (flags_version & EAP_TLS_FLAG_L || eap_tls->rx_pdu_buf) {
|
||||||
int r = eap_tls_handle_fragmented_request(eap, pkt, len,
|
int r = eap_tls_handle_fragmented_request(eap, pkt, len,
|
||||||
flags_version);
|
flags_version);
|
||||||
|
Loading…
Reference in New Issue
Block a user