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.
This commit is contained in:
Chao-Wen Yang 2011-01-13 17:50:59 +02:00 committed by Jouni Malinen
parent e24cf97c0d
commit c5cf0a18f1
8 changed files with 88 additions and 24 deletions

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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:

View file

@ -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);
}