]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Do not disable AP PIN permanently, only slow down attacks
authorJouni Malinen <j@w1.fi>
Tue, 24 Aug 2010 12:24:05 +0000 (15:24 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 24 Aug 2010 12:24:05 +0000 (15:24 +0300)
As a compromise between usability and security, do not disable
AP PIN permanently based on failed PIN validations. Instead, go to
AP Setup Locked state for increasing amount of time between each
failure to slow down brute force attacks against the AP PIN.

This avoids problems with some external Registrars that may try
to use the same PIN multiple times without user input. Now, the
user will still be able to fix the PIN and try again later while
a real attack is delayed enough to make it impractical.

src/ap/hostapd.h
src/ap/wps_hostapd.c
src/common/wpa_ctrl.h

index 5bf4040698a8ef43b210530c4138e7e45602c691..d0d67c8228a495c1114e794167370e825512335f 100644 (file)
@@ -167,6 +167,7 @@ struct hostapd_data {
 #ifdef CONFIG_WPS
        unsigned int ap_pin_failures;
        struct upnp_wps_device_sm *wps_upnp;
+       unsigned int ap_pin_lockout_time;
 #endif /* CONFIG_WPS */
 
        struct hostapd_probereq_cb *probereq_cb;
index c63b7fc89ecb1a7a1dbc016ac8d376e41c4bdc7d..d0e7e0a95045989a7f1b39cff56c18ac35501cc8 100644 (file)
@@ -421,20 +421,36 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
 }
 
 
+static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
+{
+       struct hostapd_data *hapd = eloop_data;
+
+       if (hapd->conf->ap_setup_locked)
+               return;
+
+       wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN");
+       wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);
+       hapd->wps->ap_setup_locked = 0;
+       wps_registrar_update_ie(hapd->wps->registrar);
+
+}
+
+
 static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
                                  struct wps_event_pwd_auth_fail *data)
 {
-       FILE *f;
-
        if (!data->enrollee || hapd->conf->ap_pin == NULL)
                return;
 
        /*
         * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
-        * if this happens multiple times.
+        * for some time if this happens multiple times to slow down brute
+        * force attacks.
         */
        hapd->ap_pin_failures++;
-       if (hapd->ap_pin_failures < 4)
+       wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
+                  hapd->ap_pin_failures);
+       if (hapd->ap_pin_failures < 3)
                return;
 
        wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
@@ -442,23 +458,22 @@ static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
 
        wps_registrar_update_ie(hapd->wps->registrar);
 
-       if (hapd->conf->wps_cred_processing == 1)
-               return;
-
-       f = fopen(hapd->iface->config_fname, "a");
-       if (f == NULL) {
-               wpa_printf(MSG_WARNING, "WPS: Could not append to the current "
-                          "configuration file");
-               return;
+       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 &&
+                        (hapd->ap_pin_failures % 3) == 0)
+                       hapd->ap_pin_lockout_time *= 2;
+
+               wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds",
+                          hapd->ap_pin_lockout_time);
+               eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
+               eloop_register_timeout(hapd->ap_pin_lockout_time, 0,
+                                      hostapd_wps_reenable_ap_pin, hapd,
+                                      NULL);
        }
 
-       fprintf(f, "# WPS AP Setup Locked based on possible attack\n");
-       fprintf(f, "ap_setup_locked=1\n");
-       fclose(f);
-
-       /* TODO: dualband AP may need to update multiple configuration files */
-
-       wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
+       /* TODO: dualband AP may need to update other interfaces */
 }
 
 
@@ -667,6 +682,7 @@ int hostapd_init_wps(struct hostapd_data *hapd,
 
 void hostapd_deinit_wps(struct hostapd_data *hapd)
 {
+       eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
        if (hapd->wps == NULL)
                return;
 #ifdef CONFIG_WPS_UPNP
index ac88e8f6c5b48225d3e5f26c9013a1acf93cf6c0..0c4a965e275af7bb94212cc06c7e8f4c39bd2904 100644 (file)
@@ -93,6 +93,7 @@ extern "C" {
 #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
 #define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS "
 #define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED "
+#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED "
 #define AP_STA_CONNECTED "AP-STA-CONNECTED "
 #define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "