Accumulative patch from commit f5f37d3a4fc2df2a24676b4f95afca15ed793cba
Author: Jouni Malinen <j@w1.fi>
Date: Sun Nov 25 22:05:32 2012 +0200
Fix REAUTHENTICATE command after PMKSA caching
The current PMKSA cache entry needs to be clear to allow EAPOL
reauthentication to be started in case this association used PMKSA
caching.
- Remove old WPS_OOB NCF
- WPS: Add preliminary NFC connection handover support for Enrollee
- WPS: Reenable the networks disabled during wpa_wpas_reassoc
- P2P: Avoid multi-channel scans when they are not needed
- P2P: Allow discoverable interval for p2p_find to be configured
- P2P: Allow all channels with multi-channel concurrency
- Bonjour changes
- Remove disassociate
- HS 2.0 changes
- Add preliminary support for using SQLite for eap_user database
- Add SAE support
- Add disallow_aps parameter to disallow BSSIDs/SSIDs
Change-Id: I85358a05b39d46b8db49acdad667e771c580b05c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index ce20e5f..a13a135 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -49,6 +49,8 @@
num = hapd->iface->num_rates;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
num++;
+ if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
+ num++;
if (num > 8) {
/* rest of the rates are encoded in Extended supported
* rates element */
@@ -66,9 +68,15 @@
pos++;
}
- if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
- hapd->iface->num_rates < 8)
+ if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
+ count++;
*pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
+ }
+
+ if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
+ count++;
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
+ }
return pos;
}
@@ -85,6 +93,8 @@
num = hapd->iface->num_rates;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
num++;
+ if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
+ num++;
if (num <= 8)
return eid;
num -= 8;
@@ -103,9 +113,17 @@
pos++;
}
- if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
- hapd->iface->num_rates >= 8)
- *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
+ if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
+ count++;
+ if (count > 8)
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
+ }
+
+ if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
+ count++;
+ if (count > 8)
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
+ }
return pos;
}
@@ -296,6 +314,142 @@
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+
+static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ struct wpabuf *buf;
+
+ buf = wpabuf_alloc(2);
+ if (buf == NULL)
+ return NULL;
+
+ wpabuf_put_le16(buf, 19); /* Finite Cyclic Group */
+ /* TODO: Anti-Clogging Token (if requested) */
+ /* TODO: Scalar */
+ /* TODO: Element */
+
+ return buf;
+}
+
+
+static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ struct wpabuf *buf;
+
+ buf = wpabuf_alloc(2);
+ if (buf == NULL)
+ return NULL;
+
+ wpabuf_put_le16(buf, sta->sae_send_confirm);
+ sta->sae_send_confirm++;
+ /* TODO: Confirm */
+
+ return buf;
+}
+
+
+static u16 handle_sae_commit(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *data, size_t len)
+{
+ wpa_hexdump(MSG_DEBUG, "SAE commit fields", data, len);
+
+ /* Check Finite Cyclic Group */
+ if (len < 2)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ if (WPA_GET_LE16(data) != 19) {
+ wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
+ WPA_GET_LE16(data));
+ return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
+ }
+
+ return WLAN_STATUS_SUCCESS;
+}
+
+
+static u16 handle_sae_confirm(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *data, size_t len)
+{
+ u16 rc;
+
+ wpa_hexdump(MSG_DEBUG, "SAE confirm fields", data, len);
+
+ if (len < 2)
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ rc = WPA_GET_LE16(data);
+ wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", rc);
+
+ return WLAN_STATUS_SUCCESS;
+}
+
+
+static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
+ const struct ieee80211_mgmt *mgmt, size_t len,
+ u8 auth_transaction)
+{
+ u16 resp = WLAN_STATUS_SUCCESS;
+ struct wpabuf *data;
+
+ if (auth_transaction == 1) {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "start SAE authentication (RX commit)");
+ resp = handle_sae_commit(hapd, sta, mgmt->u.auth.variable,
+ ((u8 *) mgmt) + len -
+ mgmt->u.auth.variable);
+ if (resp == WLAN_STATUS_SUCCESS)
+ sta->sae_state = SAE_COMMIT;
+ } else if (auth_transaction == 2) {
+ if (sta->sae_state != SAE_COMMIT) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "SAE confirm before commit");
+ resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
+ }
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "SAE authentication (RX confirm)");
+ resp = handle_sae_confirm(hapd, sta, mgmt->u.auth.variable,
+ ((u8 *) mgmt) + len -
+ mgmt->u.auth.variable);
+ if (resp == WLAN_STATUS_SUCCESS) {
+ sta->flags |= WLAN_STA_AUTH;
+ wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
+ sta->auth_alg = WLAN_AUTH_SAE;
+ mlme_authenticate_indication(hapd, sta);
+ }
+ } else {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "unexpected SAE authentication transaction %u",
+ auth_transaction);
+ resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
+ }
+
+ sta->auth_alg = WLAN_AUTH_SAE;
+
+ if (resp == WLAN_STATUS_SUCCESS) {
+ if (auth_transaction == 1)
+ data = auth_build_sae_commit(hapd, sta);
+ else
+ data = auth_build_sae_confirm(hapd, sta);
+ if (data == NULL)
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ } else
+ data = NULL;
+
+ send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
+ auth_transaction, resp,
+ data ? wpabuf_head(data) : (u8 *) "",
+ data ? wpabuf_len(data) : 0);
+ wpabuf_free(data);
+}
+#endif /* CONFIG_SAE */
+
+
static void handle_auth(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@@ -307,8 +461,7 @@
const u8 *challenge = NULL;
u32 session_timeout, acct_interim_interval;
int vlan_id = 0;
- u8 psk[PMK_LEN];
- int has_psk = 0;
+ struct hostapd_sta_wpa_psk_short *psk = NULL;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
char *identity = NULL;
@@ -348,6 +501,10 @@
(hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
auth_alg == WLAN_AUTH_FT) ||
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+ (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
+ auth_alg == WLAN_AUTH_SAE) ||
+#endif /* CONFIG_SAE */
((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
auth_alg == WLAN_AUTH_SHARED_KEY))) {
printf("Unsupported authentication algorithm (%d)\n",
@@ -356,7 +513,7 @@
goto fail;
}
- if (!(auth_transaction == 1 ||
+ if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
(auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
printf("Unknown authentication transaction number (%d)\n",
auth_transaction);
@@ -374,7 +531,7 @@
res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
&session_timeout,
&acct_interim_interval, &vlan_id,
- psk, &has_psk, &identity, &radius_cui);
+ &psk, &identity, &radius_cui);
if (res == HOSTAPD_ACL_REJECT) {
printf("Station " MACSTR " not allowed to authenticate.\n",
@@ -413,13 +570,11 @@
HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
}
- if (has_psk && hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
- os_free(sta->psk);
- sta->psk = os_malloc(PMK_LEN);
- if (sta->psk)
- os_memcpy(sta->psk, psk, PMK_LEN);
+ hostapd_free_psk_list(sta->psk);
+ if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
+ sta->psk = psk;
+ psk = NULL;
} else {
- os_free(sta->psk);
sta->psk = NULL;
}
@@ -486,11 +641,17 @@
/* handle_auth_ft_finish() callback will complete auth. */
return;
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+ case WLAN_AUTH_SAE:
+ handle_auth_sae(hapd, sta, mgmt, len, auth_transaction);
+ return;
+#endif /* CONFIG_SAE */
}
fail:
os_free(identity);
os_free(radius_cui);
+ hostapd_free_psk_list(psk);
send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
auth_transaction + 1, resp, resp_ies, resp_ies_len);
@@ -779,6 +940,16 @@
}
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+ if (wpa_auth_uses_sae(sta->wpa_sm) &&
+ sta->auth_alg != WLAN_AUTH_SAE) {
+ wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
+ "SAE AKM after non-SAE auth_alg %u",
+ MAC2STR(sta->addr), sta->auth_alg);
+ return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
+ }
+#endif /* CONFIG_SAE */
+
#ifdef CONFIG_IEEE80211N
if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
@@ -807,6 +978,15 @@
p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
#endif /* CONFIG_P2P */
+#ifdef CONFIG_HS20
+ wpabuf_free(sta->hs20_ie);
+ if (elems.hs20 && elems.hs20_len > 4) {
+ sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
+ elems.hs20_len - 4);
+ } else
+ sta->hs20_ie = NULL;
+#endif /* CONFIG_HS20 */
+
return WLAN_STATUS_SUCCESS;
}