From 0e794989e56959e37039cedb23b1e100fe2bca1f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 16:07:25 +0300 Subject: [PATCH] Beacon frame protection event for incorrect protection Define a driver interface event for Beacon frame protection failures. Report such events over the control interface and send a WNM-Notification Request frame to the AP as well. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_defs.h | 7 +++++++ src/common/wpa_ctrl.h | 2 ++ src/drivers/driver.h | 16 ++++++++++++++++ src/drivers/driver_common.c | 1 + wpa_supplicant/events.c | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 8dc469881..7f31e09a1 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1881,6 +1881,13 @@ enum wnm_sleep_mode_subelement_id { WNM_SLEEP_SUBELEM_BIGTK = 2, }; +/* WNM notification type (IEEE P802.11-REVmd/D3.0, Table 9-430) */ +enum wnm_notification_Type { + WNM_NOTIF_TYPE_FIRMWARE_UPDATE = 0, + WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE = 2, + WNM_NOTIF_TYPE_VENDOR_SPECIFIC = 221, +}; + /* Channel Switch modes (802.11h) */ #define CHAN_SWITCH_MODE_ALLOW_TX 0 #define CHAN_SWITCH_MODE_BLOCK_TX 1 diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 0b0413068..ca1c35f85 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -95,6 +95,8 @@ extern "C" { /** SAE authentication failed due to unknown password identifier */ #define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \ "CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER " +/** Unprotected Beacon frame dropped */ +#define WPA_EVENT_UNPROT_BEACON "CTRL-EVENT-UNPROT-BEACON " /** IP subnet status change notification * diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 6ffa7fece..032bbd892 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4970,6 +4970,15 @@ enum wpa_event_type { * EVENT_UPDATE_DH - Notification of updated DH information */ EVENT_UPDATE_DH, + + /** + * EVENT_UNPROT_BEACON - Unprotected Beacon frame received + * + * This event should be called when a Beacon frame is dropped due to it + * not being protected correctly. union wpa_event_data::unprot_beacon + * is required to provide more details of the frame. + */ + EVENT_UNPROT_BEACON, }; @@ -5822,6 +5831,13 @@ union wpa_event_data { const u8 *ie; size_t ie_len; } update_dh; + + /** + * struct unprot_beacon - Data for EVENT_UNPROT_BEACON + */ + struct unprot_beacon { + const u8 *sa; + } unprot_beacon; }; /** diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 2e03b6676..63846db2e 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -89,6 +89,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(INTERFACE_MAC_CHANGED); E2S(WDS_STA_INTERFACE_STATUS); E2S(UPDATE_DH); + E2S(UNPROT_BEACON); } return "UNKNOWN"; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e8b8a9c98..19a883bee 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4467,6 +4467,38 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, } +static void wpas_event_unprot_beacon(struct wpa_supplicant *wpa_s, + struct unprot_beacon *data) +{ + struct wpabuf *buf; + int res; + + if (!data || wpa_s->wpa_state != WPA_COMPLETED || + os_memcmp(data->sa, wpa_s->bssid, ETH_ALEN) != 0) + return; + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_UNPROT_BEACON MACSTR, + MAC2STR(data->sa)); + + buf = wpabuf_alloc(4); + if (!buf) + return; + + wpabuf_put_u8(buf, WLAN_ACTION_WNM); + wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); + wpabuf_put_u8(buf, 1); /* Dialog Token */ + wpabuf_put_u8(buf, WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE); + + res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (res < 0) + wpa_printf(MSG_DEBUG, + "Failed to send WNM-Notification Request frame"); + + wpabuf_free(buf); +} + + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { @@ -5271,6 +5303,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->sta_opmode.rx_nss); #endif /* CONFIG_AP */ break; + case EVENT_UNPROT_BEACON: + wpas_event_unprot_beacon(wpa_s, &data->unprot_beacon); + break; default: wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event); break;