diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 4032db895..b093f2805 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -62,6 +62,8 @@ extern "C" { #define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " /** M2D received */ #define WPS_EVENT_M2D "WPS-M2D " +/** WPS registration failed after M2/M2D */ +#define WPS_EVENT_FAIL "WPS-FAIL " /* hostapd control interface - fixed message prefixes */ #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " diff --git a/src/wps/wps.h b/src/wps/wps.h index e1026b6fa..d61db68e1 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -96,7 +96,8 @@ struct wps_registrar_config { enum wps_event { - WPS_EV_M2D + WPS_EV_M2D, + WPS_EV_FAIL }; union wps_event_data { @@ -116,6 +117,9 @@ union wps_event_data { u16 config_error; u16 dev_password_id; } m2d; + struct wps_event_fail { + int msg; /* enum wps_msg_type */ + } fail; }; /** diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c index 7ac3c03e9..99f6eb9ad 100644 --- a/src/wps/wps_common.c +++ b/src/wps/wps_common.c @@ -298,3 +298,16 @@ unsigned int wps_generate_pin(void) /* Append checksum digit */ return val * 10 + wps_pin_checksum(val); } + + +void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg) +{ + union wps_event_data data; + + if (wps->event_cb == NULL) + return; + + os_memset(&data, 0, sizeof(data)); + data.fail.msg = msg; + wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); +} diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 7fd1b35f7..18967cd37 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -947,12 +947,18 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, break; case WPS_M4: ret = wps_process_m4(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M4); break; case WPS_M6: ret = wps_process_m6(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M6); break; case WPS_M8: ret = wps_process_m8(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M8); break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", @@ -1079,6 +1085,24 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with " "Configuration Error %d", WPA_GET_BE16(attr.config_error)); + switch (wps->state) { + case RECV_M4: + wps_fail_event(wps->wps, WPS_M3); + break; + case RECV_M6: + wps_fail_event(wps->wps, WPS_M5); + break; + case RECV_M8: + wps_fail_event(wps->wps, WPS_M7); + break; + default: + break; + } + + /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if + * Enrollee is Authenticator */ + wps->state = SEND_WSC_NACK; + return WPS_FAILURE; } diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index b661b5d13..3ae53b8ea 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -165,6 +165,7 @@ void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, size_t dev_passwd_len); struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, size_t encr_len); +void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg); /* wps_attr_parse.c */ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index b7a38c2be..cd53c74de 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1824,12 +1824,18 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, break; case WPS_M3: ret = wps_process_m3(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M3); break; case WPS_M5: ret = wps_process_m5(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M5); break; case WPS_M7: ret = wps_process_m7(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M7); break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", @@ -1904,9 +1910,11 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; + int old_state; wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); + old_state = wps->state; wps->state = SEND_WSC_NACK; if (wps_parse_msg(msg, &attr) < 0) @@ -1951,6 +1959,23 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with " "Configuration Error %d", WPA_GET_BE16(attr.config_error)); + switch (old_state) { + case RECV_M3: + wps_fail_event(wps->wps, WPS_M2); + break; + case RECV_M5: + wps_fail_event(wps->wps, WPS_M4); + break; + case RECV_M7: + wps_fail_event(wps->wps, WPS_M6); + break; + case RECV_DONE: + wps_fail_event(wps->wps, WPS_M8); + break; + default: + break; + } + return WPS_FAILURE; } @@ -2060,6 +2085,7 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, u8 op_code, const struct wpabuf *msg) { + enum wps_process_res ret; wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " "op_code=%d)", @@ -2073,7 +2099,12 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, case WSC_NACK: return wps_process_wsc_nack(wps, msg); case WSC_Done: - return wps_process_wsc_done(wps, msg); + ret = wps_process_wsc_done(wps, msg); + if (ret == WPS_FAILURE) { + wps->state = SEND_WSC_NACK; + wps_fail_event(wps->wps, WPS_WSC_DONE); + } + return ret; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); return WPS_FAILURE; diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp index edf88ea0a..dc555ab83 100644 --- a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp +++ b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp @@ -804,6 +804,8 @@ void WpaGui::processMsg(char *msg) wpsStatusText->setText("Registration started"); } else if (str_match(pos, WPS_EVENT_M2D)) { wpsStatusText->setText("Registrar does not yet know PIN"); + } else if (str_match(pos, WPS_EVENT_FAIL)) { + wpsStatusText->setText("Registration failed"); } } diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 5f3b29d5b..1babe86ef 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -29,6 +29,7 @@ static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx); +static void wpas_clear_wps(struct wpa_supplicant *wpa_s); int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) @@ -189,6 +190,14 @@ static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s, } +static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s, + struct wps_event_fail *fail) +{ + wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL "msg=%d", fail->msg); + wpas_clear_wps(wpa_s); +} + + static void wpa_supplicant_wps_event(void *ctx, enum wps_event event, union wps_event_data *data) { @@ -197,6 +206,9 @@ static void wpa_supplicant_wps_event(void *ctx, enum wps_event event, case WPS_EV_M2D: wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d); break; + case WPS_EV_FAIL: + wpa_supplicant_wps_event_fail(wpa_s, &data->fail); + break; } }