/*
* WPA Supplicant
- * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
const char *const wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors";
const char *const wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
}
+void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
+{
+ struct fils_hlp_req *req;
+
+ while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
+ list)) != NULL) {
+ dl_list_del(&req->list);
+ wpabuf_free(req->pkt);
+ os_free(req);
+ }
+}
+
+
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
int i;
#ifdef CONFIG_TESTING_OPTIONS
l2_packet_deinit(wpa_s->l2_test);
wpa_s->l2_test = NULL;
+ os_free(wpa_s->get_pref_freq_list_override);
+ wpa_s->get_pref_freq_list_override = NULL;
#endif /* CONFIG_TESTING_OPTIONS */
if (wpa_s->conf != NULL) {
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
+ os_free(wpa_s->select_network_scan_freqs);
+ wpa_s->select_network_scan_freqs = NULL;
os_free(wpa_s->manual_sched_scan_freqs);
wpa_s->manual_sched_scan_freqs = NULL;
wpabuf_free(wpa_s->lci);
wpa_s->lci = NULL;
+ wpas_clear_beacon_rep_data(wpa_s);
+
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+ {
+ struct external_pmksa_cache *entry;
+
+ while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache,
+ struct external_pmksa_cache,
+ list)) != NULL) {
+ dl_list_del(&entry->list);
+ os_free(entry->pmksa_cache);
+ os_free(entry);
+ }
+ }
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+ wpas_flush_fils_hlp_req(wpa_s);
+
+ wpabuf_free(wpa_s->ric_ies);
+ wpa_s->ric_ies = NULL;
}
* TODO: should notify EAPOL SM about changes in opensc_engine_path,
* pkcs11_engine_path, pkcs11_module_path, openssl_ciphers.
*/
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
/*
* Clear forced success to clear EAP state for next
* authentication.
wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_OWE
+ } else if (sel & WPA_KEY_MGMT_OWE) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_OWE;
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE");
+#endif /* CONFIG_OWE */
} else {
wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
"authenticated key management type");
u8 channel;
int i;
-#ifdef CONFIG_HT_OVERRIDES
- if (ssid->disable_ht)
- return 0;
-#endif /* CONFIG_HT_OVERRIDES */
-
hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
if (hw_mode == NUM_HOSTAPD_MODES)
return 0;
vht_freq = *freq;
+#ifdef CONFIG_VHT_OVERRIDES
+ if (ssid->disable_vht) {
+ freq->vht_enabled = 0;
+ return;
+ }
+#endif /* CONFIG_VHT_OVERRIDES */
+
vht_freq.vht_enabled = vht_supported(mode);
if (!vht_freq.vht_enabled)
return;
struct ieee80211_vht_capabilities vhtcaps;
struct ieee80211_vht_capabilities vhtcaps_mask;
#endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_FILS
+ const u8 *realm, *username, *rrk;
+ size_t realm_len, username_len, rrk_len;
+ u16 next_seq_num;
+#endif /* CONFIG_FILS */
if (deinit) {
if (work->started) {
algs |= WPA_AUTH_ALG_LEAP;
}
}
+
+#ifdef CONFIG_FILS
+ /* Clear FILS association */
+ wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0);
+
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) &&
+ ssid->eap.erp && wpa_key_mgmt_fils(ssid->key_mgmt) &&
+ eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username,
+ &username_len, &realm, &realm_len,
+ &next_seq_num, &rrk, &rrk_len) == 0) {
+ algs = WPA_AUTH_ALG_FILS;
+ params.fils_erp_username = username;
+ params.fils_erp_username_len = username_len;
+ params.fils_erp_realm = realm;
+ params.fils_erp_realm_len = realm_len;
+ params.fils_erp_next_seq_num = next_seq_num;
+ params.fils_erp_rrk = rrk;
+ params.fils_erp_rrk_len = rrk_len;
+ }
+#endif /* CONFIG_FILS */
#endif /* IEEE8021X_EAPOL */
+
wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
if (ssid->auth_alg) {
algs = ssid->auth_alg;
wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
wpa_key_mgmt_wpa(ssid->key_mgmt)) {
int try_opportunistic;
+ const u8 *cache_id = NULL;
+
try_opportunistic = (ssid->proactive_key_caching < 0 ?
wpa_s->conf->okc :
ssid->proactive_key_caching) &&
(ssid->proto & WPA_PROTO_RSN);
+#ifdef CONFIG_FILS
+ if (wpa_key_mgmt_fils(ssid->key_mgmt))
+ cache_id = wpa_bss_get_fils_cache_id(bss);
+#endif /* CONFIG_FILS */
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
- ssid, try_opportunistic) == 0)
+ ssid, try_opportunistic,
+ cache_id) == 0)
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
wpa_ie_len = sizeof(wpa_ie);
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
params.key_mgmt_suite = wpa_s->key_mgmt;
params.wpa_proto = wpa_s->wpa_proto;
params.auth_alg = algs;
+ wpa_s->auth_alg = params.auth_alg;
params.mode = ssid->mode;
params.bg_scan_period = ssid->bg_scan_period;
for (i = 0; i < NUM_WEP_KEYS; i++) {
os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
+ wpa_s->key_mgmt != WPA_KEY_MGMT_OWE &&
eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
return;
wpa_drv_poll(wpa_s);
wpa_s->sched_scanning = 0;
dl_list_init(&wpa_s->bss_tmp_disallowed);
+ dl_list_init(&wpa_s->fils_hlp_req);
return wpa_s;
}
wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
+ long v;
+
errno = 0;
- long v = strtol(tmp, &end, 16);
+ v = strtol(tmp, &end, 16);
+
if (errno == 0) {
wpa_msg(wpa_s, MSG_DEBUG,
"htcap value[%i]: %ld end: %p tmp: %p",
struct ieee80211_ht_capabilities *htcaps_mask,
int disabled)
{
- /* Masking these out disables HT40 */
- le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
- HT_CAP_INFO_SHORT_GI40MHZ);
-
wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
- if (disabled)
- htcaps->ht_capabilities_info &= ~msk;
- else
- htcaps->ht_capabilities_info |= msk;
-
- htcaps_mask->ht_capabilities_info |= msk;
+ set_disable_ht40(htcaps, disabled);
+ set_disable_ht40(htcaps_mask, 0);
return 0;
}
{
struct wpa_supplicant *wpa_s = ctx;
- WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0);
+ if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) {
+ wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR,
+ __func__, MAC2STR(wpa_s->bssid), MAC2STR(da));
+ return -1;
+ }
return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
- wpa_s->own_addr, wpa_s->bssid,
- wpabuf_head(data), wpabuf_len(data),
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(data), wpabuf_len(data),
0);
}
}
+static int radio_work_is_connect(struct wpa_radio_work *work)
+{
+ return os_strcmp(work->type, "sme-connect") == 0 ||
+ os_strcmp(work->type, "connect") == 0;
+}
+
+
+static int radio_work_is_scan(struct wpa_radio_work *work)
+{
+ return os_strcmp(work->type, "scan") == 0 ||
+ os_strcmp(work->type, "p2p-scan") == 0;
+}
+
+
static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
{
struct wpa_radio_work *active_work = NULL;
return NULL;
}
- if (os_strcmp(active_work->type, "sme-connect") == 0 ||
- os_strcmp(active_work->type, "connect") == 0) {
+ if (radio_work_is_connect(active_work)) {
/*
* If the active work is either connect or sme-connect,
* do not parallelize them with other radio works.
* If connect or sme-connect are enqueued, parallelize only
* those operations ahead of them in the queue.
*/
- if (os_strcmp(tmp->type, "connect") == 0 ||
- os_strcmp(tmp->type, "sme-connect") == 0)
+ if (radio_work_is_connect(tmp))
break;
+ /* Serialize parallel scan and p2p_scan operations on the same
+ * interface since the driver_nl80211 mechanism for tracking
+ * scan cookies does not yet have support for this. */
+ if (active_work->wpa_s == tmp->wpa_s &&
+ radio_work_is_scan(active_work) &&
+ radio_work_is_scan(tmp)) {
+ wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+ "Do not start work '%s' when another work '%s' is already scheduled",
+ tmp->type, active_work->type);
+ continue;
+ }
/*
* Check that the radio works are distinct and
* on different bands.
if (wpa_bss_init(wpa_s) < 0)
return -1;
+#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
+#ifdef CONFIG_MESH
+ dl_list_init(&wpa_s->mesh_external_pmksa_cache);
+#endif /* CONFIG_MESH */
+#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
/*
* Set Wake-on-WLAN triggers, if configured.
* Note: We don't restore/remove the triggers on shutdown (it doesn't
#ifdef CONFIG_MESH
unsigned int mesh_if_created = wpa_s->mesh_if_created;
char *ifname = NULL;
+ struct wpa_supplicant *parent = wpa_s->parent;
#endif /* CONFIG_MESH */
/* Remove interface from the global list of interfaces */
#ifdef CONFIG_MESH
if (mesh_if_created) {
- wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname);
+ wpa_drv_if_remove(parent, WPA_IF_MESH, ifname);
os_free(ifname);
}
#endif /* CONFIG_MESH */
case WPA_CTRL_REQ_SIM:
str_clear_free(eap->external_sim_resp);
eap->external_sim_resp = os_strdup(value);
+ eap->pending_req_sim = 0;
break;
case WPA_CTRL_REQ_PSK_PASSPHRASE:
if (wpa_config_set(ssid, "psk", value, 0) < 0)