aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2010-05-26 14:16:14 (GMT)
committerJouni Malinen <j@w1.fi>2010-09-09 13:07:48 (GMT)
commit54f489be451b6c38574cbb0972f18d623bf0a17a (patch)
treef5ffbf7781cba58f75ef5e71c57bfcc1a833f71e /wpa_supplicant
parent00ae50bc879479f556c6919d8003dbfdb3e24c2d (diff)
downloadhostap-54f489be451b6c38574cbb0972f18d623bf0a17a.zip
hostap-54f489be451b6c38574cbb0972f18d623bf0a17a.tar.gz
hostap-54f489be451b6c38574cbb0972f18d623bf0a17a.tar.bz2
WPS 2.0: Validate WPS attributes in management frames and WSC messages
If CONFIG_WPS_STRICT is set, validate WPS IE(s) in management frames and reject the frames if any of the mandatory attributes is missing or if an included attribute uses an invalid value. In addition, verify that all mandatory attributes are included and have valid values in the WSC messages.
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/Makefile5
-rw-r--r--wpa_supplicant/events.c22
-rw-r--r--wpa_supplicant/scan.c34
-rw-r--r--wpa_supplicant/scan.h2
-rw-r--r--wpa_supplicant/wps_supplicant.c22
5 files changed, 85 insertions, 0 deletions
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 514f5c6..e6a51c7 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -496,6 +496,11 @@ OBJS += ../src/wps/wps_nfc_pn531.o
LIBS += ${PN531_PATH}/lib/wpsnfc.dll
LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
endif
+
+ifdef CONFIG_WPS_STRICT
+CFLAGS += -DCONFIG_WPS_STRICT
+OBJS += ../src/wps/wps_validate.o
+endif
endif
ifdef NEED_WPS_OOB
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 54f05e5..cc4f1b7 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -30,6 +30,7 @@
#include "ap/hostapd.h"
#include "notify.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
#include "blacklist.h"
#include "wpas_glue.h"
#include "wps_supplicant.h"
@@ -921,6 +922,27 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
p = data->assoc_info.resp_ies;
l = data->assoc_info.resp_ies_len;
+#ifdef CONFIG_WPS_STRICT
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
+ struct wpabuf *wps;
+ wps = ieee802_11_vendor_ie_concat(p, l, WPS_IE_VENDOR_TYPE);
+ if (wps == NULL) {
+ wpa_printf(MSG_INFO, "WPS-STRICT: AP did not include "
+ "WPS IE in (Re)Association Response");
+ return -1;
+ }
+
+ if (wps_validate_assoc_resp(wps) < 0) {
+ wpabuf_free(wps);
+ wpa_supplicant_deauthenticate(
+ wpa_s, WLAN_REASON_INVALID_IE);
+ return -1;
+ }
+ wpabuf_free(wps);
+ }
+#endif /* CONFIG_WPS_STRICT */
+
/* Go through the IEs and make a copy of the MDIE, if present. */
while (p && l >= 2) {
len = p[1] + 2;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index bb24995..19210ec 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -580,6 +580,40 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
}
+struct wpabuf * wpa_scan_get_vendor_ie_multi_beacon(
+ const struct wpa_scan_res *res, u32 vendor_type)
+{
+ struct wpabuf *buf;
+ const u8 *end, *pos;
+
+ if (res->beacon_ie_len == 0)
+ return NULL;
+ buf = wpabuf_alloc(res->beacon_ie_len);
+ if (buf == NULL)
+ return NULL;
+
+ pos = (const u8 *) (res + 1);
+ pos += res->ie_len;
+ end = pos + res->beacon_ie_len;
+
+ while (pos + 1 < end) {
+ if (pos + 2 + pos[1] > end)
+ break;
+ if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
+ vendor_type == WPA_GET_BE32(&pos[2]))
+ wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
+ pos += 2 + pos[1];
+ }
+
+ if (wpabuf_len(buf) == 0) {
+ wpabuf_free(buf);
+ buf = NULL;
+ }
+
+ return buf;
+}
+
+
/* Compare function for sorting scan results. Return >0 if @b is considered
* better. */
static int wpa_scan_result_compar(const void *a, const void *b)
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index 441fdbb..025b815 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -32,6 +32,8 @@ const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
u32 vendor_type);
struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
u32 vendor_type);
+struct wpabuf * wpa_scan_get_vendor_ie_multi_beacon(
+ const struct wpa_scan_res *res, u32 vendor_type);
void wpa_scan_results_free(struct wpa_scan_results *res);
#endif /* SCAN_H */
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 5a471f4..18d80dd 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -1029,6 +1029,28 @@ int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
ret = 1;
}
+#ifdef CONFIG_WPS_STRICT
+ if (wps_ie) {
+ if (wps_validate_beacon_probe_resp(wps_ie, bss->beacon_ie_len >
+ 0) < 0)
+ ret = 0;
+ if (bss->beacon_ie_len) {
+ struct wpabuf *bcn_wps;
+ bcn_wps = wpa_scan_get_vendor_ie_multi_beacon(
+ bss, WPS_IE_VENDOR_TYPE);
+ if (bcn_wps == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Mandatory WPS IE "
+ "missing from AP Beacon");
+ ret = 0;
+ } else {
+ if (wps_validate_beacon(wps_ie) < 0)
+ ret = 0;
+ wpabuf_free(bcn_wps);
+ }
+ }
+ }
+#endif /* CONFIG_WPS_STRICT */
+
wpabuf_free(wps_ie);
return ret;