static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_scan_res *bss) { struct wpa_ie_data ie; int proto_match = 0; const u8 *rsn_ie, *wpa_ie; int ret; ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss); if (ret >= 0) return ret; rsn_ie = wpa_scan_get_ie(bss, WLAN_EID_RSN); while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) { proto_match++; if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) { wpa_printf(MSG_DEBUG, " skip RSN IE - parse failed"); break; } if (!(ie.proto & ssid->proto)) { wpa_printf(MSG_DEBUG, " skip RSN IE - proto " "mismatch"); break; } if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { wpa_printf(MSG_DEBUG, " skip RSN IE - PTK cipher " "mismatch"); break; } if (!(ie.group_cipher & ssid->group_cipher)) { wpa_printf(MSG_DEBUG, " skip RSN IE - GTK cipher " "mismatch"); break; } if (!(ie.key_mgmt & ssid->key_mgmt)) { wpa_printf(MSG_DEBUG, " skip RSN IE - key mgmt " "mismatch"); break; } #ifdef CONFIG_IEEE80211W if (!(ie.capabilities & WPA_CAPABILITY_MFPC) && ssid->ieee80211w == IEEE80211W_REQUIRED) { wpa_printf(MSG_DEBUG, " skip RSN IE - no mgmt frame " "protection"); break; } #endif /* CONFIG_IEEE80211W */ wpa_printf(MSG_DEBUG, " selected based on RSN IE"); return 1; } wpa_ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) { proto_match++; if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) { wpa_printf(MSG_DEBUG, " skip WPA IE - parse failed"); break; } if (!(ie.proto & ssid->proto)) { wpa_printf(MSG_DEBUG, " skip WPA IE - proto " "mismatch"); break; } if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { wpa_printf(MSG_DEBUG, " skip WPA IE - PTK cipher " "mismatch"); break; } if (!(ie.group_cipher & ssid->group_cipher)) { wpa_printf(MSG_DEBUG, " skip WPA IE - GTK cipher " "mismatch"); break; } if (!(ie.key_mgmt & ssid->key_mgmt)) { wpa_printf(MSG_DEBUG, " skip WPA IE - key mgmt " "mismatch"); break; } wpa_printf(MSG_DEBUG, " selected based on WPA IE"); return 1; } if (proto_match == 0) wpa_printf(MSG_DEBUG, " skip - no WPA/RSN proto match"); return 0; }
static struct wpa_scan_res * wpa_supplicant_select_bss_open(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, struct wpa_ssid **selected_ssid) { struct wpa_ssid *ssid; struct wpa_scan_res *bss; size_t i; struct wpa_blacklist *e; const u8 *ie; wpa_printf(MSG_DEBUG, "Try to find OPEN AP"); for (i = 0; i < wpa_s->scan_res->num; i++) { const u8 *ssid_; u8 wpa_ie_len, rsn_ie_len, ssid_len; bss = wpa_s->scan_res->res[i]; ie = wpa_scan_get_ie(bss, WLAN_EID_SSID); ssid_ = ie ? ie + 2 : (u8 *) ""; ssid_len = ie ? ie[1] : 0; ie = wpa_scan_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; ie = wpa_scan_get_ie(bss, WLAN_EID_RSN); rsn_ie_len = ie ? ie[1] : 0; wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x", (int) i, MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len), wpa_ie_len, rsn_ie_len, bss->caps); e = wpa_blacklist_get(wpa_s, bss->bssid); if (e && e->count > 1) { wpa_printf(MSG_DEBUG, " skip - blacklisted"); continue; } if (ssid_len == 0) { wpa_printf(MSG_DEBUG, " skip - SSID not known"); continue; } for (ssid = group; ssid; ssid = ssid->pnext) { int check_ssid = ssid->ssid_len != 0; if (ssid->disabled) { wpa_printf(MSG_DEBUG, " skip - disabled"); continue; } #ifdef CONFIG_WPS if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { /* Only allow wildcard SSID match if an AP * advertises active WPS operation that matches * with our mode. */ check_ssid = 1; if (ssid->ssid_len == 0 && wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) check_ssid = 0; } #endif /* CONFIG_WPS */ if (check_ssid && (ssid_len != ssid->ssid_len || os_memcmp(ssid_, ssid->ssid, ssid_len) != 0)) { wpa_printf(MSG_DEBUG, " skip - " "SSID mismatch"); continue; } if (ssid->bssid_set && os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, " skip - " "BSSID mismatch"); continue; } /* Fix 5.1.7 WPS test case */ if (wpas_wps_ssid_bss_match(wpa_s, ssid, bss) == 0) { continue; } if (!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { wpa_printf(MSG_DEBUG, " skip - " "non-WPA network not allowed"); continue; } if ((ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_PSK_SHA256)) || (wpa_ie_len != 0 || rsn_ie_len != 0)) { wpa_printf(MSG_DEBUG, " skip - " "WPA network"); continue; } if (bss->caps & IEEE80211_CAP_PRIVACY || !wpa_supplicant_match_privacy(bss, ssid)) { wpa_printf(MSG_DEBUG, " skip - " "privacy mismatch"); continue; } if (bss->caps & IEEE80211_CAP_IBSS) { wpa_printf(MSG_DEBUG, " skip - " "IBSS (adhoc) network"); continue; } wpa_printf(MSG_DEBUG, " selected non-WPA AP " MACSTR " ssid='%s'", MAC2STR(bss->bssid), wpa_ssid_txt(ssid_, ssid_len)); *selected_ssid = ssid; return bss; } } return NULL; }