summaryrefslogtreecommitdiffstats
path: root/freebsd/contrib/wpa/src/wps
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/contrib/wpa/src/wps')
-rw-r--r--freebsd/contrib/wpa/src/wps/wps.c6
-rw-r--r--freebsd/contrib/wpa/src/wps/wps.h14
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_build.c31
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_parse.c4
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_attr_process.c10
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_common.c47
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_defs.h4
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_enrollee.c33
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_i.h4
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_registrar.c77
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp.c11
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp.h3
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp_i.h3
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c6
-rw-r--r--freebsd/contrib/wpa/src/wps/wps_upnp_web.c88
15 files changed, 246 insertions, 95 deletions
diff --git a/freebsd/contrib/wpa/src/wps/wps.c b/freebsd/contrib/wpa/src/wps/wps.c
index fb6d8f65..c0caca91 100644
--- a/freebsd/contrib/wpa/src/wps/wps.c
+++ b/freebsd/contrib/wpa/src/wps/wps.c
@@ -21,6 +21,10 @@
int wps_version_number = 0x20;
int wps_testing_dummy_cred = 0;
int wps_corrupt_pkhash = 0;
+int wps_force_auth_types_in_use = 0;
+u16 wps_force_auth_types = 0;
+int wps_force_encr_types_in_use = 0;
+u16 wps_force_encr_types = 0;
#endif /* CONFIG_WPS_TESTING */
@@ -172,7 +176,7 @@ void wps_deinit(struct wps_data *data)
} else if (data->registrar)
wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e);
- wpabuf_free(data->dh_privkey);
+ wpabuf_clear_free(data->dh_privkey);
wpabuf_free(data->dh_pubkey_e);
wpabuf_free(data->dh_pubkey_r);
wpabuf_free(data->last_msg);
diff --git a/freebsd/contrib/wpa/src/wps/wps.h b/freebsd/contrib/wpa/src/wps/wps.h
index 2c91d167..2505d2d9 100644
--- a/freebsd/contrib/wpa/src/wps/wps.h
+++ b/freebsd/contrib/wpa/src/wps/wps.h
@@ -1,6 +1,6 @@
/*
* Wi-Fi Protected Setup
- * Copyright (c) 2007-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -664,6 +664,16 @@ struct wps_context {
u16 encr_types;
/**
+ * encr_types_rsn - Enabled encryption types for RSN (WPS_ENCR_*)
+ */
+ u16 encr_types_rsn;
+
+ /**
+ * encr_types_wpa - Enabled encryption types for WPA (WPS_ENCR_*)
+ */
+ u16 encr_types_wpa;
+
+ /**
* auth_types - Authentication types (bit field of WPS_AUTH_*)
*/
u16 auth_types;
@@ -827,7 +837,7 @@ int wps_build_credential_wrap(struct wpabuf *msg,
unsigned int wps_pin_checksum(unsigned int pin);
unsigned int wps_pin_valid(unsigned int pin);
-unsigned int wps_generate_pin(void);
+int wps_generate_pin(unsigned int *pin);
int wps_pin_str_valid(const char *pin);
void wps_free_pending_msgs(struct upnp_pending_message *msgs);
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_build.c b/freebsd/contrib/wpa/src/wps/wps_attr_build.c
index 742e082c..e7083388 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_build.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_build.c
@@ -2,7 +2,7 @@
/*
* Wi-Fi Protected Setup - attribute building
- * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -22,10 +22,10 @@
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
{
- struct wpabuf *pubkey;
+ struct wpabuf *pubkey = NULL;
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
- wpabuf_free(wps->dh_privkey);
+ wpabuf_clear_free(wps->dh_privkey);
wps->dh_privkey = NULL;
if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey &&
wps->wps->dh_ctx) {
@@ -300,7 +300,16 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
auth_types &= ~WPS_AUTH_WPA;
auth_types &= ~WPS_AUTH_WPA2;
auth_types &= ~WPS_AUTH_SHARED;
- wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags");
+#ifdef CONFIG_WPS_TESTING
+ if (wps_force_auth_types_in_use) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Testing - replace auth type 0x%x with 0x%x",
+ auth_types, wps_force_auth_types);
+ auth_types = wps_force_auth_types;
+ }
+#endif /* CONFIG_WPS_TESTING */
+ wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags (0x%x)",
+ auth_types);
wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
wpabuf_put_be16(msg, 2);
wpabuf_put_be16(msg, auth_types);
@@ -312,7 +321,16 @@ int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
{
u16 encr_types = WPS_ENCR_TYPES;
encr_types &= ~WPS_ENCR_WEP;
- wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags");
+#ifdef CONFIG_WPS_TESTING
+ if (wps_force_encr_types_in_use) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Testing - replace encr type 0x%x with 0x%x",
+ encr_types, wps_force_encr_types);
+ encr_types = wps_force_encr_types;
+ }
+#endif /* CONFIG_WPS_TESTING */
+ wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags (0x%x)",
+ encr_types);
wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
wpabuf_put_be16(msg, 2);
wpabuf_put_be16(msg, encr_types);
@@ -397,7 +415,8 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
dev_pw_id);
addr[0] = wpabuf_head(pubkey);
hash_len = wpabuf_len(pubkey);
- sha256_vector(1, addr, &hash_len, pubkey_hash);
+ if (sha256_vector(1, addr, &hash_len, pubkey_hash) < 0)
+ return -1;
#ifdef CONFIG_WPS_TESTING
if (wps_corrupt_pkhash) {
wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash",
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
index 748fe0ac..edcfb58b 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c
@@ -85,10 +85,10 @@ static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
const u8 *end = pos + len;
u8 id, elen;
- while (pos + 2 <= end) {
+ while (end - pos >= 2) {
id = *pos++;
elen = *pos++;
- if (pos + elen > end)
+ if (elen > end - pos)
break;
if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
return -1;
diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_process.c b/freebsd/contrib/wpa/src/wps/wps_attr_process.c
index 329649df..bf04d784 100644
--- a/freebsd/contrib/wpa/src/wps/wps_attr_process.c
+++ b/freebsd/contrib/wpa/src/wps/wps_attr_process.c
@@ -231,6 +231,16 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
cred->key_len--;
#endif /* CONFIG_WPS_STRICT */
}
+
+
+ if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
+ (cred->key_len < 8 || has_ctrl_char(cred->key, cred->key_len))) {
+ wpa_printf(MSG_INFO, "WPS: Reject credential with invalid WPA/WPA2-Personal passphrase");
+ wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key",
+ cred->key, cred->key_len);
+ return -1;
+ }
+
return 0;
}
diff --git a/freebsd/contrib/wpa/src/wps/wps_common.c b/freebsd/contrib/wpa/src/wps/wps_common.c
index b6c83892..d7ac00b7 100644
--- a/freebsd/contrib/wpa/src/wps/wps_common.c
+++ b/freebsd/contrib/wpa/src/wps/wps_common.c
@@ -92,7 +92,7 @@ int wps_derive_keys(struct wps_data *wps)
}
/* Own DH private key is not needed anymore */
- wpabuf_free(wps->dh_privkey);
+ wpabuf_clear_free(wps->dh_privkey);
wps->dh_privkey = NULL;
wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared);
@@ -102,7 +102,7 @@ int wps_derive_keys(struct wps_data *wps)
len[0] = wpabuf_len(dh_shared);
sha256_vector(1, addr, len, dhkey);
wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
- wpabuf_free(dh_shared);
+ wpabuf_clear_free(dh_shared);
/* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
addr[0] = wps->nonce_e;
@@ -131,23 +131,26 @@ int wps_derive_keys(struct wps_data *wps)
}
-void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
- size_t dev_passwd_len)
+int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
+ size_t dev_passwd_len)
{
u8 hash[SHA256_MAC_LEN];
- hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
- (dev_passwd_len + 1) / 2, hash);
+ if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
+ (dev_passwd_len + 1) / 2, hash) < 0)
+ return -1;
os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
- hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
- dev_passwd + (dev_passwd_len + 1) / 2,
- dev_passwd_len / 2, hash);
+ if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
+ dev_passwd + (dev_passwd_len + 1) / 2,
+ dev_passwd_len / 2, hash) < 0)
+ return -1;
os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
dev_passwd, dev_passwd_len);
wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
+ return 0;
}
@@ -175,7 +178,7 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
wpabuf_len(decrypted))) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
return NULL;
}
@@ -186,14 +189,14 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
pad = *pos;
if (pad > wpabuf_len(decrypted)) {
wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
return NULL;
}
for (i = 0; i < pad; i++) {
if (*pos-- != pad) {
wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
"string");
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
return NULL;
}
}
@@ -237,20 +240,18 @@ unsigned int wps_pin_valid(unsigned int pin)
* wps_generate_pin - Generate a random PIN
* Returns: Eight digit PIN (i.e., including the checksum digit)
*/
-unsigned int wps_generate_pin(void)
+int wps_generate_pin(unsigned int *pin)
{
unsigned int val;
/* Generate seven random digits for the PIN */
- if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
- struct os_time now;
- os_get_time(&now);
- val = os_random() ^ now.sec ^ now.usec;
- }
+ if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0)
+ return -1;
val %= 10000000;
/* Append checksum digit */
- return val * 10 + wps_pin_checksum(val);
+ *pin = val * 10 + wps_pin_checksum(val);
+ return 0;
}
@@ -377,7 +378,7 @@ struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band,
wps_build_mac_addr(plain, wps->dev.mac_addr) ||
wps_build_wfa_ext(plain, 0, NULL, 0)) {
os_free(data.new_psk);
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
return NULL;
}
@@ -425,7 +426,7 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
wps_build_wfa_ext(data, 0, NULL, 0)) {
wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password "
"token");
- wpabuf_free(data);
+ wpabuf_clear_free(data);
return NULL;
}
@@ -662,7 +663,7 @@ int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey)
wpabuf_free(*pubkey);
*pubkey = pub;
- wpabuf_free(*privkey);
+ wpabuf_clear_free(*privkey);
*privkey = priv;
return 0;
@@ -693,7 +694,7 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
}
*id = 0x10 + val % 0xfff0;
- wpabuf_free(*dev_pw);
+ wpabuf_clear_free(*dev_pw);
*dev_pw = pw;
return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
diff --git a/freebsd/contrib/wpa/src/wps/wps_defs.h b/freebsd/contrib/wpa/src/wps/wps_defs.h
index a23b979d..301864da 100644
--- a/freebsd/contrib/wpa/src/wps/wps_defs.h
+++ b/freebsd/contrib/wpa/src/wps/wps_defs.h
@@ -14,6 +14,10 @@
extern int wps_version_number;
extern int wps_testing_dummy_cred;
extern int wps_corrupt_pkhash;
+extern int wps_force_auth_types_in_use;
+extern u16 wps_force_auth_types;
+extern int wps_force_encr_types_in_use;
+extern u16 wps_force_encr_types;
#define WPS_VERSION wps_version_number
#else /* CONFIG_WPS_TESTING */
diff --git a/freebsd/contrib/wpa/src/wps/wps_enrollee.c b/freebsd/contrib/wpa/src/wps/wps_enrollee.c
index e2cfa571..2260b506 100644
--- a/freebsd/contrib/wpa/src/wps/wps_enrollee.c
+++ b/freebsd/contrib/wpa/src/wps/wps_enrollee.c
@@ -175,7 +175,8 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps)
wpa_printf(MSG_DEBUG, "WPS: No Device Password available");
return NULL;
}
- wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
+ if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0)
+ return NULL;
if (wps->wps->ap && random_pool_ready() != 1) {
wpa_printf(MSG_INFO,
@@ -226,11 +227,11 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->state = RECV_M6;
return msg;
@@ -396,11 +397,11 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
if (wps->wps->ap && wps->wps->registrar) {
/*
@@ -1009,11 +1010,11 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
eattr.key_wrap_auth) ||
wps_process_creds(wps, eattr.cred, eattr.cred_len,
eattr.num_cred, attr->version2 != NULL)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = WPS_MSG_DONE;
return WPS_CONTINUE;
@@ -1114,7 +1115,7 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps,
}
if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -1124,11 +1125,11 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps,
if (wps_parse_msg(decrypted, &eattr) < 0 ||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_r_snonce1(wps, eattr.r_snonce1)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_M5;
return WPS_CONTINUE;
@@ -1167,7 +1168,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
}
if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -1177,11 +1178,11 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
if (wps_parse_msg(decrypted, &eattr) < 0 ||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_r_snonce2(wps, eattr.r_snonce2)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
if (wps->wps->ap)
wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS,
@@ -1238,7 +1239,7 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps,
if (wps_validate_m8_encr(decrypted, wps->wps->ap,
attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -1251,11 +1252,11 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps,
eattr.num_cred, attr->version2 != NULL) ||
wps_process_ap_settings_e(wps, &eattr, decrypted,
attr->version2 != NULL)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = WPS_MSG_DONE;
return WPS_CONTINUE;
diff --git a/freebsd/contrib/wpa/src/wps/wps_i.h b/freebsd/contrib/wpa/src/wps/wps_i.h
index f7154f87..fe0c60bd 100644
--- a/freebsd/contrib/wpa/src/wps/wps_i.h
+++ b/freebsd/contrib/wpa/src/wps/wps_i.h
@@ -132,8 +132,8 @@ struct wps_data {
void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
const char *label, u8 *res, size_t res_len);
int wps_derive_keys(struct wps_data *wps);
-void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
- size_t dev_passwd_len);
+int 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,
diff --git a/freebsd/contrib/wpa/src/wps/wps_registrar.c b/freebsd/contrib/wpa/src/wps/wps_registrar.c
index 261b4557..803569ea 100644
--- a/freebsd/contrib/wpa/src/wps/wps_registrar.c
+++ b/freebsd/contrib/wpa/src/wps/wps_registrar.c
@@ -2,7 +2,7 @@
/*
* Wi-Fi Protected Setup - Registrar
- * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -705,7 +705,7 @@ void wps_registrar_deinit(struct wps_registrar *reg)
eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
wps_registrar_flush(reg);
- wpabuf_free(reg->extra_cred);
+ wpabuf_clear_free(reg->extra_cred);
os_free(reg);
}
@@ -1579,13 +1579,13 @@ int wps_build_credential_wrap(struct wpabuf *msg,
if (wbuf == NULL)
return -1;
if (wps_build_credential(wbuf, cred)) {
- wpabuf_free(wbuf);
+ wpabuf_clear_free(wbuf);
return -1;
}
wpabuf_put_be16(msg, ATTR_CRED);
wpabuf_put_be16(msg, wpabuf_len(wbuf));
wpabuf_put_buf(msg, wbuf);
- wpabuf_free(wbuf);
+ wpabuf_clear_free(wbuf);
return 0;
}
@@ -1608,6 +1608,9 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
wps->cred.ssid_len = wps->wps->ssid_len;
/* Select the best authentication and encryption type */
+ wpa_printf(MSG_DEBUG,
+ "WPS: Own auth types 0x%x - masked Enrollee auth types 0x%x",
+ wps->wps->auth_types, wps->auth_type);
if (wps->auth_type & WPS_AUTH_WPA2PSK)
wps->auth_type = WPS_AUTH_WPA2PSK;
else if (wps->auth_type & WPS_AUTH_WPAPSK)
@@ -1621,6 +1624,14 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
}
wps->cred.auth_type = wps->auth_type;
+ wpa_printf(MSG_DEBUG,
+ "WPS: Own encr types 0x%x (rsn: 0x%x, wpa: 0x%x) - masked Enrollee encr types 0x%x",
+ wps->wps->encr_types, wps->wps->encr_types_rsn,
+ wps->wps->encr_types_wpa, wps->encr_type);
+ if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPA2PSK)
+ wps->encr_type &= wps->wps->encr_types_rsn;
+ else if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPAPSK)
+ wps->encr_type &= wps->wps->encr_types_wpa;
if (wps->auth_type == WPS_AUTH_WPA2PSK ||
wps->auth_type == WPS_AUTH_WPAPSK) {
if (wps->encr_type & WPS_ENCR_AES)
@@ -1742,14 +1753,14 @@ use_provided:
return -1;
if (wps_build_credential(cred, &wps->cred)) {
- wpabuf_free(cred);
+ wpabuf_clear_free(cred);
return -1;
}
wpabuf_put_be16(msg, ATTR_CRED);
wpabuf_put_be16(msg, wpabuf_len(cred));
wpabuf_put_buf(msg, cred);
- wpabuf_free(cred);
+ wpabuf_clear_free(cred);
skip_cred_build:
if (wps->wps->registrar->extra_cred) {
@@ -1787,7 +1798,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
}
if (wps_build_ap_settings(wps, plain)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
@@ -1795,7 +1806,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
wpabuf_put_be16(msg, ATTR_CRED);
wpabuf_put_be16(msg, wpabuf_len(plain));
wpabuf_put_buf(msg, plain);
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
return msg;
}
@@ -1855,10 +1866,10 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
wps_build_key_wrap_auth(wps, plain) ||
wps_build_encr_settings(wps, msg, plain)) {
wpabuf_free(msg);
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
config_in_m2 = 1;
}
#endif /* CONFIG_WPS_NFC */
@@ -1919,7 +1930,8 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
wpa_printf(MSG_DEBUG, "WPS: Building Message M4");
- wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
+ if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0)
+ return NULL;
plain = wpabuf_alloc(200);
if (plain == NULL)
@@ -1940,11 +1952,11 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->state = RECV_M5;
return msg;
@@ -1975,11 +1987,11 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->wps_pin_revealed = 1;
wps->state = RECV_M7;
@@ -2012,11 +2024,11 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
wps_build_encr_settings(wps, msg, plain) ||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
wps_build_authenticator(wps, msg)) {
- wpabuf_free(plain);
- wpabuf_free(msg);
+ wpabuf_clear_free(plain);
+ wpabuf_clear_free(msg);
return NULL;
}
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wps->state = RECV_DONE;
return msg;
@@ -2345,6 +2357,23 @@ static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth)
wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x",
auth_types);
+#ifdef WPS_WORKAROUNDS
+ /*
+ * Some deployed implementations seem to advertise incorrect information
+ * in this attribute. A value of 0x1b (WPA2 + WPA + WPAPSK + OPEN, but
+ * no WPA2PSK) has been reported to be used. Add WPA2PSK to the list to
+ * avoid issues with building Credentials that do not use the strongest
+ * actually supported authentication option (that device does support
+ * WPA2PSK even when it does not claim it here).
+ */
+ if ((auth_types &
+ (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) ==
+ (WPS_AUTH_WPA2 | WPS_AUTH_WPAPSK)) {
+ wpa_printf(MSG_DEBUG,
+ "WPS: Workaround - assume Enrollee supports WPA2PSK based on claimed WPA2 support");
+ auth_types |= WPS_AUTH_WPA2PSK;
+ }
+#endif /* WPS_WORKAROUNDS */
wps->auth_type = wps->wps->auth_types & auth_types;
if (wps->auth_type == 0) {
wpa_printf(MSG_DEBUG, "WPS: No match in supported "
@@ -2759,7 +2788,7 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
}
if (wps_validate_m5_encr(decrypted, attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -2769,11 +2798,11 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
if (wps_parse_msg(decrypted, &eattr) < 0 ||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_e_snonce1(wps, eattr.e_snonce1)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_M6;
return WPS_CONTINUE;
@@ -2911,7 +2940,7 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps,
if (wps_validate_m7_encr(decrypted, wps->wps->ap || wps->er,
attr->version2 != NULL) < 0) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
@@ -2922,12 +2951,12 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps,
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
wps_process_e_snonce2(wps, eattr.e_snonce2) ||
wps_process_ap_settings_r(wps, &eattr)) {
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
- wpabuf_free(decrypted);
+ wpabuf_clear_free(decrypted);
wps->state = SEND_M8;
return WPS_CONTINUE;
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp.c b/freebsd/contrib/wpa/src/wps/wps_upnp.c
index d66ca357..b69d2026 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp.c
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp.c
@@ -1084,6 +1084,7 @@ upnp_wps_get_iface(struct upnp_wps_device_sm *sm, void *priv)
void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm, void *priv)
{
struct upnp_wps_device_interface *iface;
+ struct upnp_wps_peer *peer;
if (!sm)
return;
@@ -1104,8 +1105,13 @@ void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm, void *priv)
iface->wps->registrar);
dl_list_del(&iface->list);
- if (iface->peer.wps)
- wps_deinit(iface->peer.wps);
+ while ((peer = dl_list_first(&iface->peers, struct upnp_wps_peer,
+ list))) {
+ if (peer->wps)
+ wps_deinit(peer->wps);
+ dl_list_del(&peer->list);
+ os_free(peer);
+ }
os_free(iface->ctx->ap_pin);
os_free(iface->ctx);
os_free(iface);
@@ -1143,6 +1149,7 @@ upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps,
}
wpa_printf(MSG_DEBUG, "WPS UPnP: Init interface instance %p", iface);
+ dl_list_init(&iface->peers);
iface->ctx = ctx;
iface->wps = wps;
iface->priv = priv;
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp.h b/freebsd/contrib/wpa/src/wps/wps_upnp.h
index 87b7ab14..b6f6df5e 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp.h
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp.h
@@ -11,11 +11,14 @@
#ifndef WPS_UPNP_H
#define WPS_UPNP_H
+#include "utils/list.h"
+
struct upnp_wps_device_sm;
struct wps_context;
struct wps_data;
struct upnp_wps_peer {
+ struct dl_list list;
struct wps_data *wps;
};
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp_i.h b/freebsd/contrib/wpa/src/wps/wps_upnp_i.h
index f289fe68..6a7c6272 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp_i.h
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp_i.h
@@ -109,8 +109,7 @@ struct upnp_wps_device_interface {
struct wps_context *wps;
void *priv;
- /* FIX: maintain separate structures for each UPnP peer */
- struct upnp_wps_peer peer;
+ struct dl_list peers; /* active UPnP peer sessions */
};
/*
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c b/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c
index ed972494..4d1c8ed4 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp_ssdp.c
@@ -102,12 +102,6 @@ static int line_length(const char *l)
}
-static int str_starts(const char *str, const char *start)
-{
- return os_strncmp(str, start, os_strlen(start)) == 0;
-}
-
-
/***************************************************************************
* Advertisements.
* These are multicast to the world to tell them we are here.
diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp_web.c b/freebsd/contrib/wpa/src/wps/wps_upnp_web.c
index 8c3bbd1b..09f36d37 100644
--- a/freebsd/contrib/wpa/src/wps/wps_upnp_web.c
+++ b/freebsd/contrib/wpa/src/wps/wps_upnp_web.c
@@ -302,7 +302,8 @@ static void http_put_empty(struct wpabuf *buf, enum http_reply_code code)
* would appear to be required (given that we will be closing it!).
*/
static void web_connection_parse_get(struct upnp_wps_device_sm *sm,
- struct http_request *hreq, char *filename)
+ struct http_request *hreq,
+ const char *filename)
{
struct wpabuf *buf; /* output buffer, allocated */
char *put_length_here;
@@ -411,6 +412,15 @@ send_buf:
}
+static void wps_upnp_peer_del(struct upnp_wps_peer *peer)
+{
+ dl_list_del(&peer->list);
+ if (peer->wps)
+ wps_deinit(peer->wps);
+ os_free(peer);
+}
+
+
static enum http_reply_code
web_process_get_device_info(struct upnp_wps_device_sm *sm,
struct wpabuf **reply, const char **replyname)
@@ -428,7 +438,9 @@ web_process_get_device_info(struct upnp_wps_device_sm *sm,
if (!iface || iface->ctx->ap_pin == NULL)
return HTTP_INTERNAL_SERVER_ERROR;
- peer = &iface->peer;
+ peer = os_zalloc(sizeof(*peer));
+ if (!peer)
+ return HTTP_INTERNAL_SERVER_ERROR;
/*
* Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS
@@ -438,9 +450,6 @@ web_process_get_device_info(struct upnp_wps_device_sm *sm,
* registration.
*/
- if (peer->wps)
- wps_deinit(peer->wps);
-
os_memset(&cfg, 0, sizeof(cfg));
cfg.wps = iface->wps;
cfg.pin = (u8 *) iface->ctx->ap_pin;
@@ -457,8 +466,22 @@ web_process_get_device_info(struct upnp_wps_device_sm *sm,
*reply = NULL;
if (*reply == NULL) {
wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo");
+ os_free(peer);
return HTTP_INTERNAL_SERVER_ERROR;
}
+
+ if (dl_list_len(&iface->peers) > 3) {
+ struct upnp_wps_peer *old;
+
+ old = dl_list_first(&iface->peers, struct upnp_wps_peer, list);
+ if (old) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Drop oldest active session");
+ wps_upnp_peer_del(old);
+ }
+ }
+ dl_list_add_tail(&iface->peers, &peer->list);
+ /* TODO: Could schedule a timeout to free the entry */
+
*replyname = name;
return HTTP_OK;
}
@@ -474,6 +497,8 @@ web_process_put_message(struct upnp_wps_device_sm *sm, char *data,
enum wps_process_res res;
enum wsc_op_code op_code;
struct upnp_wps_device_interface *iface;
+ struct wps_parse_attr attr;
+ struct upnp_wps_peer *tmp, *peer;
iface = dl_list_first(&sm->interfaces,
struct upnp_wps_device_interface, list);
@@ -489,11 +514,56 @@ web_process_put_message(struct upnp_wps_device_sm *sm, char *data,
msg = xml_get_base64_item(data, "NewInMessage", &ret);
if (msg == NULL)
return ret;
- res = wps_process_msg(iface->peer.wps, WSC_UPnP, msg);
- if (res == WPS_FAILURE)
+
+ if (wps_parse_msg(msg, &attr)) {
+ wpa_printf(MSG_DEBUG,
+ "WPS UPnP: Could not parse PutMessage - NewInMessage");
+ wpabuf_free(msg);
+ return HTTP_BAD_REQUEST;
+ }
+
+ /* Find a matching active peer session */
+ peer = NULL;
+ dl_list_for_each(tmp, &iface->peers, struct upnp_wps_peer, list) {
+ if (!tmp->wps)
+ continue;
+ if (attr.enrollee_nonce &&
+ os_memcmp(tmp->wps->nonce_e, attr.enrollee_nonce,
+ WPS_NONCE_LEN) != 0)
+ continue; /* Enrollee nonce mismatch */
+ if (attr.msg_type &&
+ *attr.msg_type != WPS_M2 &&
+ *attr.msg_type != WPS_M2D &&
+ attr.registrar_nonce &&
+ os_memcmp(tmp->wps->nonce_r, attr.registrar_nonce,
+ WPS_NONCE_LEN) != 0)
+ continue; /* Registrar nonce mismatch */
+ peer = tmp;
+ break;
+ }
+ if (!peer) {
+ /*
+ Try to use the first entry in case message could work with
+ * it. The actual handler function will reject this, if needed.
+ * This maintains older behavior where only a single peer entry
+ * was supported.
+ */
+ peer = dl_list_first(&iface->peers, struct upnp_wps_peer, list);
+ }
+ if (!peer || !peer->wps) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: No active peer entry found");
+ wpabuf_free(msg);
+ return HTTP_BAD_REQUEST;
+ }
+
+ res = wps_process_msg(peer->wps, WSC_UPnP, msg);
+ if (res == WPS_FAILURE) {
*reply = NULL;
- else
- *reply = wps_get_msg(iface->peer.wps, &op_code);
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Drop active peer session");
+ wps_upnp_peer_del(peer);
+ } else {
+ *reply = wps_get_msg(peer->wps, &op_code);
+ }
wpabuf_free(msg);
if (*reply == NULL)
return HTTP_INTERNAL_SERVER_ERROR;