WPS: Disable AP PIN after 10 consecutive failures
authorJouni Malinen <jouni@qca.qualcomm.com>
Mon, 30 Jan 2012 15:31:06 +0000 (17:31 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 30 Jan 2012 15:36:14 +0000 (17:36 +0200)
While the exponential increase in the lockout period provides an
efficient mitigation mechanism against brute force attacks, this
additional trigger to enter indefinite lockout period (cleared by
restarting hostapd) will limit attacks even further by giving maximum of
10 attempts (without authorized user action) even in a very long term
attack.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/ap/hostapd.h
src/ap/wps_hostapd.c
src/wps/wps.h
src/wps/wps_enrollee.c
wpa_supplicant/wps_supplicant.c

index c6f6205..3222d77 100644 (file)
@@ -125,6 +125,7 @@ struct hostapd_data {
        struct wpabuf *wps_probe_resp_ie;
 #ifdef CONFIG_WPS
        unsigned int ap_pin_failures;
+       unsigned int ap_pin_failures_consecutive;
        struct upnp_wps_device_sm *wps_upnp;
        unsigned int ap_pin_lockout_time;
 #endif /* CONFIG_WPS */
index 817012e..dc106e7 100644 (file)
@@ -512,6 +512,8 @@ static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
 
        if (hapd->conf->ap_setup_locked)
                return;
+       if (hapd->ap_pin_failures_consecutive >= 10)
+               return;
 
        wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN");
        wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
@@ -533,8 +535,10 @@ static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
         * force attacks.
         */
        hapd->ap_pin_failures++;
-       wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
-                  hapd->ap_pin_failures);
+       hapd->ap_pin_failures_consecutive++;
+       wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u "
+                  "(%u consecutive)",
+                  hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
        if (hapd->ap_pin_failures < 3)
                return 0;
 
@@ -543,7 +547,15 @@ static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
 
        wps_registrar_update_ie(hapd->wps->registrar);
 
-       if (!hapd->conf->ap_setup_locked) {
+       if (!hapd->conf->ap_setup_locked &&
+           hapd->ap_pin_failures_consecutive >= 10) {
+               /*
+                * In indefinite lockdown - disable automatic AP PIN
+                * reenablement.
+                */
+               eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
+               wpa_printf(MSG_DEBUG, "WPS: AP PIN disabled indefinitely");
+       } else if (!hapd->conf->ap_setup_locked) {
                if (hapd->ap_pin_lockout_time == 0)
                        hapd->ap_pin_lockout_time = 60;
                else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 &&
@@ -569,6 +581,29 @@ static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
 }
 
 
+static int wps_ap_pin_success(struct hostapd_data *hapd, void *ctx)
+{
+       if (hapd->conf->ap_pin == NULL || hapd->wps == NULL)
+               return 0;
+
+       if (hapd->ap_pin_failures_consecutive == 0)
+               return 0;
+
+       wpa_printf(MSG_DEBUG, "WPS: Clear consecutive AP PIN failure counter "
+                  "- total validation failures %u (%u consecutive)",
+                  hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
+       hapd->ap_pin_failures_consecutive = 0;
+
+       return 0;
+}
+
+
+static void hostapd_wps_ap_pin_success(struct hostapd_data *hapd)
+{
+       hostapd_wps_for_each(hapd, wps_ap_pin_success, NULL);
+}
+
+
 static const char * wps_event_fail_reason[NUM_WPS_EI_VALUES] = {
        "No Error", /* WPS_EI_NO_ERROR */
        "TKIP Only Prohibited", /* WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED */
@@ -628,6 +663,9 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
                break;
        case WPS_EV_ER_SET_SELECTED_REGISTRAR:
                break;
+       case WPS_EV_AP_PIN_SUCCESS:
+               hostapd_wps_ap_pin_success(hapd);
+               break;
        }
        if (hapd->wps_event_cb)
                hapd->wps_event_cb(hapd->wps_event_cb_ctx, event, data);
@@ -1293,6 +1331,7 @@ static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout)
 {
        wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
        hapd->ap_pin_failures = 0;
+       hapd->ap_pin_failures_consecutive = 0;
        hapd->conf->ap_setup_locked = 0;
        if (hapd->wps->ap_setup_locked) {
                wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
index 4986881..389be3e 100644 (file)
@@ -457,7 +457,12 @@ enum wps_event {
        /**
         * WPS_EV_ER_SET_SELECTED_REGISTRAR - ER: SetSelectedRegistrar event
         */
-       WPS_EV_ER_SET_SELECTED_REGISTRAR
+       WPS_EV_ER_SET_SELECTED_REGISTRAR,
+
+       /**
+        * WPS_EV_AP_PIN_SUCCESS - External Registrar used correct AP PIN
+        */
+       WPS_EV_AP_PIN_SUCCESS
 };
 
 /**
index 9aef10f..60d5b7e 100644 (file)
@@ -1064,6 +1064,10 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
        }
        wpabuf_free(decrypted);
 
+       if (wps->wps->ap)
+               wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS,
+                                  NULL);
+
        wps->state = SEND_M7;
        return WPS_CONTINUE;
 }
index fcf6c3d..69acd58 100644 (file)
@@ -664,6 +664,8 @@ static void wpa_supplicant_wps_event(void *ctx, enum wps_event event,
                wpa_supplicant_wps_event_er_set_sel_reg(wpa_s,
                                                        &data->set_sel_reg);
                break;
+       case WPS_EV_AP_PIN_SUCCESS:
+               break;
        }
 }