aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/wpa_ctrl.h2
-rw-r--r--src/wps/wps.h6
-rw-r--r--src/wps/wps_common.c13
-rw-r--r--src/wps/wps_enrollee.c24
-rw-r--r--src/wps/wps_i.h1
-rw-r--r--src/wps/wps_registrar.c33
6 files changed, 77 insertions, 2 deletions
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 4032db8..b093f28 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 e1026b6..d61db68 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 7ac3c03..99f6eb9 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 7fd1b35..18967cd 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 b661b5d..3ae53b8 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 b7a38c2..cd53c74 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;