aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@codeaurora.org>2018-10-10 17:21:21 -0400
committerJohannes Berg <johannes.berg@intel.com>2018-10-11 10:01:08 -0400
commitefb543e61cc3a2e75ffbe52f9b4cfcb850d812fd (patch)
tree207974e8215c8981fc19a6f833f4a3e2dabe7f6a
parent8d7432a2f53bc283148062955cbe7ffbf713e646 (diff)
mac80211: Extend SAE authentication in infra BSS STA mode
Previous implementation of SAE authentication in infrastructure BSS was somewhat restricting and not exactly clean way of handling the two auth() operations. This ended up removing and re-adding the STA entry for the AP in the middle of authentication and also messing up authentication state tracking through the sequence of four Authentication frames. Furthermore, this did not work if the AP ended up sending out SAE Confirm (auth trans #2) immediately after SAE Commit (auth trans #1) before the station had time to transmit its SAE Confirm. Clean up authentication state handling for the SAE case to allow two rounds of auth() calls without dropping all state between those operations. Track peer Confirmed status and mark authentication completed only once both ends have confirmed. ieee80211_mgd_auth() check for EBUSY cases is now handling only the pending association (ifmgd->assoc_data) while all pending authentication (ifmgd->auth_data) cases are allowed to proceed to allow user space to start a new connection attempt from scratch even if the previously requested authentication is still waiting completion. This is needed to avoid making SAE error cases with retries take excessive amount of time with no means for the user space to stop that (apart from setting the netdev down). As an extra bonus, the end of ieee80211_rx_mgmt_auth() can be cleaned up to avoid the extra copy of the cfg80211_rx_mlme_mgmt() call for ongoing SAE authentication since the new ieee80211_mark_sta_auth() helper function can handle both completion of authentication and updates to the STA entry under the same condition and there is no need to return from the function between those operations. Signed-off-by: Jouni Malinen <jouni@codeaurora.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/mlme.c70
2 files changed, 48 insertions, 23 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f40a2167935f..10a05062e4a0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -377,6 +377,7 @@ struct ieee80211_mgd_auth_data {
377 u8 key[WLAN_KEY_LEN_WEP104]; 377 u8 key[WLAN_KEY_LEN_WEP104];
378 u8 key_len, key_idx; 378 u8 key_len, key_idx;
379 bool done; 379 bool done;
380 bool peer_confirmed;
380 bool timeout_started; 381 bool timeout_started;
381 382
382 u16 sae_trans, sae_status; 383 u16 sae_trans, sae_status;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1818dbc5622d..d2bc8d57c87e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2764,8 +2764,15 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
2764static bool ieee80211_mark_sta_auth(struct ieee80211_sub_if_data *sdata, 2764static bool ieee80211_mark_sta_auth(struct ieee80211_sub_if_data *sdata,
2765 const u8 *bssid) 2765 const u8 *bssid)
2766{ 2766{
2767 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2767 struct sta_info *sta; 2768 struct sta_info *sta;
2768 2769
2770 sdata_info(sdata, "authenticated\n");
2771 ifmgd->auth_data->done = true;
2772 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
2773 ifmgd->auth_data->timeout_started = true;
2774 run_again(sdata, ifmgd->auth_data->timeout);
2775
2769 /* move station state to auth */ 2776 /* move station state to auth */
2770 mutex_lock(&sdata->local->sta_mtx); 2777 mutex_lock(&sdata->local->sta_mtx);
2771 sta = sta_info_get(sdata, bssid); 2778 sta = sta_info_get(sdata, bssid);
@@ -2811,7 +2818,11 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2811 status_code = le16_to_cpu(mgmt->u.auth.status_code); 2818 status_code = le16_to_cpu(mgmt->u.auth.status_code);
2812 2819
2813 if (auth_alg != ifmgd->auth_data->algorithm || 2820 if (auth_alg != ifmgd->auth_data->algorithm ||
2814 auth_transaction != ifmgd->auth_data->expected_transaction) { 2821 (auth_alg != WLAN_AUTH_SAE &&
2822 auth_transaction != ifmgd->auth_data->expected_transaction) ||
2823 (auth_alg == WLAN_AUTH_SAE &&
2824 (auth_transaction < ifmgd->auth_data->expected_transaction ||
2825 auth_transaction > 2))) {
2815 sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n", 2826 sdata_info(sdata, "%pM unexpected authentication state: alg %d (expected %d) transact %d (expected %d)\n",
2816 mgmt->sa, auth_alg, ifmgd->auth_data->algorithm, 2827 mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
2817 auth_transaction, 2828 auth_transaction,
@@ -2854,25 +2865,17 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
2854 2865
2855 event.u.mlme.status = MLME_SUCCESS; 2866 event.u.mlme.status = MLME_SUCCESS;
2856 drv_event_callback(sdata->local, sdata, &event); 2867 drv_event_callback(sdata->local, sdata, &event);
2857 sdata_info(sdata, "authenticated\n"); 2868 if (ifmgd->auth_data->algorithm != WLAN_AUTH_SAE ||
2858 ifmgd->auth_data->done = true; 2869 (auth_transaction == 2 &&
2859 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; 2870 ifmgd->auth_data->expected_transaction == 2)) {
2860 ifmgd->auth_data->timeout_started = true; 2871 if (!ieee80211_mark_sta_auth(sdata, bssid))
2861 run_again(sdata, ifmgd->auth_data->timeout); 2872 goto out_err;
2862 2873 } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
2863 if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && 2874 auth_transaction == 2) {
2864 ifmgd->auth_data->expected_transaction != 2) { 2875 sdata_info(sdata, "SAE peer confirmed\n");
2865 /* 2876 ifmgd->auth_data->peer_confirmed = true;
2866 * Report auth frame to user space for processing since another
2867 * round of Authentication frames is still needed.
2868 */
2869 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2870 return;
2871 } 2877 }
2872 2878
2873 if (!ieee80211_mark_sta_auth(sdata, bssid))
2874 goto out_err;
2875
2876 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); 2879 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2877 return; 2880 return;
2878 out_err: 2881 out_err:
@@ -4888,6 +4891,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
4888 struct ieee80211_mgd_auth_data *auth_data; 4891 struct ieee80211_mgd_auth_data *auth_data;
4889 u16 auth_alg; 4892 u16 auth_alg;
4890 int err; 4893 int err;
4894 bool cont_auth;
4891 4895
4892 /* prepare auth data structure */ 4896 /* prepare auth data structure */
4893 4897
@@ -4922,8 +4926,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
4922 return -EOPNOTSUPP; 4926 return -EOPNOTSUPP;
4923 } 4927 }
4924 4928
4925 if ((ifmgd->auth_data && !ifmgd->auth_data->done) || 4929 if (ifmgd->assoc_data)
4926 ifmgd->assoc_data)
4927 return -EBUSY; 4930 return -EBUSY;
4928 4931
4929 auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len + 4932 auth_data = kzalloc(sizeof(*auth_data) + req->auth_data_len +
@@ -4945,6 +4948,13 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
4945 auth_data->data_len += req->auth_data_len - 4; 4948 auth_data->data_len += req->auth_data_len - 4;
4946 } 4949 }
4947 4950
4951 /* Check if continuing authentication or trying to authenticate with the
4952 * same BSS that we were in the process of authenticating with and avoid
4953 * removal and re-addition of the STA entry in
4954 * ieee80211_prep_connection().
4955 */
4956 cont_auth = ifmgd->auth_data && req->bss == ifmgd->auth_data->bss;
4957
4948 if (req->ie && req->ie_len) { 4958 if (req->ie && req->ie_len) {
4949 memcpy(&auth_data->data[auth_data->data_len], 4959 memcpy(&auth_data->data[auth_data->data_len],
4950 req->ie, req->ie_len); 4960 req->ie, req->ie_len);
@@ -4961,12 +4971,26 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
4961 4971
4962 /* try to authenticate/probe */ 4972 /* try to authenticate/probe */
4963 4973
4964 if (ifmgd->auth_data) 4974 if (ifmgd->auth_data) {
4965 ieee80211_destroy_auth_data(sdata, false); 4975 if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE) {
4976 auth_data->peer_confirmed =
4977 ifmgd->auth_data->peer_confirmed;
4978 }
4979 ieee80211_destroy_auth_data(sdata, cont_auth);
4980 }
4966 4981
4967 /* prep auth_data so we don't go into idle on disassoc */ 4982 /* prep auth_data so we don't go into idle on disassoc */
4968 ifmgd->auth_data = auth_data; 4983 ifmgd->auth_data = auth_data;
4969 4984
4985 /* If this is continuation of an ongoing SAE authentication exchange
4986 * (i.e., request to send SAE Confirm) and the peer has already
4987 * confirmed, mark authentication completed since we are about to send
4988 * out SAE Confirm.
4989 */
4990 if (cont_auth && req->auth_type == NL80211_AUTHTYPE_SAE &&
4991 auth_data->peer_confirmed && auth_data->sae_trans == 2)
4992 ieee80211_mark_sta_auth(sdata, req->bss->bssid);
4993
4970 if (ifmgd->associated) { 4994 if (ifmgd->associated) {
4971 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; 4995 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
4972 4996
@@ -4984,7 +5008,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
4984 5008
4985 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); 5009 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
4986 5010
4987 err = ieee80211_prep_connection(sdata, req->bss, false, false); 5011 err = ieee80211_prep_connection(sdata, req->bss, cont_auth, false);
4988 if (err) 5012 if (err)
4989 goto err_clear; 5013 goto err_clear;
4990 5014