P2P: Add event messages for possible PSK failures on P2P groups
[mech_eap.git] / wpa_supplicant / events.c
index bd57916..69e4030 100644 (file)
@@ -187,6 +187,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
                eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
        wpa_s->ap_ies_from_associnfo = 0;
        wpa_s->current_ssid = NULL;
+       eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
        wpa_s->key_mgmt = 0;
 }
 
@@ -272,7 +273,7 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 {
 #ifdef IEEE8021X_EAPOL
 #ifdef PCSC_FUNCS
-       int aka = 0, sim = 0, type;
+       int aka = 0, sim = 0;
 
        if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL)
                return 0;
@@ -311,14 +312,9 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 
        wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to use SIM "
                "(sim=%d aka=%d) - initialize PCSC", sim, aka);
-       if (sim && aka)
-               type = SCARD_TRY_BOTH;
-       else if (aka)
-               type = SCARD_USIM_ONLY;
-       else
-               type = SCARD_GSM_SIM_ONLY;
 
-       wpa_s->scard = scard_init(type, NULL);
+       wpa_s->scard = scard_init((!sim && aka) ? SCARD_USIM_ONLY :
+                                 SCARD_TRY_BOTH, NULL);
        if (wpa_s->scard == NULL) {
                wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
                        "(pcsc-lite)");
@@ -334,10 +330,24 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 
 
 #ifndef CONFIG_NO_SCAN_PROCESSING
+
+static int has_wep_key(struct wpa_ssid *ssid)
+{
+       int i;
+
+       for (i = 0; i < NUM_WEP_KEYS; i++) {
+               if (ssid->wep_key_len[i])
+                       return 1;
+       }
+
+       return 0;
+}
+
+
 static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
                                        struct wpa_ssid *ssid)
 {
-       int i, privacy = 0;
+       int privacy = 0;
 
        if (ssid->mixed_cell)
                return 1;
@@ -347,12 +357,9 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
                return 1;
 #endif /* CONFIG_WPS */
 
-       for (i = 0; i < NUM_WEP_KEYS; i++) {
-               if (ssid->wep_key_len[i]) {
-                       privacy = 1;
-                       break;
-               }
-       }
+       if (has_wep_key(ssid))
+               privacy = 1;
+
 #ifdef IEEE8021X_EAPOL
        if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
            ssid->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
@@ -818,6 +825,12 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
                        continue;
                }
 
+               if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
+                   has_wep_key(ssid)) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "   skip - ignore WPA/WPA2 AP for WEP network block");
+                       continue;
+               }
+
                if (!wpa_supplicant_match_privacy(bss, ssid)) {
                        wpa_dbg(wpa_s, MSG_DEBUG, "   skip - privacy "
                                "mismatch");
@@ -2004,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 &&
@@ -2430,12 +2445,141 @@ static void wpa_supplicant_event_unprot_disassoc(struct wpa_supplicant *wpa_s,
 }
 
 
+static void wpas_event_disconnect(struct wpa_supplicant *wpa_s, const u8 *addr,
+                                 u16 reason_code, int locally_generated,
+                                 const u8 *ie, size_t ie_len, int deauth)
+{
+#ifdef CONFIG_AP
+       if (wpa_s->ap_iface && addr) {
+               hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], addr);
+               return;
+       }
+
+       if (wpa_s->ap_iface) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Ignore deauth event in AP mode");
+               return;
+       }
+#endif /* CONFIG_AP */
+
+       wpa_supplicant_event_disassoc(wpa_s, reason_code, locally_generated);
+
+       if (reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
+           ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
+             (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
+            eapol_sm_failed(wpa_s->eapol)))
+               wpas_auth_failed(wpa_s);
+
+#ifdef CONFIG_P2P
+       if (deauth && reason_code > 0) {
+               if (wpas_p2p_deauth_notif(wpa_s, addr, reason_code, ie, ie_len,
+                                         locally_generated) > 0) {
+                       /*
+                        * The interface was removed, so cannot continue
+                        * processing any additional operations after this.
+                        */
+                       return;
+               }
+       }
+#endif /* CONFIG_P2P */
+
+       wpa_supplicant_event_disassoc_finish(wpa_s, reason_code,
+                                            locally_generated);
+}
+
+
+static void wpas_event_disassoc(struct wpa_supplicant *wpa_s,
+                               struct disassoc_info *info)
+{
+       u16 reason_code = 0;
+       int locally_generated = 0;
+       const u8 *addr = NULL;
+       const u8 *ie = NULL;
+       size_t ie_len = 0;
+
+       wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification");
+
+       if (info) {
+               addr = info->addr;
+               ie = info->ie;
+               ie_len = info->ie_len;
+               reason_code = info->reason_code;
+               locally_generated = info->locally_generated;
+               wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", reason_code,
+                       locally_generated ? " (locally generated)" : "");
+               if (addr)
+                       wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR,
+                               MAC2STR(addr));
+               wpa_hexdump(MSG_DEBUG, "Disassociation frame IE(s)",
+                           ie, ie_len);
+       }
+
+#ifdef CONFIG_AP
+       if (wpa_s->ap_iface && info && info->addr) {
+               hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], info->addr);
+               return;
+       }
+
+       if (wpa_s->ap_iface) {
+               wpa_dbg(wpa_s, MSG_DEBUG, "Ignore disassoc event in AP mode");
+               return;
+       }
+#endif /* CONFIG_AP */
+
+#ifdef CONFIG_P2P
+       if (info) {
+               wpas_p2p_disassoc_notif(
+                       wpa_s, info->addr, reason_code, info->ie, info->ie_len,
+                       locally_generated);
+       }
+#endif /* CONFIG_P2P */
+
+       if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
+               sme_event_disassoc(wpa_s, info);
+
+       wpas_event_disconnect(wpa_s, addr, reason_code, locally_generated,
+                             ie, ie_len, 0);
+}
+
+
+static void wpas_event_deauth(struct wpa_supplicant *wpa_s,
+                             struct deauth_info *info)
+{
+       u16 reason_code = 0;
+       int locally_generated = 0;
+       const u8 *addr = NULL;
+       const u8 *ie = NULL;
+       size_t ie_len = 0;
+
+       wpa_dbg(wpa_s, MSG_DEBUG, "Deauthentication notification");
+
+       if (info) {
+               addr = info->addr;
+               ie = info->ie;
+               ie_len = info->ie_len;
+               reason_code = info->reason_code;
+               locally_generated = info->locally_generated;
+               wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s",
+                       reason_code,
+                       locally_generated ? " (locally generated)" : "");
+               if (addr) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR,
+                               MAC2STR(addr));
+               }
+               wpa_hexdump(MSG_DEBUG, "Deauthentication frame IE(s)",
+                           ie, ie_len);
+       }
+
+       wpa_reset_ft_completed(wpa_s->wpa);
+
+       wpas_event_disconnect(wpa_s, addr, reason_code,
+                             locally_generated, ie, ie_len, 1);
+}
+
+
 void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                          union wpa_event_data *data)
 {
        struct wpa_supplicant *wpa_s = ctx;
-       u16 reason_code = 0;
-       int locally_generated = 0;
 
        if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
            event != EVENT_INTERFACE_ENABLED &&
@@ -2474,109 +2618,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                wpa_supplicant_event_assoc(wpa_s, data);
                break;
        case EVENT_DISASSOC:
-               wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification");
-               if (data) {
-                       wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s",
-                               data->disassoc_info.reason_code,
-                               data->disassoc_info.locally_generated ?
-                               " (locally generated)" : "");
-                       if (data->disassoc_info.addr)
-                               wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR,
-                                       MAC2STR(data->disassoc_info.addr));
-               }
-#ifdef CONFIG_AP
-               if (wpa_s->ap_iface && data && data->disassoc_info.addr) {
-                       hostapd_notif_disassoc(wpa_s->ap_iface->bss[0],
-                                              data->disassoc_info.addr);
-                       break;
-               }
-               if (wpa_s->ap_iface) {
-                       wpa_dbg(wpa_s, MSG_DEBUG, "Ignore disassoc event in "
-                               "AP mode");
-                       break;
-               }
-#endif /* CONFIG_AP */
-               if (data) {
-                       reason_code = data->disassoc_info.reason_code;
-                       locally_generated =
-                               data->disassoc_info.locally_generated;
-                       wpa_hexdump(MSG_DEBUG, "Disassociation frame IE(s)",
-                                   data->disassoc_info.ie,
-                                   data->disassoc_info.ie_len);
-#ifdef CONFIG_P2P
-                       wpas_p2p_disassoc_notif(
-                               wpa_s, data->disassoc_info.addr, reason_code,
-                               data->disassoc_info.ie,
-                               data->disassoc_info.ie_len,
-                               locally_generated);
-#endif /* CONFIG_P2P */
-               }
-               if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
-                       sme_event_disassoc(wpa_s, data);
-               /* fall through */
+               wpas_event_disassoc(wpa_s,
+                                   data ? &data->disassoc_info : NULL);
+               break;
        case EVENT_DEAUTH:
-               if (event == EVENT_DEAUTH) {
-                       wpa_dbg(wpa_s, MSG_DEBUG,
-                               "Deauthentication notification");
-                       if (data) {
-                               reason_code = data->deauth_info.reason_code;
-                               locally_generated =
-                                       data->deauth_info.locally_generated;
-                               wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s",
-                                       data->deauth_info.reason_code,
-                                       data->deauth_info.locally_generated ?
-                                       " (locally generated)" : "");
-                               if (data->deauth_info.addr) {
-                                       wpa_dbg(wpa_s, MSG_DEBUG, " * address "
-                                               MACSTR,
-                                               MAC2STR(data->deauth_info.
-                                                       addr));
-                               }
-                               wpa_hexdump(MSG_DEBUG,
-                                           "Deauthentication frame IE(s)",
-                                           data->deauth_info.ie,
-                                           data->deauth_info.ie_len);
-                       }
-                       wpa_reset_ft_completed(wpa_s->wpa);
-               }
-#ifdef CONFIG_AP
-               if (wpa_s->ap_iface && data && data->deauth_info.addr) {
-                       hostapd_notif_disassoc(wpa_s->ap_iface->bss[0],
-                                              data->deauth_info.addr);
-                       break;
-               }
-               if (wpa_s->ap_iface) {
-                       wpa_dbg(wpa_s, MSG_DEBUG, "Ignore deauth event in "
-                               "AP mode");
-                       break;
-               }
-#endif /* CONFIG_AP */
-               wpa_supplicant_event_disassoc(wpa_s, reason_code,
-                                             locally_generated);
-               if (reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
-                   ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
-                     (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
-                    eapol_sm_failed(wpa_s->eapol)))
-                       wpas_auth_failed(wpa_s);
-#ifdef CONFIG_P2P
-               if (event == EVENT_DEAUTH && data) {
-                       if (wpas_p2p_deauth_notif(wpa_s,
-                                                 data->deauth_info.addr,
-                                                 reason_code,
-                                                 data->deauth_info.ie,
-                                                 data->deauth_info.ie_len,
-                                                 locally_generated) > 0) {
-                               /*
-                                * The interface was removed, so cannot
-                                * continue processing any additional
-                                * operations after this.
-                                */
-                               break;
-                       }
-               }
-#endif /* CONFIG_P2P */
-               wpa_supplicant_event_disassoc_finish(wpa_s, reason_code,
-                                                    locally_generated);
+               wpas_event_deauth(wpa_s,
+                                 data ? &data->deauth_info : NULL);
                break;
        case EVENT_MICHAEL_MIC_FAILURE:
                wpa_supplicant_event_michael_mic_failure(wpa_s, data);