From 8833a7377e4c4bdc35add3231876990079bf016f Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Tue, 27 Sep 2022 12:47:25 -0700 Subject: [PATCH] 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. --- src/netdev.c | 149 ++++++++++++++++++++++----------------------------- 1 file changed, 65 insertions(+), 84 deletions(-) diff --git a/src/netdev.c b/src/netdev.c index dbf51882..029e96ad 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -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),