@@ -1878,6 +1878,74 @@ static int wpa_supp_aead_decrypt(struct wpa_sm *sm, u8 *buf, size_t buf_len,
}
#endif /* CONFIG_FILS */
+#ifdef CONFIG_TESTING_OPTIONS
+/* Mostly same as below, but this should not change any state. Returns the
+ * message type so we can make decisions before feeding this into the state
+ * machine.
+ */
+enum eapol_key_msg_type wpa_eapol_key_type(struct wpa_sm *sm, const u8 *buf, size_t len)
+{
+ size_t plen;
+ const struct ieee802_1x_hdr *hdr;
+ struct wpa_eapol_key *key;
+ u16 key_info;
+ enum eapol_key_msg_type ret = EAPOL_MSG_TYPE_UNKNOWN;
+ size_t mic_len, keyhdrlen;
+
+ mic_len = wpa_mic_len(sm->key_mgmt);
+ keyhdrlen = sizeof(*key) + mic_len + 2;
+
+ if (len < sizeof(*hdr) + keyhdrlen) {
+ return ret;
+ }
+
+ hdr = (const struct ieee802_1x_hdr *) buf;
+ plen = be_to_host16(hdr->length);
+
+ if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
+ goto out;
+ }
+ if (plen > len - sizeof(*hdr) || plen < keyhdrlen) {
+ goto out;
+ }
+
+ key = (struct wpa_eapol_key *) (buf + sizeof(struct ieee802_1x_hdr));
+
+ if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
+ {
+ goto out;
+ }
+
+ key_info = WPA_GET_BE16(key->key_info);
+
+ if (key_info & WPA_KEY_INFO_KEY_TYPE) {
+ if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
+ goto out;
+ }
+
+ if (key_info & (WPA_KEY_INFO_MIC |
+ WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ /* 3/4 4-Way Handshake */
+ ret = EAPOL_MSG_TYPE_3_OF_4;
+ goto out;
+ } else {
+ /* 1/4 4-Way Handshake */
+ ret = EAPOL_MSG_TYPE_1_OF_4;
+ goto out;
+ }
+ } else {
+ if ((mic_len && (key_info & WPA_KEY_INFO_MIC)) ||
+ (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA))) {
+ /* 1/2 Group Key Handshake */
+ ret = EAPOL_MSG_TYPE_GROUP_1_OF_2;
+ goto out;
+ }
+ }
+
+out:
+ return ret;
+}
+#endif
/**
* wpa_sm_rx_eapol - Process received WPA EAPOL frames
@@ -109,8 +109,24 @@ struct rsn_supp_config {
int wpa_rsc_relaxation;
};
+enum eapol_key_msg_type {
+ EAPOL_MSG_TYPE_UNKNOWN,
+ EAPOL_MSG_TYPE_1_OF_4, /* rx by sta */
+ EAPOL_MSG_TYPE_2_OF_4, /* sent by sta */
+ EAPOL_MSG_TYPE_3_OF_4, /* rx by sta */
+ EAPOL_MSG_TYPE_4_OF_4, /* sent by sta */
+ EAPOL_MSG_TYPE_GROUP_1_OF_2, /* rx by sta */
+ EAPOL_MSG_TYPE_GROUP_2_OF_2, /* sent by sta */
+};
+
+
#ifndef CONFIG_NO_WPA
+#ifdef CONFIG_TESTING_OPTIONS
+enum eapol_key_msg_type wpa_eapol_key_type(struct wpa_sm *sm, const u8 *buf, size_t len);
+#endif
+
+
struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx);
void wpa_sm_deinit(struct wpa_sm *sm);
void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid);
@@ -169,6 +185,13 @@ void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
#else /* CONFIG_NO_WPA */
+#ifdef CONFIG_TESTING_OPTIONS
+enum eapol_key_msg_type wpa_eapol_key_type(struct wpa_sm *sm, const u8 *src_addr,
+ const u8 *buf, size_t len) {
+ return EAPOL_MSG_TYPE_UNKNOWN;
+}
+#endif
+
static inline struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
{
return (struct wpa_sm *) 1;
@@ -3833,6 +3833,11 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
config->accept_external_scan_results = DEFAULT_ACCEPT_EXTERNAL_SCAN_RESULTS;
#if CONFIG_TESTING_OPTIONS
config->ignore_auth_resp = DEFAULT_IGNORE_AUTH_RESP;
+ config->ignore_assoc = DEFAULT_IGNORE_AUTH_RESP;
+ config->ignore_deauth = DEFAULT_IGNORE_AUTH_RESP;
+ config->ignore_eapol_1_of_4 = DEFAULT_IGNORE_AUTH_RESP;
+ config->ignore_eapol_3_of_4 = DEFAULT_IGNORE_AUTH_RESP;
+ config->ignore_eapol_1_of_2 = DEFAULT_IGNORE_AUTH_RESP;
#endif
return config;
@@ -4553,6 +4558,11 @@ static const struct global_parse_data global_fields[] = {
{ INT(concurrent_assoc_ok), 0 },
#if CONFIG_TESTING_OPTIONS
{ INT(ignore_auth_resp), 0 },
+ { INT(ignore_assoc), 0 },
+ { INT(ignore_deauth), 0 },
+ { INT(ignore_eapol_1_of_4), 0 },
+ { INT(ignore_eapol_3_of_4), 0 },
+ { INT(ignore_eapol_1_of_2), 0 },
#endif
{ INT(accept_external_scan_results), 0 },
{ STR(wowlan_triggers), 0 },
@@ -886,6 +886,11 @@ struct wpa_config {
* 0 == never, 65535 == always
*/
unsigned short ignore_auth_resp;
+ unsigned short ignore_assoc;
+ unsigned short ignore_deauth;
+ unsigned short ignore_eapol_1_of_4;
+ unsigned short ignore_eapol_3_of_4;
+ unsigned short ignore_eapol_1_of_2;
#endif
/**
@@ -3725,10 +3725,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
case EVENT_ASSOC:
#ifdef CONFIG_TESTING_OPTIONS
- if (wpa_s->conf->ignore_auth_resp &&
- (os_random_16() < wpa_s->conf->ignore_auth_resp)) {
+ if ((wpa_s->conf->ignore_auth_resp &&
+ (os_random_16() < wpa_s->conf->ignore_auth_resp)) ||
+ (wpa_s->conf->ignore_assoc &&
+ (os_random_16() < wpa_s->conf->ignore_assoc))) {
wpa_dbg(wpa_s, MSG_INFO,
- "EVENT_ASSOC - ignore_auth_resp active!");
+ "EVENT_ASSOC - ignore_assoc active!");
break;
}
#endif /* CONFIG_TESTING_OPTIONS */
@@ -3747,10 +3749,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
case EVENT_DEAUTH:
#ifdef CONFIG_TESTING_OPTIONS
- if (wpa_s->conf->ignore_auth_resp &&
- (os_random_16() < wpa_s->conf->ignore_auth_resp)) {
+ if ((wpa_s->conf->ignore_auth_resp &&
+ (os_random_16() < wpa_s->conf->ignore_auth_resp)) ||
+ (wpa_s->conf->ignore_deauth &&
+ (os_random_16() < wpa_s->conf->ignore_deauth))) {
wpa_dbg(wpa_s, MSG_INFO,
- "EVENT_DEAUTH - ignore_auth_resp active!");
+ "EVENT_DEAUTH - ignore_deauth active!");
break;
}
#endif /* CONFIG_TESTING_OPTIONS */
@@ -3502,6 +3502,9 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
+#ifdef CONFIG_TESTING_OPTIONS
+ enum eapol_key_msg_type emt;
+#endif
wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
@@ -3512,6 +3515,31 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
wpa_dbg(wpa_s, MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
return;
}
+
+
+ /* Check for dropping specific eapol frames */
+ emt = wpa_eapol_key_type(wpa_s->wpa, buf, len);
+ if (emt == EAPOL_MSG_TYPE_1_OF_4) {
+ if (wpa_s->conf->ignore_eapol_1_of_4 &&
+ (os_random_16() < wpa_s->conf->ignore_eapol_1_of_4)) {
+ wpa_dbg(wpa_s, MSG_INFO, "RX EAPOL - ignore_eapol_1_of_4 active!");
+ return;
+ }
+ }
+ else if (emt == EAPOL_MSG_TYPE_3_OF_4) {
+ if (wpa_s->conf->ignore_eapol_3_of_4 &&
+ (os_random_16() < wpa_s->conf->ignore_eapol_3_of_4)) {
+ wpa_dbg(wpa_s, MSG_INFO, "RX EAPOL - ignore_eapol_3_of_4 active!");
+ return;
+ }
+ }
+ else if (emt == EAPOL_MSG_TYPE_GROUP_1_OF_2) {
+ if (wpa_s->conf->ignore_eapol_1_of_2 &&
+ (os_random_16() < wpa_s->conf->ignore_eapol_1_of_2)) {
+ wpa_dbg(wpa_s, MSG_INFO, "RX EAPOL - ignore_eapol_1_of_2 active!");
+ return;
+ }
+ }
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_PEERKEY
@@ -1367,9 +1367,18 @@ fast_reauth=1
# Testing logic, not for use in production systems.
# Value is 0-65535, where 0 means never ignore, 65535 means always
# ignore, and the range between is a percentage chance.
+# This matches all eapol messages, AUTH, and DEAUTH messages.
# You must enable CONFIG_TESTING_OPTIONS when compiling to enable this.
#ignore_auth_resp=1000
+# More specific ways to ignore certain frame types. Same range as
+# ignore_auth_resp
+#ignore_assoc=1000
+#ignore_deauth=1000
+#ignore_eapol_1_of_4=1000
+#ignore_eapol_3_of_4=1000
+#ignore_eapol_1_of_2=1000
+
# Example blocks: