P2P: Add event messages for possible PSK failures on P2P groups
It is possible for the GO of a persistent group to change the PSK or remove a client when per-client PSKs are used and this can happen without the SSID changing (i.e., the group is still valid, but just not for a specific client). If the client side of such persistent group ends up trying to use an invalidated persistent group information, the connection will fail in 4-way handshake. A new WPS provisioning step is needed to recover from this. Detect this type of case based on two 4-way handshake failures when acting as a P2P client in a persistent group. A new "P2P-PERSISTENT-PSK-FAIL id=<persistent group id>" event is used to indicate when this happens. This makes it easier for upper layers to remove the persistent group information with "REMOVE_NETWORK <persistent group id>" if desired (e.g., based on user confirmation). In addition to indicating the error cases for persistent groups, all this type of PSK failures end up in the client removing the group with the new reason=PSK_FAILURE information in the P2P-GROUP-REMOVED event. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
eac8dab87c
commit
5bf9a6c859
5 changed files with 58 additions and 1 deletions
|
@ -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: <PMF enabled> <timeout in ms> <Session Information URL> */
|
||||
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue