aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Wetzel <alexander@wetzel-home.de>2020-01-10 22:19:09 (GMT)
committerJouni Malinen <j@w1.fi>2020-02-23 11:05:19 (GMT)
commit1f90a49d028debceb748ab91b7685ae774451e8f (patch)
tree039a94724d640b46232122ec7a9d311fe665be7f
parent1a7963e36fa67b865fd1486ce863e612e6b6a052 (diff)
downloadhostap-1f90a49d028debceb748ab91b7685ae774451e8f.zip
hostap-1f90a49d028debceb748ab91b7685ae774451e8f.tar.gz
hostap-1f90a49d028debceb748ab91b7685ae774451e8f.tar.bz2
STA: Allow PTK rekeying without Ext KeyID to be disabled as a workaround
Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many broken implementations and should be avoided when using or interacting with one. The effects can be triggered by either end of the connection and range from hardly noticeable disconnects over long connection freezes up to leaking clear text MPDUs. To allow affected users to mitigate the issues, add a new configuration option "wpa_deny_ptk0_rekey" to replace all PTK0 rekeys with fast reconnects. Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
-rw-r--r--src/eapol_supp/eapol_supp_sm.c14
-rw-r--r--src/eapol_supp/eapol_supp_sm.h9
-rw-r--r--src/rsn_supp/wpa.c18
-rw-r--r--src/rsn_supp/wpa.h3
-rw-r--r--src/rsn_supp/wpa_i.h7
-rw-r--r--wpa_supplicant/ap.c1
-rw-r--r--wpa_supplicant/config.c2
-rw-r--r--wpa_supplicant/config_file.c1
-rw-r--r--wpa_supplicant/config_ssid.h13
-rw-r--r--wpa_supplicant/ctrl_iface.c2
-rw-r--r--wpa_supplicant/events.c19
-rw-r--r--wpa_supplicant/ibss_rsn.c7
-rw-r--r--wpa_supplicant/preauth_test.c7
-rw-r--r--wpa_supplicant/wpa_cli.c1
-rw-r--r--wpa_supplicant/wpa_supplicant.c26
-rw-r--r--wpa_supplicant/wpa_supplicant.conf26
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h3
-rw-r--r--wpa_supplicant/wpas_glue.c23
18 files changed, 174 insertions, 8 deletions
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index f1ca0a8..a34cc0b 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -200,6 +200,15 @@ 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;
+
+ 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 +325,11 @@ 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 c9d7522..67f82c6 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -298,6 +298,15 @@ 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
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ * Returns: 0 when authentication can continue, -1 when reconnecting
+ *
+ * Automatically triggers a reconnect when not.
+ */
+ int (*confirm_auth_cb)(void *ctx);
};
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 1e209ad..263e210 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_INFO,
+ "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) ||
@@ -618,6 +626,13 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
return;
}
+ if (sm->wpa_deny_ptk0_rekey && wpa_sm_get_state(sm) == WPA_COMPLETED) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "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 "
"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
@@ -3142,6 +3157,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
case WPA_PARAM_SAE_PWE:
sm->sae_pwe = value;
break;
+ case WPA_PARAM_DENY_PTK0_REKEY:
+ sm->wpa_deny_ptk0_rekey = value;
+ break;
default:
break;
}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index e14f26e..0bd1449 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -27,6 +27,7 @@ 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 (*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;
int owe_ptk_workaround;
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index bd44464..7af678d 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -63,6 +63,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;
int owe_ptk_workaround;
@@ -210,6 +211,12 @@ static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg,
seq, seq_len, key, key_len, key_flag);
}
+static inline void wpa_sm_reconnect(struct wpa_sm *sm)
+{
+ WPA_ASSERT(sm->ctx->reconnect);
+ sm->ctx->reconnect(sm->ctx->ctx);
+}
+
static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm)
{
WPA_ASSERT(sm->ctx->get_network_ctx);
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index d1002d2..bbd8f05 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -345,6 +345,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 9dad4ff..9381654 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) },
@@ -3020,6 +3021,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
ssid->pairwise_cipher = DEFAULT_PAIRWISE;
ssid->group_cipher = DEFAULT_GROUP;
ssid->key_mgmt = DEFAULT_KEY_MGMT;
+ ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
ssid->ht = 1;
#ifdef IEEE8021X_EAPOL
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 29bd81f..d453ca5 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 5642d0d..ac08ad8 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -553,6 +553,19 @@ struct wpa_ssid {
*/
int wpa_ptk_rekey;
+ /** wpa_deny_ptk0_rekey - Control PTK0 rekeying
+ *
+ * Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many
+ * broken implementations and should be avoided when using or
+ * interacting with one.
+ *
+ * 0 = always rekey when configured/instructed
+ * 1 = only rekey when the local driver is explicitly indicating it can
+ * perform this operation without issues
+ * 2 = never allow PTK0 rekeys
+ */
+ enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
+
/**
* group_rekey - Group rekeying time in seconds
*
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index c9074a2..10c0961 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -8108,6 +8108,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->no_keep_alive = 0;
wpa_s->own_disconnect_req = 0;
+ wpa_s->own_reconnect_req = 0;
+ wpa_s->deny_ptk0_rekey = 0;
os_free(wpa_s->disallow_aps_bssid);
wpa_s->disallow_aps_bssid = NULL;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index e3fce8f..2851ffc 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2895,6 +2895,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_AP */
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ wpa_s->own_reconnect_req = 0;
ft_completed = wpa_ft_is_completed(wpa_s->wpa);
if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
@@ -3255,21 +3256,25 @@ 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
- * reconnect to the same BSS without full scan to save
- * time for some common cases.
+ * us, but could allow us to get back in. This is also
+ * triggered for cases where local reconnection request
+ * is used to force reassociation with the same BSS.
+ * Try to reconnect to the same BSS without a full scan
+ * to save time for some common cases.
*/
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");
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 37368c4..d143040 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -206,6 +206,12 @@ static void supp_deauthenticate(void * ctx, u16 reason_code)
}
+static void supp_reconnect(void *ctx)
+{
+ wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__);
+}
+
+
static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr,
const u8 *psk)
{
@@ -225,6 +231,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/preauth_test.c b/wpa_supplicant/preauth_test.c
index a732828..7ed5860 100644
--- a/wpa_supplicant/preauth_test.c
+++ b/wpa_supplicant/preauth_test.c
@@ -41,6 +41,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 u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
const void *data, u16 data_len,
size_t *msg_len, void **data_pos)
@@ -245,6 +251,7 @@ static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *ifname)
ctx->set_config_blob = wpa_supplicant_set_config_blob;
ctx->get_config_blob = wpa_supplicant_get_config_blob;
ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
+ ctx->reconnect = _wpa_supplicant_reconnect;
wpa_s->wpa = wpa_sm_init(ctx);
assert(wpa_s->wpa != NULL);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 6d3f56a..490e77c 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1441,6 +1441,7 @@ static const char *network_fields[] = {
"dot11MeshHoldingTimeout",
#endif /* CONFIG_MESH */
"wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
+ "wpa_deny_ptk0_rekey",
"enable_edmg", "edmg_channel",
#ifdef CONFIG_P2P
"go_p2p_dev_addr", "p2p_client_list", "psk_list",
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 7e06a22..634fb29 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1760,6 +1760,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
} else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
+ if (ssid->mode != WPAS_MODE_IBSS &&
+ !(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 - replaced with reconnect");
+ wpa_s->deny_ptk0_rekey = 1;
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1);
+ } else {
+ wpa_s->deny_ptk0_rekey = 0;
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
+ }
+
return 0;
}
@@ -2057,6 +2071,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
@@ -3843,6 +3858,15 @@ 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)
{
@@ -7081,7 +7105,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 d587bd3..15121c3 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1101,6 +1101,32 @@ 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" (two different Key ID values for pairwise keys) can, depending on the
+# used cards/drivers, impact the security and stability of connections. Both
+# ends can accidentally trick one end to drop all packets send by it until the
+# connection is torn down or rekeyed again. Additionally, some drivers may
+# skip/break the encryption for the time window the key is updated (normally a
+# few milliseconds).
+#
+# To avoid such issues, wpa_supplicant can now replace all PTK rekeys using only
+# keyid 0 (PTK0 rekeys) with fast reconnects.
+#
+# EAP reauthentication depends on replacing the PTK and is therefore just
+# another way to rekey the PTK and is affected by the parameter, too.
+#
+# "Extended Key ID for Individually Addressed Frames" is avoiding the issues
+# using two separate keys and this parameter will be ignored when using it
+# (i.e., PTK rekeying is allowed regardless of this parameter value).
+#
+# Available options:
+# 0 = always rekey when configured/instructed (default)
+# 1 = only rekey when the local driver is explicitly indicating it can perform
+# this operation without issues
+# 2 = never allow problematic PTK0 rekeys
+#
# 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 219568a..de2e635 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -554,6 +554,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;
@@ -1071,6 +1072,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)
@@ -1325,6 +1327,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 e8747e6..5ddefce 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -486,6 +486,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);
@@ -1058,6 +1064,20 @@ 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;
+
+ if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "WPA: PTK0 rekey not allowed, reconnecting");
+ wpa_supplicant_reconnect(wpa_s);
+ return -1;
+ }
+ return 0;
+}
+
+
static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -1136,6 +1156,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);
@@ -1222,6 +1243,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;
@@ -1286,6 +1308,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;
conf.owe_ptk_workaround = ssid->owe_ptk_workaround;
#ifdef CONFIG_P2P
if (ssid->p2p_group && wpa_s->current_bss &&