[PATCH v2 10/14] PASN: Add support for comeback flow to the wpa_supplicant
Ilan Peer
ilan.peer at intel.com
Wed Dec 16 06:01:01 EST 2020
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
wpa_supplicant/ctrl_iface.c | 27 ++++++++--
wpa_supplicant/pasn_supplicant.c | 85 +++++++++++++++++++++++++++----
wpa_supplicant/wpa_supplicant_i.h | 6 ++-
3 files changed, 104 insertions(+), 14 deletions(-)
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index fe167f13ac..2e4b0a4ce7 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -10464,7 +10464,9 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
u8 bssid[ETH_ALEN];
int akmp = -1, cipher = -1, got_bssid = 0;
u16 group = 0xFFFF;
- int id = 0;
+ u8 *comeback = NULL;
+ size_t comeback_len = 0;
+ int id = 0, ret;
/*
* Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
@@ -10506,6 +10508,21 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
group = atoi(token + 6);
} else if (os_strncmp(token, "nid=", 4) == 0) {
id = atoi(token + 4);
+ } else if (os_strncmp(token, "comeback=", 9) == 0) {
+ comeback_len = os_strlen(token + 9);
+
+ if (!comeback_len || comeback_len % 2)
+ return -1;
+
+ comeback_len /= 2;
+ comeback = os_malloc(comeback_len);
+ if (!comeback)
+ return -1;
+
+ if (hexstr2bin(token + 9, comeback, comeback_len)) {
+ os_free(comeback);
+ return -1;
+ }
} else {
wpa_printf(MSG_DEBUG,
"CTRL: PASN Invalid parameter: '%s'",
@@ -10516,11 +10533,15 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
+ os_free(comeback);
return -1;
}
- return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group,
- id);
+ ret = wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group,
+ id, comeback, comeback_len);
+
+ os_free(comeback);
+ return ret;
}
#endif /* CONFIG_PASN */
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
index 7cf7714506..9ab02192b2 100644
--- a/wpa_supplicant/pasn_supplicant.c
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -33,6 +33,7 @@ struct wpa_pasn_auth_work {
int cipher;
u16 group;
int network_id;
+ struct wpabuf *comeback;
};
@@ -57,8 +58,30 @@ static void wpas_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s)
static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
- int akmp, int cipher, u8 status)
+ int akmp, int cipher, u8 status,
+ struct wpabuf *comeback,
+ u16 comeback_after)
{
+ if (comeback) {
+ size_t comeback_len = wpabuf_len(comeback);
+ char *comeback_txt = os_malloc(comeback_len * 2 + 1);
+
+ if (comeback_txt) {
+ wpa_snprintf_hex(comeback_txt, comeback_len * 2 + 1,
+ wpabuf_head(comeback), comeback_len);
+
+ wpa_msg(wpa_s, MSG_INFO, PASN_AUTH_STATUS MACSTR
+ " akmp=%s, status=%u comeback_after=%u"
+ " comeback=%s",
+ MAC2STR(bssid),
+ wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
+ status, comeback_after, comeback_txt);
+
+ os_free(comeback_txt);
+ return;
+ }
+ }
+
wpa_msg(wpa_s, MSG_INFO,
PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
@@ -601,7 +624,8 @@ static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
}
-static struct wpabuf *wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
+static struct wpabuf *wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s,
+ struct wpabuf *comeback)
{
struct wpas_pasn *pasn = &wpa_s->pasn;
struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
@@ -654,7 +678,7 @@ static struct wpabuf *wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
wrapped_data = WPA_PASN_NO_WRAPPED_DATA;
wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
- pubkey, NULL, 0);
+ pubkey, comeback, 0);
wpa_pasn_add_wrapped_data(buf, wrapped_data_buf);
@@ -782,6 +806,10 @@ static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
wpabuf_free(pasn->beacon_rsne);
pasn->beacon_rsne = NULL;
+ wpabuf_free(pasn->comeback);
+ pasn->comeback = NULL;
+ pasn->comeback_after = 0;
+
#ifdef CONFIG_SAE
sae_clear_data(&pasn->sae);
#endif /* CONFIG_SAE */
@@ -876,7 +904,7 @@ static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
int akmp, int cipher, u16 group, int freq,
const u8 *beacon_rsne, u8 beacon_rsne_len,
- int network_id)
+ int network_id, struct wpabuf *comeback)
{
struct wpas_pasn *pasn = &wpa_s->pasn;
struct wpa_ssid *ssid;
@@ -946,7 +974,7 @@ static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
pasn->group);
- frame = wpas_pasn_build_auth_1(wpa_s);
+ frame = wpas_pasn_build_auth_1(wpa_s, comeback);
if (!frame) {
wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
goto fail;
@@ -1029,6 +1057,8 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
wpa_s, NULL);
wpa_s->pasn_auth_work = NULL;
}
+
+ wpabuf_free(awork->comeback);
os_free(awork);
return;
}
@@ -1053,16 +1083,23 @@ static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
awork->group, bss->freq,
- rsne, *(rsne + 1) + 2, awork->network_id);
+ rsne, *(rsne + 1) + 2, awork->network_id,
+ awork->comeback);
if (ret) {
wpa_printf(MSG_DEBUG,
"PASN: Failed to start PASN authentication");
goto fail;
}
+ /* comeback token is no longer needed at this stage */
+ wpabuf_free(awork->comeback);
+ awork->comeback = NULL;
+
wpa_s->pasn_auth_work = work;
return;
fail:
+ wpabuf_free(awork->comeback);
+ awork->comeback = NULL;
os_free(awork);
work->ctx = NULL;
radio_work_done(work);
@@ -1071,7 +1108,8 @@ fail:
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
const u8 *bssid, int akmp, int cipher,
- u16 group, int network_id)
+ u16 group, int network_id,
+ const u8 *comeback, size_t comeback_len)
{
struct wpa_pasn_auth_work *awork;
struct wpa_bss *bss;
@@ -1118,8 +1156,19 @@ int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
awork->group = group;
awork->network_id = network_id;
+ if (comeback && comeback_len) {
+ awork->comeback = wpabuf_alloc(comeback_len);
+ if (!awork->comeback) {
+ os_free(awork);
+ return -1;
+ }
+
+ wpabuf_put_data(awork->comeback, comeback, comeback_len);
+ }
+
if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
wpas_pasn_auth_start_cb, awork) < 0) {
+ wpabuf_free(awork->comeback);
os_free(awork);
return -1;
}
@@ -1139,7 +1188,8 @@ void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "PASN: stopping authentication");
wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
- pasn->status);
+ pasn->status, pasn->comeback,
+ pasn->comeback_after);
wpas_pasn_reset(wpa_s);
}
@@ -1237,10 +1287,21 @@ int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
goto fail;
}
- /* TODO: handle comeback flow */
if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
wpa_printf(MSG_DEBUG,
"PASN: authentication temporarily rejected");
+
+ if (pasn_params.comeback && pasn_params.comeback_len) {
+ pasn->comeback = wpabuf_alloc(pasn_params.comeback_len);
+ if (pasn->comeback) {
+ wpabuf_put_data(pasn->comeback,
+ pasn_params.comeback,
+ pasn_params.comeback_len);
+ pasn->comeback_after = pasn_params.after;
+ }
+ }
+
+ pasn->status = status;
goto fail;
}
@@ -1368,7 +1429,11 @@ fail:
* the frame and terminate the authentication exchange. However, better
* reply to the AP with an error status
*/
- pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ if (status == WLAN_STATUS_SUCCESS)
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ else
+ pasn->status = status;
+
wpas_pasn_auth_stop(wpa_s);
return -1;
}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index a2f96ef191..244c43f2ed 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -553,6 +553,9 @@ struct wpas_pasn {
struct wpa_ptk ptk;
struct crypto_ecdh *ecdh;
+ struct wpabuf *comeback;
+ u16 comeback_after;
+
#ifdef CONFIG_SAE
struct sae_data sae;
#endif /* CONFIG_SAE */
@@ -1703,7 +1706,8 @@ int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s);
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
const u8 *bssid, int akmp, int cipher,
- u16 group, int network_id);
+ u16 group, int network_id,
+ const u8 *comeback, size_t comeback_len);
void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
const u8 *data, size_t data_len, u8 acked);
--
2.17.1
More information about the Hostap
mailing list