diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 6e7d11bcd..81c4c2709 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -138,6 +138,7 @@ extern "C" { #define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED " #define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT " #define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED " +#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id=" /* parameters: */ #define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT " diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e9399fef5..69e40302c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2017,6 +2017,8 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) { wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - " "pre-shared key may be incorrect"); + if (wpas_p2p_4way_hs_failed(wpa_s) > 0) + return; /* P2P group removed */ wpas_auth_failed(wpa_s); } if (!wpa_s->disconnected && diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 62d3b64e4..c0e8651c0 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -82,7 +82,8 @@ enum p2p_group_removal_reason { P2P_GROUP_REMOVAL_REQUESTED, P2P_GROUP_REMOVAL_IDLE_TIMEOUT, P2P_GROUP_REMOVAL_UNAVAILABLE, - P2P_GROUP_REMOVAL_GO_ENDING_SESSION + P2P_GROUP_REMOVAL_GO_ENDING_SESSION, + P2P_GROUP_REMOVAL_PSK_FAILURE }; @@ -391,6 +392,9 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, case P2P_GROUP_REMOVAL_GO_ENDING_SESSION: reason = " reason=GO_ENDING_SESSION"; break; + case P2P_GROUP_REMOVAL_PSK_FAILURE: + reason = " reason=PSK_FAILURE"; + break; default: reason = ""; break; @@ -4519,6 +4523,7 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s, wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 0); if (wpa_s == NULL) return -1; + wpa_s->p2p_last_4way_hs_fail = NULL; wpa_supplicant_ap_deinit(wpa_s); @@ -6248,3 +6253,45 @@ void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer, for (w = wpa_s->global->ifaces; w; w = w->next) wpas_p2p_remove_client_go(w, peer, iface_addr); } + + +int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid = wpa_s->current_ssid; + + if (ssid == NULL || !ssid->p2p_group) + return 0; + + if (wpa_s->p2p_last_4way_hs_fail && + wpa_s->p2p_last_4way_hs_fail == ssid) { + u8 go_dev_addr[ETH_ALEN]; + struct wpa_ssid *persistent; + + if (wpas_p2p_persistent_group(wpa_s, go_dev_addr, + ssid->ssid, + ssid->ssid_len) <= 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not determine whether 4-way handshake failures were for a persistent group"); + goto disconnect; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr=" + MACSTR, MAC2STR(go_dev_addr)); + persistent = wpas_p2p_get_persistent(wpa_s->parent, go_dev_addr, + ssid->ssid, + ssid->ssid_len); + if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored"); + goto disconnect; + } + wpa_msg_global(wpa_s->parent, MSG_INFO, + P2P_EVENT_PERSISTENT_PSK_FAIL "%d", + persistent->id); + disconnect: + wpa_s->p2p_last_4way_hs_fail = NULL; + wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_PSK_FAILURE); + return 1; + } + + wpa_s->p2p_last_4way_hs_fail = ssid; + return 0; +} diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 5c39a17b6..c718fba88 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -160,10 +160,16 @@ void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer, #ifdef CONFIG_P2P void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s); +int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s); #else /* CONFIG_P2P */ static inline void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s) { } + +static inline int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s) +{ + return 0; +} #endif /* CONFIG_P2P */ #endif /* P2P_SUPPLICANT_H */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index ac22c3195..d69cd61c9 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -652,6 +652,7 @@ struct wpa_supplicant { int p2p_go_intent; int p2p_connect_freq; struct os_time p2p_auto_started; + struct wpa_ssid *p2p_last_4way_hs_fail; #endif /* CONFIG_P2P */ struct wpa_ssid *bgscan_ssid;