Browse Source

WPS: Add mechanism for indicating non-standard WPS errors

Previously, only the Configuration Error values were indicated in
WPS-FAIL events. Since those values are defined in the specification
it is not feasible to extend them for indicating other errors. Add
a new error indication value that is internal to wpa_supplicant and
hostapd to allow other errors to be indicated.

Use the new mechanism to indicate if negotiation fails because of
WEP or TKIP-only configurations being disallows by WPS 2.0.
Chao-Wen Yang 14 years ago
parent
commit
c5cf0a18f1

+ 17 - 3
src/ap/wps_hostapd.c

@@ -535,12 +535,26 @@ static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
 }
 
 
+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 */
+	"WEP Prohibited" /* WPS_EI_SECURITY_WEP_PROHIBITED */
+};
+
 static void hostapd_wps_event_fail(struct hostapd_data *hapd,
 				   struct wps_event_fail *fail)
 {
-	wpa_msg(hapd->msg_ctx, MSG_INFO,
-		WPS_EVENT_FAIL "msg=%d config_error=%d",
-		fail->msg, fail->config_error);
+	if (fail->error_indication > 0 &&
+	    fail->error_indication < NUM_WPS_EI_VALUES) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO,
+			WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
+			fail->msg, fail->config_error, fail->error_indication,
+			wps_event_fail_reason[fail->error_indication]);
+	} else {
+		wpa_msg(hapd->msg_ctx, MSG_INFO,
+			WPS_EVENT_FAIL "msg=%d config_error=%d",
+			fail->msg, fail->config_error);
+	}
 }
 
 

+ 1 - 0
src/wps/wps.h

@@ -456,6 +456,7 @@ union wps_event_data {
 	struct wps_event_fail {
 		int msg;
 		u16 config_error;
+		u16 error_indication;
 	} fail;
 
 	struct wps_event_pwd_auth_fail {

+ 2 - 1
src/wps/wps_common.c

@@ -257,7 +257,7 @@ unsigned int wps_generate_pin(void)
 
 
 void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
-		    u16 config_error)
+		    u16 config_error, u16 error_indication)
 {
 	union wps_event_data data;
 
@@ -267,6 +267,7 @@ void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
 	os_memset(&data, 0, sizeof(data));
 	data.fail.msg = msg;
 	data.fail.config_error = config_error;
+	data.fail.error_indication = error_indication;
 	wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data);
 }
 

+ 8 - 0
src/wps/wps_defs.h

@@ -224,6 +224,14 @@ enum wps_config_error {
 	WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18
 };
 
+/* Vendor specific Error Indication for WPS event messages */
+enum wps_error_indication {
+	WPS_EI_NO_ERROR,
+	WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED,
+	WPS_EI_SECURITY_WEP_PROHIBITED,
+	NUM_WPS_EI_VALUES
+};
+
 /* RF Bands */
 #define WPS_RF_24GHZ 0x01
 #define WPS_RF_50GHZ 0x02

+ 16 - 6
src/wps/wps_enrollee.c

@@ -672,6 +672,7 @@ static int wps_process_cred_e(struct wps_data *wps, const u8 *cred,
 		if (wps->cred.encr_type & WPS_ENCR_WEP) {
 			wpa_printf(MSG_INFO, "WPS: Reject Credential "
 				   "due to WEP configuration");
+			wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED;
 			return -2;
 		}
 
@@ -772,6 +773,7 @@ static int wps_process_ap_settings_e(struct wps_data *wps,
 		if (cred.encr_type & WPS_ENCR_WEP) {
 			wpa_printf(MSG_INFO, "WPS: Reject new AP settings "
 				   "due to WEP configuration");
+			wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED;
 			return -1;
 		}
 
@@ -789,6 +791,8 @@ static int wps_process_ap_settings_e(struct wps_data *wps,
 		    WPS_AUTH_WPAPSK) {
 			wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC 2.0 "
 				   "AP Settings: WPA-Personal/TKIP only");
+			wps->error_indication =
+				WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED;
 			return -1;
 		}
 	}
@@ -1140,21 +1144,24 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
 			return WPS_FAILURE;
 		ret = wps_process_m4(wps, msg, &attr);
 		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
-			wps_fail_event(wps->wps, WPS_M4, wps->config_error);
+			wps_fail_event(wps->wps, WPS_M4, wps->config_error,
+				       wps->error_indication);
 		break;
 	case WPS_M6:
 		if (wps_validate_m6(msg) < 0)
 			return WPS_FAILURE;
 		ret = wps_process_m6(wps, msg, &attr);
 		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
-			wps_fail_event(wps->wps, WPS_M6, wps->config_error);
+			wps_fail_event(wps->wps, WPS_M6, wps->config_error,
+				       wps->error_indication);
 		break;
 	case WPS_M8:
 		if (wps_validate_m8(msg) < 0)
 			return WPS_FAILURE;
 		ret = wps_process_m8(wps, msg, &attr);
 		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
-			wps_fail_event(wps->wps, WPS_M8, wps->config_error);
+			wps_fail_event(wps->wps, WPS_M8, wps->config_error,
+				       wps->error_indication);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
@@ -1281,13 +1288,16 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
 
 	switch (wps->state) {
 	case RECV_M4:
-		wps_fail_event(wps->wps, WPS_M3, config_error);
+		wps_fail_event(wps->wps, WPS_M3, config_error,
+			       wps->error_indication);
 		break;
 	case RECV_M6:
-		wps_fail_event(wps->wps, WPS_M5, config_error);
+		wps_fail_event(wps->wps, WPS_M5, config_error,
+			       wps->error_indication);
 		break;
 	case RECV_M8:
-		wps_fail_event(wps->wps, WPS_M7, config_error);
+		wps_fail_event(wps->wps, WPS_M7, config_error,
+			       wps->error_indication);
 		break;
 	default:
 		break;

+ 2 - 1
src/wps/wps_i.h

@@ -102,6 +102,7 @@ struct wps_data {
 	 * config_error - Configuration Error value to be used in NACK
 	 */
 	u16 config_error;
+	u16 error_indication;
 
 	int ext_reg;
 	int int_reg;
@@ -213,7 +214,7 @@ void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
 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,
-		    u16 config_error);
+		    u16 config_error, u16 error_indication);
 void wps_success_event(struct wps_context *wps);
 void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part);
 void wps_pbc_overlap_event(struct wps_context *wps);

+ 16 - 8
src/wps/wps_registrar.c

@@ -2597,21 +2597,24 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
 			return WPS_FAILURE;
 		ret = wps_process_m3(wps, msg, &attr);
 		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
-			wps_fail_event(wps->wps, WPS_M3, wps->config_error);
+			wps_fail_event(wps->wps, WPS_M3, wps->config_error,
+				       wps->error_indication);
 		break;
 	case WPS_M5:
 		if (wps_validate_m5(msg) < 0)
 			return WPS_FAILURE;
 		ret = wps_process_m5(wps, msg, &attr);
 		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
-			wps_fail_event(wps->wps, WPS_M5, wps->config_error);
+			wps_fail_event(wps->wps, WPS_M5, wps->config_error,
+				       wps->error_indication);
 		break;
 	case WPS_M7:
 		if (wps_validate_m7(msg) < 0)
 			return WPS_FAILURE;
 		ret = wps_process_m7(wps, msg, &attr);
 		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
-			wps_fail_event(wps->wps, WPS_M7, wps->config_error);
+			wps_fail_event(wps->wps, WPS_M7, wps->config_error,
+				       wps->error_indication);
 		break;
 	default:
 		wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
@@ -2756,16 +2759,20 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
 
 	switch (old_state) {
 	case RECV_M3:
-		wps_fail_event(wps->wps, WPS_M2, config_error);
+		wps_fail_event(wps->wps, WPS_M2, config_error,
+			       wps->error_indication);
 		break;
 	case RECV_M5:
-		wps_fail_event(wps->wps, WPS_M4, config_error);
+		wps_fail_event(wps->wps, WPS_M4, config_error,
+			       wps->error_indication);
 		break;
 	case RECV_M7:
-		wps_fail_event(wps->wps, WPS_M6, config_error);
+		wps_fail_event(wps->wps, WPS_M6, config_error,
+			       wps->error_indication);
 		break;
 	case RECV_DONE:
-		wps_fail_event(wps->wps, WPS_M8, config_error);
+		wps_fail_event(wps->wps, WPS_M8, config_error,
+			       wps->error_indication);
 		break;
 	default:
 		break;
@@ -2949,7 +2956,8 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
 		if (ret == WPS_FAILURE) {
 			wps->state = SEND_WSC_NACK;
 			wps_fail_event(wps->wps, WPS_WSC_DONE,
-				       wps->config_error);
+				       wps->config_error,
+				       wps->error_indication);
 		}
 		return ret;
 	default:

+ 26 - 5
wpa_supplicant/wps_supplicant.c

@@ -410,15 +410,36 @@ static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
 }
 
 
+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 */
+	"WEP Prohibited" /* WPS_EI_SECURITY_WEP_PROHIBITED */
+};
+
 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 config_error=%d",
-		fail->msg, fail->config_error);
-	if (wpa_s->parent && wpa_s->parent != wpa_s)
-		wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
-			"msg=%d config_error=%d",
+	if (fail->error_indication > 0 &&
+	    fail->error_indication < NUM_WPS_EI_VALUES) {
+		wpa_msg(wpa_s, MSG_INFO,
+			WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
+			fail->msg, fail->config_error, fail->error_indication,
+			wps_event_fail_reason[fail->error_indication]);
+		if (wpa_s->parent && wpa_s->parent != wpa_s)
+			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+				"msg=%d config_error=%d reason=%d (%s)",
+				fail->msg, fail->config_error,
+				fail->error_indication,
+				wps_event_fail_reason[fail->error_indication]);
+	} else {
+		wpa_msg(wpa_s, MSG_INFO,
+			WPS_EVENT_FAIL "msg=%d config_error=%d",
 			fail->msg, fail->config_error);
+		if (wpa_s->parent && wpa_s->parent != wpa_s)
+			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+				"msg=%d config_error=%d",
+				fail->msg, fail->config_error);
+	}
 	wpas_clear_wps(wpa_s);
 	wpas_notify_wps_event_fail(wpa_s, fail);
 }