[Patch v9 03/16] wpa_supplicant: Address PTK rekey issues

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Rekeying a pairwise key using only keyid 0 (PTK0 rekeys) has many broken
implementations and should be avoided for both security and usability
reasons.

Add the new configuration option "wpa_deny_ptk0_rekey" - defaulting to
replace any PTK0 rekey attempt with a fast reconnect.

Signed-off-by: Alexander Wetzel <alexander@xxxxxxxxxxxxxx>
---
 src/eapol_supp/eapol_supp_sm.c     | 15 +++++++++++++++
 src/eapol_supp/eapol_supp_sm.h     |  8 ++++++++
 src/rsn_supp/wpa.c                 | 18 ++++++++++++++++++
 src/rsn_supp/wpa.h                 |  5 ++++-
 src/rsn_supp/wpa_i.h               |  7 +++++++
 wpa_supplicant/ap.c                |  1 +
 wpa_supplicant/config.c            |  2 ++
 wpa_supplicant/config_file.c       |  1 +
 wpa_supplicant/config_ssid.h       | 11 +++++++++++
 wpa_supplicant/events.c            | 16 ++++++++++------
 wpa_supplicant/ibss_rsn.c          |  9 ++++++++-
 wpa_supplicant/notify.c            | 10 ++++++++++
 wpa_supplicant/notify.h            |  1 +
 wpa_supplicant/wpa_cli.c           |  5 +++--
 wpa_supplicant/wpa_supplicant.c    | 26 +++++++++++++++++++++++++-
 wpa_supplicant/wpa_supplicant.conf | 25 +++++++++++++++++++++++++
 wpa_supplicant/wpa_supplicant_i.h  |  3 +++
 wpa_supplicant/wpas_glue.c         | 17 +++++++++++++++++
 18 files changed, 169 insertions(+), 11 deletions(-)

diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index f1ca0a859..90a551200 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -200,6 +200,17 @@ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx)
 }
 
 
+static int eapol_sm_confirm_auth(struct eapol_sm *sm)
+{
+	if (!sm->ctx->confirm_auth_cb)
+		return 0;
+
+	wpa_printf(MSG_DEBUG,
+		   "EAPOL: Confirm planned PTK key install or trigger reconnect");
+	return sm->ctx->confirm_auth_cb(sm->ctx->ctx);
+}
+
+
 static void eapol_enable_timer_tick(struct eapol_sm *sm)
 {
 	if (sm->timer_tick_enabled)
@@ -316,6 +327,10 @@ SM_STATE(SUPP_PAE, AUTHENTICATED)
 
 SM_STATE(SUPP_PAE, RESTART)
 {
+	if (eapol_sm_confirm_auth(sm))
+		/* Don't process restart, we are already reconnecting */
+		return;
+
 	SM_ENTRY(SUPP_PAE, RESTART);
 	sm->eapRestart = TRUE;
 	if (sm->altAccept) {
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index c9d7522d5..3511c12d5 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -298,6 +298,14 @@ struct eapol_ctx {
 	 * @len: Length of anonymous identity in octets
 	 */
 	void (*set_anon_id)(void *ctx, const u8 *id, size_t len);
+
+	/**
+	 * confirm_auth_cb - Callback confirming if we can install a new PTK
+	 * Triggers a reconnect when the check fails.
+	 * @ctx: Callback context (ctx)
+	 * Returns: 0 when authentication can continue, -1 when reconnecting
+	 */
+	int (*confirm_auth_cb)(void *ctx);
 };
 
 
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index adcda3443..e8931ff08 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -183,6 +183,14 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
 	int key_info, ver;
 	u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic;
 
+	if (pairwise && sm->wpa_deny_ptk0_rekey &&
+	    wpa_sm_get_state(sm) == WPA_COMPLETED) {
+		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+			"WPA: PTK0 rekey not allowed, reconnecting");
+		wpa_sm_reconnect(sm);
+		return;
+	}
+
 	if (wpa_use_akm_defined(sm->key_mgmt))
 		ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
 	else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
@@ -607,6 +615,13 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
 			"found (msg 1 of 4)");
 		return;
 	}
+	if (sm->wpa_deny_ptk0_rekey &&
+	    wpa_sm_get_state(sm) == WPA_COMPLETED) {
+		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+			"WPA: PTK0 rekey not allowed, reconnecting");
+		wpa_sm_reconnect(sm);
+		return;
+	}
 
 	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
 	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
@@ -3043,6 +3058,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
 	case WPA_PARAM_PAIRWISE:
 		sm->pairwise_cipher = value;
 		break;
+	case WPA_PARAM_DENY_PTK0_REKEY:
+		sm->wpa_deny_ptk0_rekey = value;
+		break;
 	case WPA_PARAM_GROUP:
 		sm->group_cipher = value;
 		break;
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index f1fbb1bb5..ef77475cb 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -26,7 +26,8 @@ struct wpa_sm_ctx {
 
 	void (*set_state)(void *ctx, enum wpa_states state);
 	enum wpa_states (*get_state)(void *ctx);
-	void (*deauthenticate)(void * ctx, u16 reason_code);
+	void (*deauthenticate)(void *ctx, u16 reason_code);
+	void (*reconnect)(void *ctx);
 	int (*set_key)(void *ctx, enum wpa_alg alg,
 		       const u8 *addr, int key_idx, int set_tx,
 		       const u8 *seq, size_t seq_len,
@@ -100,6 +101,7 @@ enum wpa_sm_conf_params {
 	WPA_PARAM_MFP,
 	WPA_PARAM_OCV,
 	WPA_PARAM_SAE_PWE,
+	WPA_PARAM_DENY_PTK0_REKEY
 };
 
 struct rsn_supp_config {
@@ -111,6 +113,7 @@ struct rsn_supp_config {
 	const u8 *ssid;
 	size_t ssid_len;
 	int wpa_ptk_rekey;
+	int wpa_deny_ptk0_rekey;
 	int p2p;
 	int wpa_rsc_relaxation;
 	const u8 *fils_cache_id;
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 2a433425c..8faaa85a3 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -61,6 +61,7 @@ struct wpa_sm {
 	u8 ssid[32];
 	size_t ssid_len;
 	int wpa_ptk_rekey;
+	int wpa_deny_ptk0_rekey:1;
 	int p2p;
 	int wpa_rsc_relaxation;
 
@@ -195,6 +196,12 @@ static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, u16 reason_code)
 	sm->ctx->deauthenticate(sm->ctx->ctx, reason_code);
 }
 
+static inline void wpa_sm_reconnect(struct wpa_sm *sm)
+{
+	WPA_ASSERT(sm->ctx->reconnect);
+	sm->ctx->reconnect(sm->ctx->ctx);
+}
+
 static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg,
 				 const u8 *addr, int key_idx, int set_tx,
 				 const u8 *seq, size_t seq_len,
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index e552306d7..004d86bc3 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -349,6 +349,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
 
 	bss->isolate = !wpa_s->conf->p2p_intra_bss;
 	bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
+	bss->wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey;
 
 	if (ssid->p2p_group) {
 		os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 3b37d152d..02d5f0b07 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2495,6 +2495,7 @@ static const struct parse_data ssid_fields[] = {
 	{ INT(dot11MeshHoldingTimeout) },
 #endif /* CONFIG_MESH */
 	{ INT(wpa_ptk_rekey) },
+	{ INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) },
 	{ INT(group_rekey) },
 	{ STR(bgscan) },
 	{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
@@ -3016,6 +3017,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
 {
 	ssid->proto = DEFAULT_PROTO;
 	ssid->pairwise_cipher = DEFAULT_PAIRWISE;
+	ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_NEVER;
 	ssid->group_cipher = DEFAULT_GROUP;
 	ssid->key_mgmt = DEFAULT_KEY_MGMT;
 	ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 2a0c7803e..16b5251d0 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -900,6 +900,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
 	INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD);
 #endif /* CONFIG_MESH */
 	INT(wpa_ptk_rekey);
+	INT(wpa_deny_ptk0_rekey);
 	INT(group_rekey);
 	INT(ignore_broadcast_ssid);
 #ifdef CONFIG_DPP
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 98db1fe1a..f4bbb7882 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -553,6 +553,17 @@ struct wpa_ssid {
 	 */
 	int wpa_ptk_rekey;
 
+	/** wpa_deny_ptk0_rekey - Control PTK0 rekeying
+	 *
+	 * Rekeying a pairwise key using only keyid 0 (PTK0 rekeys) has many
+	 * broken implementations and should only be used when known to be safe.
+	 *
+	 * 0 = always rekey when configured/instructed (old behavior)
+	 * 1 = only rekey when local driver is able to do it bug free
+	 * 2 = never allow PTK0 rekeys (default)
+	 */
+	int wpa_deny_ptk0_rekey;
+
 	/**
 	 * group_rekey - Group rekeying time in seconds
 	 *
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index d75a50eaf..4b02c2b2c 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3214,8 +3214,9 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
 		if (wpa_s->wpa_state == WPA_COMPLETED &&
 		    wpa_s->current_ssid &&
 		    wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
-		    !locally_generated &&
-		    disconnect_reason_recoverable(reason_code)) {
+		    (wpa_s->own_reconnect_req ||
+		     (!locally_generated &&
+		      disconnect_reason_recoverable(reason_code)))) {
 			/*
 			 * It looks like the AP has dropped association with
 			 * us, but could allow us to get back in. Try to
@@ -3224,11 +3225,12 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
 			 */
 			fast_reconnect = wpa_s->current_bss;
 			fast_reconnect_ssid = wpa_s->current_ssid;
-		} else if (wpa_s->wpa_state >= WPA_ASSOCIATING)
+		} else if (wpa_s->wpa_state >= WPA_ASSOCIATING) {
 			wpa_supplicant_req_scan(wpa_s, 0, 100000);
-		else
+		} else {
 			wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new "
 				"immediate scan");
+		}
 	} else {
 		wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not "
 			"try to re-connect");
@@ -3270,15 +3272,16 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
 			     fast_reconnect->ssid_len) &&
 	    !wpas_temp_disabled(wpa_s, fast_reconnect_ssid) &&
 	    !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect)) {
-#ifndef CONFIG_NO_SCAN_PROCESSING
 		wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
 		if (wpa_supplicant_connect(wpa_s, fast_reconnect,
 					   fast_reconnect_ssid) < 0) {
+#ifndef CONFIG_NO_SCAN_PROCESSING
 			/* Recover through full scan */
 			wpa_supplicant_req_scan(wpa_s, 0, 100000);
-		}
 #endif /* CONFIG_NO_SCAN_PROCESSING */
+		}
 	} else if (fast_reconnect) {
+#ifndef CONFIG_NO_SCAN_PROCESSING
 		/*
 		 * Could not reconnect to the same BSS due to network being
 		 * disabled. Use a new scan to match the alternative behavior
@@ -3286,6 +3289,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
 		 * way that enforces disabled network rules.
 		 */
 		wpa_supplicant_req_scan(wpa_s, 0, 100000);
+#endif /* CONFIG_NO_SCAN_PROCESSING */
 	}
 }
 
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 48dd66b12..93a683551 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -194,7 +194,13 @@ static void supp_cancel_auth_timeout(void *ctx)
 }
 
 
-static void supp_deauthenticate(void * ctx, u16 reason_code)
+static void supp_deauthenticate(void *ctx, u16 reason_code)
+{
+	wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__);
+}
+
+
+static void supp_reconnect(void *ctx)
 {
 	wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__);
 }
@@ -219,6 +225,7 @@ static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr,
 	ctx->mlme_setprotection = supp_mlme_setprotection;
 	ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
 	ctx->deauthenticate = supp_deauthenticate;
+	ctx->reconnect = supp_reconnect;
 	peer->supp = wpa_sm_init(ctx);
 	if (peer->supp == NULL) {
 		wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 0ba1e144c..6758e6cf0 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -851,6 +851,16 @@ void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code)
 	wpa_msg(wpa_s, MSG_ERROR, WPA_EVENT_EAP_ERROR_CODE "%d", error_code);
 }
 
+int wpas_notify_eap_auth_start(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey) {
+		wpa_msg(wpa_s, MSG_WARNING,
+			"WPA: PTK0 rekey not allowed, reconnecting");
+		wpa_supplicant_reconnect(wpa_s);
+		return -1;
+	}
+	return 0;
+}
 
 void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
 					   struct wpa_ssid *ssid)
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index e843aa124..bc9a022e5 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -140,6 +140,7 @@ void wpas_notify_preq(struct wpa_supplicant *wpa_s,
 void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
 			    const char *parameter);
 void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code);
+int wpas_notify_eap_auth_start(struct wpa_supplicant *wpa_s);
 void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
 					   struct wpa_ssid *ssid);
 void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 6d3f56a87..63c681ffa 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1440,8 +1440,9 @@ static const char *network_fields[] = {
 	"dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
 	"dot11MeshHoldingTimeout",
 #endif /* CONFIG_MESH */
-	"wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
-	"enable_edmg", "edmg_channel",
+	"wpa_ptk_rekey",
+	"wpa_deny_ptk0_rekey", "bgscan",
+	"ignore_broadcast_ssid", "enable_edmg", "edmg_channel",
 #ifdef CONFIG_P2P
 	"go_p2p_dev_addr", "p2p_client_list", "psk_list",
 #endif /* CONFIG_P2P */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 08b140312..e6460fa4a 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1271,6 +1271,22 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
 	int sel, proto;
 	const u8 *bss_wpa, *bss_rsn, *bss_rsnx, *bss_osen;
 
+	if (ssid->mode == WPAS_MODE_IBSS) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"PTK rekey not supported, ignoring PTK0 rekey setting");
+	} else if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
+	    (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
+	     (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
+	      !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
+		wpa_msg(wpa_s, MSG_INFO, "Disable PTK0 rekey support");
+		wpa_s->deny_ptk0_rekey = 1;
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
+	} else {
+		wpa_dbg(wpa_s, MSG_DEBUG, "Support PTK0 rekey");
+		wpa_s->deny_ptk0_rekey = 0;
+		wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
+	}
+
 	if (bss) {
 		bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
 		bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
@@ -2044,6 +2060,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
 	int rand_style;
 
 	wpa_s->own_disconnect_req = 0;
+	wpa_s->own_reconnect_req = 0;
 
 	/*
 	 * If we are starting a new connection, any previously pending EAPOL
@@ -3830,6 +3847,13 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
 	wpa_supplicant_clear_connection(wpa_s, addr);
 }
 
+void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s)
+{
+	wpa_s->own_reconnect_req = 1;
+	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED);
+
+}
+
 static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
 					      struct wpa_ssid *ssid)
 {
@@ -7069,7 +7093,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
 	 * There is no point in blacklisting the AP if this event is
 	 * generated based on local request to disconnect.
 	 */
-	if (wpa_s->own_disconnect_req) {
+	if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
 		wpa_s->own_disconnect_req = 0;
 		wpa_dbg(wpa_s, MSG_DEBUG,
 			"Ignore connection failure due to local request to disconnect");
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 328f91a97..2665a8d11 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1102,6 +1102,31 @@ fast_reauth=1
 # wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
 # enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
 #
+# wpa_deny_ptk0_rekey: Control PTK0 rekeying.
+# Rekeying the PTK without using "Extended Key ID for Individually Addressed
+# Frames" can - depending on the cards/drivers - reduce both the security and
+# the stability of connections. Both ends can freeze the connection or even leak
+# the PTK by repeating MPDU's without encryption. To avoid the issues
+# wpa_supplicant is now by default replacing all PTK rekeys using only keyid 0
+# (PTK0 rekeys) with disconnects.
+# This is a regression for setups able to rekey the PTK and actually do so.
+#
+# Eap reauthentication depends on replacing the PTK and is therefore just
+# another way to rekey the PTK and affected by the setting, too.
+#
+# Unfortunately there is no way to detect if a remote stations can safely rekey
+# the PTK and the default is therefore to replace all those rekeys with a
+# disconnect when not two keyids (Extended Key ID for Individually Addressed
+# Frames) are available for it.
+#
+# If you are sure your cards/drivers don't need the workaround the old behavior
+# can be restored by setting wpa_deny_ptk0_rekey = 0.
+#
+# Available options:
+# 0 = always rekey when configured/instructed (old behavior)
+# 1 = only rekey when local driver is able to do it bug free
+# 2 = never allow problematic PTK0 rekeys (default)
+#
 # group_rekey: Group rekeying time in seconds. This value, if non-zero, is used
 # as the dot11RSNAConfigGroupRekeyTime parameter when operating in
 # Authenticator role in IBSS, or in AP and mesh modes.
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index b8313f935..4e7faa246 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -553,6 +553,7 @@ struct wpa_supplicant {
 
 	/* Selected configuration (based on Beacon/ProbeResp WPA IE) */
 	int pairwise_cipher;
+	int deny_ptk0_rekey;
 	int group_cipher;
 	int key_mgmt;
 	int wpa_proto;
@@ -1072,6 +1073,7 @@ struct wpa_supplicant {
 	unsigned int wmm_ac_supported:1;
 	unsigned int ext_work_in_progress:1;
 	unsigned int own_disconnect_req:1;
+	unsigned int own_reconnect_req:1;
 	unsigned int ignore_post_flush_scan_res:1;
 
 #define MAC_ADDR_RAND_SCAN       BIT(0)
@@ -1326,6 +1328,7 @@ const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s);
 void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
 				   u16 reason_code);
+void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s);
 
 struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id);
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index d80b8f28d..1f78e2d93 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -476,6 +476,12 @@ static void _wpa_supplicant_deauthenticate(void *wpa_s, u16 reason_code)
 }
 
 
+static void _wpa_supplicant_reconnect(void *wpa_s)
+{
+	wpa_supplicant_reconnect(wpa_s);
+}
+
+
 static void * wpa_supplicant_get_network_ctx(void *wpa_s)
 {
 	return wpa_supplicant_get_ssid(wpa_s);
@@ -1047,6 +1053,14 @@ static void wpa_supplicant_eap_error_cb(void *ctx, int error_code)
 }
 
 
+static int wpa_supplicant_eap_auth_start_cb(void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	return wpas_notify_eap_auth_start(wpa_s);
+}
+
+
 static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
 {
 	struct wpa_supplicant *wpa_s = ctx;
@@ -1125,6 +1139,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
 	ctx->cert_in_cb = wpa_s->conf->cert_in_cb;
 	ctx->status_cb = wpa_supplicant_status_cb;
 	ctx->eap_error_cb = wpa_supplicant_eap_error_cb;
+	ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb;
 	ctx->set_anon_id = wpa_supplicant_set_anon_id;
 	ctx->cb_ctx = wpa_s;
 	wpa_s->eapol = eapol_sm_init(ctx);
@@ -1211,6 +1226,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
 	ctx->set_state = _wpa_supplicant_set_state;
 	ctx->get_state = _wpa_supplicant_get_state;
 	ctx->deauthenticate = _wpa_supplicant_deauthenticate;
+	ctx->reconnect = _wpa_supplicant_reconnect;
 	ctx->set_key = wpa_supplicant_set_key;
 	ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
 	ctx->get_bssid = wpa_supplicant_get_bssid;
@@ -1275,6 +1291,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
 		conf.ssid = ssid->ssid;
 		conf.ssid_len = ssid->ssid_len;
 		conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
+		conf.wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey;
 #ifdef CONFIG_P2P
 		if (ssid->p2p_group && wpa_s->current_bss &&
 		    !wpa_s->p2p_disable_ip_addr_req) {
-- 
2.24.1


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux