From 349493bd0c9e6355d2d00efb10d0b45d82745adb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 10 May 2012 14:34:46 +0300 Subject: [PATCH] Validate WEP key lengths based on driver capabilities The nl80211 driver interface does not allow 128-bit WEP to be used without a vendor specific cipher suite and no such suite is defined for this purpose. Do not accept WEP key length 16 for nl80211 driver interface forn ow. wext-interface can still try to use these for backwards compatibility. Signed-hostap: Jouni Malinen --- src/drivers/driver.h | 1 + src/drivers/driver_wext.c | 1 + wpa_supplicant/config.c | 20 -------------- wpa_supplicant/config.h | 1 - wpa_supplicant/ctrl_iface.c | 4 +-- wpa_supplicant/events.c | 10 +++---- wpa_supplicant/interworking.c | 2 +- wpa_supplicant/scan.c | 29 +++++++++++--------- wpa_supplicant/scan.h | 2 +- wpa_supplicant/wpa_supplicant.c | 44 +++++++++++++++++++++++++++---- wpa_supplicant/wpa_supplicant_i.h | 3 +++ 11 files changed, 69 insertions(+), 48 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 329f89a25..f7fb2efb2 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -740,6 +740,7 @@ struct wpa_driver_capa { #define WPA_DRIVER_CAPA_ENC_WEP104 0x00000002 #define WPA_DRIVER_CAPA_ENC_TKIP 0x00000004 #define WPA_DRIVER_CAPA_ENC_CCMP 0x00000008 +#define WPA_DRIVER_CAPA_ENC_WEP128 0x00000010 unsigned int enc; #define WPA_DRIVER_AUTH_OPEN 0x00000001 diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index b76ce1d20..c688874bc 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -1575,6 +1575,7 @@ static int wpa_driver_wext_get_range(void *priv) } drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104; + drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP128; if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP) drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP; if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index de8ff1590..ce763b305 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2924,23 +2924,3 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) return ret; } - - -int wpas_network_disabled(struct wpa_ssid *ssid) -{ - int i; - - if (ssid == NULL) - return 1; - - if (ssid->disabled) - return 1; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - size_t len = ssid->wep_key_len[i]; - if (len && len != 5 && len != 13 && len != 16) - return 1; /* invalid WEP key */ - } - - return 0; -} diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 119252e70..3e4f22942 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -653,7 +653,6 @@ int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var, char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys); char * wpa_config_get(struct wpa_ssid *ssid, const char *var); char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var); -int wpas_network_disabled(struct wpa_ssid *ssid); void wpa_config_update_psk(struct wpa_ssid *ssid); int wpa_config_add_prio_network(struct wpa_config *config, struct wpa_ssid *ssid); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index bdc01b9b8..4361f7961 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -60,7 +60,7 @@ static int pno_start(struct wpa_supplicant *wpa_s) num_ssid = 0; ssid = wpa_s->conf->ssid; while (ssid) { - if (!wpas_network_disabled(ssid)) + if (!wpas_network_disabled(wpa_s, ssid)) num_ssid++; ssid = ssid->next; } @@ -82,7 +82,7 @@ static int pno_start(struct wpa_supplicant *wpa_s) i = 0; ssid = wpa_s->conf->ssid; while (ssid) { - if (!wpas_network_disabled(ssid)) { + if (!wpas_network_disabled(wpa_s, ssid)) { params.ssids[i].ssid = ssid->ssid; params.ssids[i].ssid_len = ssid->ssid_len; params.num_ssids++; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e8cf32695..407407ad3 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -57,7 +57,7 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) return -1; } - if (wpas_network_disabled(ssid)) { + if (wpas_network_disabled(wpa_s, ssid)) { wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is disabled"); return -1; } @@ -612,7 +612,7 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, e = wpa_blacklist_get(wpa_s, bss->bssid); if (e) { int limit = 1; - if (wpa_supplicant_enabled_networks(wpa_s->conf) == 1) { + if (wpa_supplicant_enabled_networks(wpa_s) == 1) { /* * When only a single network is enabled, we can * trigger blacklisting on the first failure. This @@ -640,7 +640,7 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, for (ssid = group; ssid; ssid = ssid->pnext) { int check_ssid = wpa ? 1 : (ssid->ssid_len != 0); - if (wpas_network_disabled(ssid)) { + if (wpas_network_disabled(wpa_s, ssid)) { wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); continue; } @@ -805,7 +805,7 @@ wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s, int timeout_sec, int timeout_usec) { - if (!wpa_supplicant_enabled_networks(wpa_s->conf)) { + if (!wpa_supplicant_enabled_networks(wpa_s)) { /* * No networks are enabled; short-circuit request so * we don't wait timeout seconds before transitioning @@ -876,7 +876,7 @@ wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s) for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { for (ssid = wpa_s->conf->pssid[prio]; ssid; ssid = ssid->pnext) { - if (wpas_network_disabled(ssid)) + if (wpas_network_disabled(wpa_s, ssid)) continue; if (ssid->mode == IEEE80211_MODE_IBSS || ssid->mode == IEEE80211_MODE_AP) diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index a260556ee..515d94bbe 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -1104,7 +1104,7 @@ static int interworking_find_network_match(struct wpa_supplicant *wpa_s) dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { - if (wpas_network_disabled(ssid) || + if (wpas_network_disabled(wpa_s, ssid) || ssid->mode != WPAS_MODE_INFRA) continue; if (ssid->ssid_len != bss->ssid_len || diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 277b34f11..923717f29 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -80,12 +80,12 @@ static int wpas_wps_in_use(struct wpa_supplicant *wpa_s, #endif /* CONFIG_WPS */ -int wpa_supplicant_enabled_networks(struct wpa_config *conf) +int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s) { - struct wpa_ssid *ssid = conf->ssid; + struct wpa_ssid *ssid = wpa_s->conf->ssid; int count = 0; while (ssid) { - if (!wpas_network_disabled(ssid)) + if (!wpas_network_disabled(wpa_s, ssid)) count++; ssid = ssid->next; } @@ -97,7 +97,7 @@ static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { while (ssid) { - if (!wpas_network_disabled(ssid)) + if (!wpas_network_disabled(wpa_s, ssid)) break; ssid = ssid->next; } @@ -447,7 +447,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) return; } - if (!wpa_supplicant_enabled_networks(wpa_s->conf) && + if (!wpa_supplicant_enabled_networks(wpa_s) && !wpa_s->scan_req) { wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); @@ -554,7 +554,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) if (ssid == NULL && max_ssids > 1) ssid = wpa_s->conf->ssid; while (ssid) { - if (!wpas_network_disabled(ssid) && ssid->scan_ssid) { + if (!wpas_network_disabled(wpa_s, ssid) && + ssid->scan_ssid) { wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", ssid->ssid, ssid->ssid_len); params.ssids[params.num_ssids].ssid = @@ -574,7 +575,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) } for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) { - if (wpas_network_disabled(tssid)) + if (wpas_network_disabled(wpa_s, tssid)) continue; if ((params.freqs || !freqs_set) && tssid->scan_freq) { int_array_concat(¶ms.freqs, @@ -695,7 +696,8 @@ void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) struct wpa_ssid *ssid = wpa_s->conf->ssid; while (ssid) { - if (!wpas_network_disabled(ssid) && ssid->scan_ssid) + if (!wpas_network_disabled(wpa_s, ssid) && + ssid->scan_ssid) break; ssid = ssid->next; } @@ -771,14 +773,15 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) need_ssids = 0; for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { - if (!wpas_network_disabled(ssid) && !ssid->scan_ssid) { + if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) { /* Use wildcard SSID to find this network */ wildcard = 1; - } else if (!wpas_network_disabled(ssid) && ssid->ssid_len) + } else if (!wpas_network_disabled(wpa_s, ssid) && + ssid->ssid_len) need_ssids++; #ifdef CONFIG_WPS - if (!wpas_network_disabled(ssid) && + if (!wpas_network_disabled(wpa_s, ssid) && ssid->key_mgmt == WPA_KEY_MGMT_WPS) { /* * Normal scan is more reliable and faster for WPS @@ -850,7 +853,7 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) } while (ssid) { - if (wpas_network_disabled(ssid)) + if (wpas_network_disabled(wpa_s, ssid)) goto next; if (params.num_filter_ssids < wpa_s->max_match_sets && @@ -887,7 +890,7 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) do { ssid = ssid->next; } while (ssid && - (wpas_network_disabled(ssid) || + (wpas_network_disabled(wpa_s, ssid) || !ssid->scan_ssid)); break; } diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index 8c83a4230..b0ddf97e9 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -9,7 +9,7 @@ #ifndef SCAN_H #define SCAN_H -int wpa_supplicant_enabled_networks(struct wpa_config *conf); +int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s); void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec); int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s, int sec, int usec); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 6e881cf02..5b9b55674 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -750,7 +750,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) wpa_supplicant_update_config(wpa_s); wpa_supplicant_clear_status(wpa_s); - if (wpa_supplicant_enabled_networks(wpa_s->conf)) { + if (wpa_supplicant_enabled_networks(wpa_s)) { wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } @@ -1898,14 +1898,14 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) entry = wpa_s->conf->ssid; while (entry) { - if (!wpas_network_disabled(entry) && + if (!wpas_network_disabled(wpa_s, entry) && ((ssid_len == entry->ssid_len && os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) && (!entry->bssid_set || os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) return entry; #ifdef CONFIG_WPS - if (!wpas_network_disabled(entry) && + if (!wpas_network_disabled(wpa_s, entry) && (entry->key_mgmt & WPA_KEY_MGMT_WPS) && (entry->ssid == NULL || entry->ssid_len == 0) && (!entry->bssid_set || @@ -1913,7 +1913,7 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) return entry; #endif /* CONFIG_WPS */ - if (!wpas_network_disabled(entry) && entry->bssid_set && + if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set && entry->ssid_len == 0 && os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0) return entry; @@ -2205,7 +2205,7 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; wpa_s->prev_scan_wildcard = 0; - if (wpa_supplicant_enabled_networks(wpa_s->conf)) { + if (wpa_supplicant_enabled_networks(wpa_s)) { if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count, 100000)) wpa_supplicant_req_scan(wpa_s, interface_count, @@ -2620,6 +2620,7 @@ next_driver: if (wpa_drv_get_capa(wpa_s, &capa) == 0) { wpa_s->drv_capa_known = 1; wpa_s->drv_flags = capa.flags; + wpa_s->drv_enc = capa.enc; wpa_s->probe_resp_offloads = capa.probe_resp_offloads; wpa_s->max_scan_ssids = capa.max_scan_ssids; wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids; @@ -3316,3 +3317,36 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s, #endif /* IEEE8021X_EAPOL */ } #endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */ + + +int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +{ + int i; + unsigned int drv_enc; + + if (ssid == NULL) + return 1; + + if (ssid->disabled) + return 1; + + if (wpa_s && wpa_s->drv_capa_known) + drv_enc = wpa_s->drv_enc; + else + drv_enc = (unsigned int) -1; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + size_t len = ssid->wep_key_len[i]; + if (len == 0) + continue; + if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40)) + continue; + if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104)) + continue; + if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128)) + continue; + return 1; /* invalid WEP key */ + } + + return 0; +} diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index f36d117eb..012732bb7 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -362,6 +362,7 @@ struct wpa_supplicant { int normal_scans; /* normal scans run before sched_scan */ unsigned int drv_flags; + unsigned int drv_enc; /* * A bitmap of supported protocols for probe response offload. See @@ -676,4 +677,6 @@ static inline int network_is_persistent_group(struct wpa_ssid *ssid) return ((ssid->disabled == 2) || ssid->p2p_persistent_group); } +int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); + #endif /* WPA_SUPPLICANT_I_H */ -- 2.39.2