Browse Source

WPS: Added callback for failure-after-M2/M2D

This callback is now used to stop wpa_supplicant from trying to continue
using parameters (most likely, device password) that do not work in a
loop. In addition, wpa_gui can now notify user of failed registration.
Jouni Malinen 16 years ago
parent
commit
469fc3a41f

+ 2 - 0
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 "

+ 5 - 1
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;
 };
 
 /**

+ 13 - 0
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);
+}

+ 24 - 0
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;
 }
 

+ 1 - 0
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);

+ 32 - 1
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;

+ 2 - 0
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");
 	}
 }
 

+ 12 - 0
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;
 	}
 }