diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index c6f620573..3222d771b 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -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 */ diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 817012e38..dc106e703 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -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); diff --git a/src/wps/wps.h b/src/wps/wps.h index 4986881b0..389be3eee 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -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 }; /** diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 9aef10f57..60d5b7e70 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -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; } diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index fcf6c3d02..69acd58fc 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -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; } }