netdev: hook in RX for FT-Action/Authentication/Association

This forwards Action, Authentication and Association frames to
ft.c via their new hooks in netdev.

Note that this will break FT-over-Air temporarily since the
auth-proto still is in use.
This commit is contained in:
James Prestwood 2022-09-27 12:47:25 -07:00 committed by Denis Kenzior
parent e12f198255
commit 8833a7377e
1 changed files with 65 additions and 84 deletions

View File

@ -3205,13 +3205,15 @@ static void netdev_associate_event(struct l_genl_msg *msg,
const uint8_t *frame = NULL;
uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
int ret;
const struct mmpdu_header *hdr;
const struct mmpdu_association_response *assoc;
l_debug("");
if (!netdev->connected || netdev->aborting)
return;
if (!netdev->ap) {
if (!netdev->ap && !netdev->in_ft) {
netdev->associated = true;
netdev->in_reassoc = false;
return;
@ -3251,61 +3253,59 @@ static void netdev_associate_event(struct l_genl_msg *msg,
if (L_WARN_ON(!frame))
goto assoc_failed;
if (netdev->ap) {
const struct mmpdu_header *hdr;
const struct mmpdu_association_response *assoc;
hdr = mpdu_validate(frame, frame_len);
if (L_WARN_ON(!hdr))
goto assoc_failed;
hdr = mpdu_validate(frame, frame_len);
if (L_WARN_ON(!hdr))
goto assoc_failed;
assoc = mmpdu_body(hdr);
status_code = L_CPU_TO_LE16(assoc->status_code);
assoc = mmpdu_body(hdr);
status_code = L_CPU_TO_LE16(assoc->status_code);
ret = auth_proto_rx_associate(netdev->ap, frame, frame_len);
if (ret == 0) {
bool fils = !!(netdev->handshake->akm_suite &
(IE_RSN_AKM_SUITE_FILS_SHA256 |
IE_RSN_AKM_SUITE_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256));
if (netdev->ap)
ret = auth_proto_rx_associate(netdev->ap, frame,
frame_len);
else
ret = __ft_rx_associate(netdev->index, frame,
frame_len);
if (ret == 0) {
bool fils = !!(netdev->handshake->akm_suite &
(IE_RSN_AKM_SUITE_FILS_SHA256 |
IE_RSN_AKM_SUITE_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384 |
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256));
if (netdev->ap) {
auth_proto_free(netdev->ap);
netdev->ap = NULL;
}
netdev->sm = eapol_sm_new(netdev->handshake);
eapol_register(netdev->sm);
netdev->sm = eapol_sm_new(netdev->handshake);
eapol_register(netdev->sm);
/* Just in case this was a retry */
netdev->ignore_connect_event = false;
/* Just in case this was a retry */
netdev->ignore_connect_event = false;
/*
* If in FT and/or FILS we don't force an initial 4-way
* handshake and instead just keep the EAPoL state
* machine for the rekeys.
*/
if (netdev->in_ft || fils)
eapol_sm_set_require_handshake(netdev->sm,
false);
/*
* If in FT and/or FILS we don't force an initial 4-way
* handshake and instead just keep the EAPoL state
* machine for the rekeys.
*/
if (netdev->in_ft || fils)
eapol_sm_set_require_handshake(netdev->sm,
false);
netdev->in_ft = false;
netdev->in_reassoc = false;
netdev->associated = true;
return;
} else if (ret == -EAGAIN) {
/*
* Here to support OWE retries. OWE will retry
* internally, but a connect event will still be emitted
*/
netdev->ignore_connect_event = true;
return;
} else if (ret > 0)
status_code = (uint16_t)ret;
goto assoc_failed;
}
return;
netdev->in_ft = false;
netdev->in_reassoc = false;
netdev->associated = true;
return;
} else if (ret == -EAGAIN) {
/*
* Here to support OWE retries. OWE will retry
* internally, but a connect event will still be emitted
*/
netdev->ignore_connect_event = true;
return;
} else if (ret > 0)
status_code = (uint16_t)ret;
assoc_failed:
netdev->result = NETDEV_RESULT_ASSOCIATION_FAILED;
@ -4591,49 +4591,25 @@ static void netdev_ft_response_frame_event(const struct mmpdu_header *hdr,
int rssi, void *user_data)
{
struct netdev *netdev = user_data;
struct netdev_ft_over_ds_info *info;
int ret;
uint16_t status_code = MMPDU_STATUS_CODE_UNSPECIFIED;
const uint8_t *aa;
const uint8_t *spa;
const uint8_t *ies;
size_t ies_len;
struct ft_ds_finder finder;
if (!netdev->connected)
return;
ret = ft_over_ds_parse_action_response(body, body_len, &spa, &aa,
&ies, &ies_len);
if (ret < 0)
__ft_rx_action(netdev->index, (const uint8_t *)hdr,
mmpdu_header_len(hdr) + body_len);
}
static void netdev_ft_auth_response_frame_event(const struct mmpdu_header *hdr,
const void *body, size_t body_len,
int rssi, void *user_data)
{
struct netdev *netdev = user_data;
if (!netdev->connected)
return;
finder.spa = spa;
finder.aa = aa;
info = l_queue_find(netdev->ft_ds_list, match_ft_ds_info, &finder);
if (!info)
return;
/* Lookup successful, now check the status code */
if (ret > 0) {
status_code = (uint16_t)ret;
goto ft_error;
}
if (!ft_over_ds_parse_action_ies(&info->super, netdev->handshake,
ies, ies_len))
goto ft_error;
info->parsed = true;
return;
ft_error:
l_debug("FT-over-DS to "MAC" failed (%d)", MAC_STR(info->super.aa),
status_code);
netdev_ft_over_ds_auth_failed(info, status_code);
__ft_rx_authenticate(netdev->index, (const uint8_t *)hdr,
mmpdu_header_len(hdr) + body_len);
}
static void netdev_qos_map_frame_event(const struct mmpdu_header *hdr,
@ -5859,6 +5835,7 @@ static void netdev_add_station_frame_watches(struct netdev *netdev)
static const uint8_t action_sa_query_resp_prefix[2] = { 0x08, 0x01 };
static const uint8_t action_sa_query_req_prefix[2] = { 0x08, 0x00 };
static const uint8_t action_ft_response_prefix[] = { 0x06, 0x02 };
static const uint8_t auth_ft_response_prefix[] = { 0x02, 0x00 };
static const uint8_t action_qos_map_prefix[] = { 0x01, 0x04 };
uint64_t wdev = netdev->wdev_id;
@ -5879,6 +5856,10 @@ static void netdev_add_station_frame_watches(struct netdev *netdev)
sizeof(action_ft_response_prefix),
netdev_ft_response_frame_event, netdev, NULL);
frame_watch_add(wdev, 0, 0x00b0, auth_ft_response_prefix,
sizeof(auth_ft_response_prefix),
netdev_ft_auth_response_frame_event, netdev, NULL);
if (wiphy_supports_qos_set_map(netdev->wiphy))
frame_watch_add(wdev, 0, 0x00d0, action_qos_map_prefix,
sizeof(action_qos_map_prefix),