/*
* EAP-WSC peer for Wi-Fi Protected Setup
- * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2009, 2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
else
len = end - pos;
if ((len & 1) || len > 2 * sizeof(cred->ssid) ||
- hexstr2bin(pos, cred->ssid, len / 2))
+ hexstr2bin(pos, cred->ssid, len / 2)) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_ssid");
return -1;
+ }
cred->ssid_len = len / 2;
pos = os_strstr(params, "new_auth=");
- if (pos == NULL)
+ if (pos == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_auth");
return -1;
+ }
if (os_strncmp(pos + 9, "OPEN", 4) == 0)
cred->auth_type = WPS_AUTH_OPEN;
else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0)
cred->auth_type = WPS_AUTH_WPAPSK;
else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0)
cred->auth_type = WPS_AUTH_WPA2PSK;
- else
+ else {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_auth");
return -1;
+ }
pos = os_strstr(params, "new_encr=");
- if (pos == NULL)
+ if (pos == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_encr");
return -1;
+ }
if (os_strncmp(pos + 9, "NONE", 4) == 0)
cred->encr_type = WPS_ENCR_NONE;
+#ifdef CONFIG_TESTING_OPTIONS
else if (os_strncmp(pos + 9, "WEP", 3) == 0)
cred->encr_type = WPS_ENCR_WEP;
+#endif /* CONFIG_TESTING_OPTIONS */
else if (os_strncmp(pos + 9, "TKIP", 4) == 0)
cred->encr_type = WPS_ENCR_TKIP;
else if (os_strncmp(pos + 9, "CCMP", 4) == 0)
cred->encr_type = WPS_ENCR_AES;
- else
+ else {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_encr");
return -1;
+ }
pos = os_strstr(params, "new_key=");
if (pos == NULL)
else
len = end - pos;
if ((len & 1) || len > 2 * sizeof(cred->key) ||
- hexstr2bin(pos, cred->key, len / 2))
+ hexstr2bin(pos, cred->key, len / 2)) {
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_key");
return -1;
+ }
cred->key_len = len / 2;
return 1;
size_t identity_len;
int registrar;
struct wps_config cfg;
- const char *pos;
+ const char *pos, *end;
const char *phase1;
struct wps_context *wps;
struct wps_credential new_ap_settings;
int res;
+ int nfc = 0;
+ u8 pkhash[WPS_OOB_PUBKEY_HASH_LEN];
wps = sm->wps;
if (wps == NULL) {
while (*pos != '\0' && *pos != ' ')
pos++;
cfg.pin_len = pos - (const char *) cfg.pin;
+ if (cfg.pin_len == 6 &&
+ os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) {
+ cfg.pin = NULL;
+ cfg.pin_len = 0;
+ nfc = 1;
+ }
} else {
pos = os_strstr(phase1, "pbc=1");
if (pos)
cfg.pbc = 1;
}
- if (cfg.pin == NULL && !cfg.pbc) {
+ pos = os_strstr(phase1, "dev_pw_id=");
+ if (pos) {
+ u16 id = atoi(pos + 10);
+ if (id == DEV_PW_NFC_CONNECTION_HANDOVER)
+ nfc = 1;
+ if (cfg.pin || id == DEV_PW_NFC_CONNECTION_HANDOVER)
+ cfg.dev_pw_id = id;
+ }
+
+ if (cfg.pin == NULL && !cfg.pbc && !nfc) {
wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 "
"configuration data");
os_free(data);
return NULL;
}
- pos = os_strstr(phase1, "dev_pw_id=");
- if (pos && cfg.pin)
- cfg.dev_pw_id = atoi(pos + 10);
+ pos = os_strstr(phase1, " pkhash=");
+ if (pos) {
+ size_t len;
+ pos += 8;
+ end = os_strchr(pos, ' ');
+ if (end)
+ len = end - pos;
+ else
+ len = os_strlen(pos);
+ if (len != 2 * WPS_OOB_PUBKEY_HASH_LEN ||
+ hexstr2bin(pos, pkhash, WPS_OOB_PUBKEY_HASH_LEN)) {
+ wpa_printf(MSG_INFO, "EAP-WSC: Invalid pkhash");
+ os_free(data);
+ return NULL;
+ }
+ cfg.peer_pubkey_hash = pkhash;
+ }
res = eap_wsc_new_ap_settings(&new_ap_settings, phase1);
if (res < 0) {
os_free(data);
+ wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to parse new AP "
+ "settings");
return NULL;
}
if (res == 1) {
data->wps = wps_init(&cfg);
if (data->wps == NULL) {
os_free(data);
+ wpa_printf(MSG_DEBUG, "EAP-WSC: wps_init failed");
return NULL;
}
res = eap_get_config_fragment_size(sm);
message_length = WPA_GET_BE16(pos);
pos += 2;
- if (message_length < end - pos) {
+ if (message_length < end - pos || message_length > 50000) {
wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message "
"Length");
ret->ignore = TRUE;
if (data->out_buf == NULL) {
wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to receive "
"message from WPS");
+ eap_wsc_state(data, FAIL);
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
return NULL;
}
data->out_used = 0;