WPS: Disable AP PIN after 10 consecutive failures

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>
This commit is contained in:
Jouni Malinen 2012-01-30 17:31:06 +02:00 committed by Jouni Malinen
parent 80e8a5eef1
commit 32cdcf15b2
5 changed files with 55 additions and 4 deletions

View file

@ -125,6 +125,7 @@ struct hostapd_data {
struct wpabuf *wps_probe_resp_ie; struct wpabuf *wps_probe_resp_ie;
#ifdef CONFIG_WPS #ifdef CONFIG_WPS
unsigned int ap_pin_failures; unsigned int ap_pin_failures;
unsigned int ap_pin_failures_consecutive;
struct upnp_wps_device_sm *wps_upnp; struct upnp_wps_device_sm *wps_upnp;
unsigned int ap_pin_lockout_time; unsigned int ap_pin_lockout_time;
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */

View file

@ -512,6 +512,8 @@ static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
if (hapd->conf->ap_setup_locked) if (hapd->conf->ap_setup_locked)
return; return;
if (hapd->ap_pin_failures_consecutive >= 10)
return;
wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN"); wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN");
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); 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. * force attacks.
*/ */
hapd->ap_pin_failures++; hapd->ap_pin_failures++;
wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", hapd->ap_pin_failures_consecutive++;
hapd->ap_pin_failures); 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) if (hapd->ap_pin_failures < 3)
return 0; 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); 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) if (hapd->ap_pin_lockout_time == 0)
hapd->ap_pin_lockout_time = 60; hapd->ap_pin_lockout_time = 60;
else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 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] = { static const char * wps_event_fail_reason[NUM_WPS_EI_VALUES] = {
"No Error", /* WPS_EI_NO_ERROR */ "No Error", /* WPS_EI_NO_ERROR */
"TKIP Only Prohibited", /* WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED */ "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; break;
case WPS_EV_ER_SET_SELECTED_REGISTRAR: case WPS_EV_ER_SET_SELECTED_REGISTRAR:
break; break;
case WPS_EV_AP_PIN_SUCCESS:
hostapd_wps_ap_pin_success(hapd);
break;
} }
if (hapd->wps_event_cb) if (hapd->wps_event_cb)
hapd->wps_event_cb(hapd->wps_event_cb_ctx, event, data); 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); wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout);
hapd->ap_pin_failures = 0; hapd->ap_pin_failures = 0;
hapd->ap_pin_failures_consecutive = 0;
hapd->conf->ap_setup_locked = 0; hapd->conf->ap_setup_locked = 0;
if (hapd->wps->ap_setup_locked) { if (hapd->wps->ap_setup_locked) {
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED);

View file

@ -457,7 +457,12 @@ enum wps_event {
/** /**
* WPS_EV_ER_SET_SELECTED_REGISTRAR - ER: SetSelectedRegistrar 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
}; };
/** /**

View file

@ -1064,6 +1064,10 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
} }
wpabuf_free(decrypted); 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; wps->state = SEND_M7;
return WPS_CONTINUE; return WPS_CONTINUE;
} }

View 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, wpa_supplicant_wps_event_er_set_sel_reg(wpa_s,
&data->set_sel_reg); &data->set_sel_reg);
break; break;
case WPS_EV_AP_PIN_SUCCESS:
break;
} }
} }