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>
This commit is contained in:
parent
1a7963e36f
commit
1f90a49d02
18 changed files with 174 additions and 8 deletions
|
@ -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)
|
static void eapol_enable_timer_tick(struct eapol_sm *sm)
|
||||||
{
|
{
|
||||||
if (sm->timer_tick_enabled)
|
if (sm->timer_tick_enabled)
|
||||||
|
@ -316,6 +325,11 @@ SM_STATE(SUPP_PAE, AUTHENTICATED)
|
||||||
|
|
||||||
SM_STATE(SUPP_PAE, RESTART)
|
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_ENTRY(SUPP_PAE, RESTART);
|
||||||
sm->eapRestart = TRUE;
|
sm->eapRestart = TRUE;
|
||||||
if (sm->altAccept) {
|
if (sm->altAccept) {
|
||||||
|
|
|
@ -298,6 +298,15 @@ struct eapol_ctx {
|
||||||
* @len: Length of anonymous identity in octets
|
* @len: Length of anonymous identity in octets
|
||||||
*/
|
*/
|
||||||
void (*set_anon_id)(void *ctx, const u8 *id, size_t len);
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,14 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
|
||||||
int key_info, ver;
|
int key_info, ver;
|
||||||
u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic;
|
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))
|
if (wpa_use_akm_defined(sm->key_mgmt))
|
||||||
ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
|
||||||
else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
|
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;
|
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_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
|
||||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
|
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
|
||||||
"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
|
"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:
|
case WPA_PARAM_SAE_PWE:
|
||||||
sm->sae_pwe = value;
|
sm->sae_pwe = value;
|
||||||
break;
|
break;
|
||||||
|
case WPA_PARAM_DENY_PTK0_REKEY:
|
||||||
|
sm->wpa_deny_ptk0_rekey = value;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ struct wpa_sm_ctx {
|
||||||
void (*set_state)(void *ctx, enum wpa_states state);
|
void (*set_state)(void *ctx, enum wpa_states state);
|
||||||
enum wpa_states (*get_state)(void *ctx);
|
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,
|
int (*set_key)(void *ctx, enum wpa_alg alg,
|
||||||
const u8 *addr, int key_idx, int set_tx,
|
const u8 *addr, int key_idx, int set_tx,
|
||||||
const u8 *seq, size_t seq_len,
|
const u8 *seq, size_t seq_len,
|
||||||
|
@ -100,6 +101,7 @@ enum wpa_sm_conf_params {
|
||||||
WPA_PARAM_MFP,
|
WPA_PARAM_MFP,
|
||||||
WPA_PARAM_OCV,
|
WPA_PARAM_OCV,
|
||||||
WPA_PARAM_SAE_PWE,
|
WPA_PARAM_SAE_PWE,
|
||||||
|
WPA_PARAM_DENY_PTK0_REKEY,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rsn_supp_config {
|
struct rsn_supp_config {
|
||||||
|
@ -111,6 +113,7 @@ struct rsn_supp_config {
|
||||||
const u8 *ssid;
|
const u8 *ssid;
|
||||||
size_t ssid_len;
|
size_t ssid_len;
|
||||||
int wpa_ptk_rekey;
|
int wpa_ptk_rekey;
|
||||||
|
int wpa_deny_ptk0_rekey;
|
||||||
int p2p;
|
int p2p;
|
||||||
int wpa_rsc_relaxation;
|
int wpa_rsc_relaxation;
|
||||||
int owe_ptk_workaround;
|
int owe_ptk_workaround;
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct wpa_sm {
|
||||||
u8 ssid[32];
|
u8 ssid[32];
|
||||||
size_t ssid_len;
|
size_t ssid_len;
|
||||||
int wpa_ptk_rekey;
|
int wpa_ptk_rekey;
|
||||||
|
int wpa_deny_ptk0_rekey:1;
|
||||||
int p2p;
|
int p2p;
|
||||||
int wpa_rsc_relaxation;
|
int wpa_rsc_relaxation;
|
||||||
int owe_ptk_workaround;
|
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);
|
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)
|
static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm)
|
||||||
{
|
{
|
||||||
WPA_ASSERT(sm->ctx->get_network_ctx);
|
WPA_ASSERT(sm->ctx->get_network_ctx);
|
||||||
|
|
|
@ -345,6 +345,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
bss->isolate = !wpa_s->conf->p2p_intra_bss;
|
bss->isolate = !wpa_s->conf->p2p_intra_bss;
|
||||||
bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
|
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) {
|
if (ssid->p2p_group) {
|
||||||
os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
|
os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
|
||||||
|
|
|
@ -2495,6 +2495,7 @@ static const struct parse_data ssid_fields[] = {
|
||||||
{ INT(dot11MeshHoldingTimeout) },
|
{ INT(dot11MeshHoldingTimeout) },
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
{ INT(wpa_ptk_rekey) },
|
{ INT(wpa_ptk_rekey) },
|
||||||
|
{ INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) },
|
||||||
{ INT(group_rekey) },
|
{ INT(group_rekey) },
|
||||||
{ STR(bgscan) },
|
{ STR(bgscan) },
|
||||||
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
|
{ 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->pairwise_cipher = DEFAULT_PAIRWISE;
|
||||||
ssid->group_cipher = DEFAULT_GROUP;
|
ssid->group_cipher = DEFAULT_GROUP;
|
||||||
ssid->key_mgmt = DEFAULT_KEY_MGMT;
|
ssid->key_mgmt = DEFAULT_KEY_MGMT;
|
||||||
|
ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
|
||||||
ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
|
ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD;
|
||||||
ssid->ht = 1;
|
ssid->ht = 1;
|
||||||
#ifdef IEEE8021X_EAPOL
|
#ifdef IEEE8021X_EAPOL
|
||||||
|
|
|
@ -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);
|
INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD);
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
INT(wpa_ptk_rekey);
|
INT(wpa_ptk_rekey);
|
||||||
|
INT(wpa_deny_ptk0_rekey);
|
||||||
INT(group_rekey);
|
INT(group_rekey);
|
||||||
INT(ignore_broadcast_ssid);
|
INT(ignore_broadcast_ssid);
|
||||||
#ifdef CONFIG_DPP
|
#ifdef CONFIG_DPP
|
||||||
|
|
|
@ -553,6 +553,19 @@ struct wpa_ssid {
|
||||||
*/
|
*/
|
||||||
int wpa_ptk_rekey;
|
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
|
* group_rekey - Group rekeying time in seconds
|
||||||
*
|
*
|
||||||
|
|
|
@ -8108,6 +8108,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
|
||||||
|
|
||||||
wpa_s->no_keep_alive = 0;
|
wpa_s->no_keep_alive = 0;
|
||||||
wpa_s->own_disconnect_req = 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);
|
os_free(wpa_s->disallow_aps_bssid);
|
||||||
wpa_s->disallow_aps_bssid = NULL;
|
wpa_s->disallow_aps_bssid = NULL;
|
||||||
|
|
|
@ -2895,6 +2895,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
|
||||||
#endif /* CONFIG_AP */
|
#endif /* CONFIG_AP */
|
||||||
|
|
||||||
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
|
||||||
|
wpa_s->own_reconnect_req = 0;
|
||||||
|
|
||||||
ft_completed = wpa_ft_is_completed(wpa_s->wpa);
|
ft_completed = wpa_ft_is_completed(wpa_s->wpa);
|
||||||
if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
|
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 &&
|
if (wpa_s->wpa_state == WPA_COMPLETED &&
|
||||||
wpa_s->current_ssid &&
|
wpa_s->current_ssid &&
|
||||||
wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
|
wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
|
||||||
!locally_generated &&
|
(wpa_s->own_reconnect_req ||
|
||||||
disconnect_reason_recoverable(reason_code)) {
|
(!locally_generated &&
|
||||||
|
disconnect_reason_recoverable(reason_code)))) {
|
||||||
/*
|
/*
|
||||||
* It looks like the AP has dropped association with
|
* It looks like the AP has dropped association with
|
||||||
* us, but could allow us to get back in. Try to
|
* us, but could allow us to get back in. This is also
|
||||||
* reconnect to the same BSS without full scan to save
|
* triggered for cases where local reconnection request
|
||||||
* time for some common cases.
|
* 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 = wpa_s->current_bss;
|
||||||
fast_reconnect_ssid = wpa_s->current_ssid;
|
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);
|
wpa_supplicant_req_scan(wpa_s, 0, 100000);
|
||||||
else
|
} else {
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new "
|
wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new "
|
||||||
"immediate scan");
|
"immediate scan");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not "
|
wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not "
|
||||||
"try to re-connect");
|
"try to re-connect");
|
||||||
|
|
|
@ -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,
|
static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr,
|
||||||
const u8 *psk)
|
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->mlme_setprotection = supp_mlme_setprotection;
|
||||||
ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
|
ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
|
||||||
ctx->deauthenticate = supp_deauthenticate;
|
ctx->deauthenticate = supp_deauthenticate;
|
||||||
|
ctx->reconnect = supp_reconnect;
|
||||||
peer->supp = wpa_sm_init(ctx);
|
peer->supp = wpa_sm_init(ctx);
|
||||||
if (peer->supp == NULL) {
|
if (peer->supp == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
|
wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
|
||||||
|
|
|
@ -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,
|
static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
|
||||||
const void *data, u16 data_len,
|
const void *data, u16 data_len,
|
||||||
size_t *msg_len, void **data_pos)
|
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->set_config_blob = wpa_supplicant_set_config_blob;
|
||||||
ctx->get_config_blob = wpa_supplicant_get_config_blob;
|
ctx->get_config_blob = wpa_supplicant_get_config_blob;
|
||||||
ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
|
ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
|
||||||
|
ctx->reconnect = _wpa_supplicant_reconnect;
|
||||||
|
|
||||||
wpa_s->wpa = wpa_sm_init(ctx);
|
wpa_s->wpa = wpa_sm_init(ctx);
|
||||||
assert(wpa_s->wpa != NULL);
|
assert(wpa_s->wpa != NULL);
|
||||||
|
|
|
@ -1441,6 +1441,7 @@ static const char *network_fields[] = {
|
||||||
"dot11MeshHoldingTimeout",
|
"dot11MeshHoldingTimeout",
|
||||||
#endif /* CONFIG_MESH */
|
#endif /* CONFIG_MESH */
|
||||||
"wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
|
"wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
|
||||||
|
"wpa_deny_ptk0_rekey",
|
||||||
"enable_edmg", "edmg_channel",
|
"enable_edmg", "edmg_channel",
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
"go_p2p_dev_addr", "p2p_client_list", "psk_list",
|
"go_p2p_dev_addr", "p2p_client_list", "psk_list",
|
||||||
|
|
|
@ -1760,6 +1760,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
||||||
} else
|
} else
|
||||||
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2057,6 +2071,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
||||||
int rand_style;
|
int rand_style;
|
||||||
|
|
||||||
wpa_s->own_disconnect_req = 0;
|
wpa_s->own_disconnect_req = 0;
|
||||||
|
wpa_s->own_reconnect_req = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are starting a new connection, any previously pending EAPOL
|
* 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);
|
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,
|
static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_ssid *ssid)
|
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
|
* There is no point in blacklisting the AP if this event is
|
||||||
* generated based on local request to disconnect.
|
* 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_s->own_disconnect_req = 0;
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
"Ignore connection failure due to local request to disconnect");
|
"Ignore connection failure due to local request to disconnect");
|
||||||
|
|
|
@ -1101,6 +1101,32 @@ fast_reauth=1
|
||||||
# wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
|
# 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.
|
# 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
|
# group_rekey: Group rekeying time in seconds. This value, if non-zero, is used
|
||||||
# as the dot11RSNAConfigGroupRekeyTime parameter when operating in
|
# as the dot11RSNAConfigGroupRekeyTime parameter when operating in
|
||||||
# Authenticator role in IBSS, or in AP and mesh modes.
|
# Authenticator role in IBSS, or in AP and mesh modes.
|
||||||
|
|
|
@ -554,6 +554,7 @@ struct wpa_supplicant {
|
||||||
|
|
||||||
/* Selected configuration (based on Beacon/ProbeResp WPA IE) */
|
/* Selected configuration (based on Beacon/ProbeResp WPA IE) */
|
||||||
int pairwise_cipher;
|
int pairwise_cipher;
|
||||||
|
int deny_ptk0_rekey;
|
||||||
int group_cipher;
|
int group_cipher;
|
||||||
int key_mgmt;
|
int key_mgmt;
|
||||||
int wpa_proto;
|
int wpa_proto;
|
||||||
|
@ -1071,6 +1072,7 @@ struct wpa_supplicant {
|
||||||
unsigned int wmm_ac_supported:1;
|
unsigned int wmm_ac_supported:1;
|
||||||
unsigned int ext_work_in_progress:1;
|
unsigned int ext_work_in_progress:1;
|
||||||
unsigned int own_disconnect_req:1;
|
unsigned int own_disconnect_req:1;
|
||||||
|
unsigned int own_reconnect_req:1;
|
||||||
unsigned int ignore_post_flush_scan_res:1;
|
unsigned int ignore_post_flush_scan_res:1;
|
||||||
|
|
||||||
#define MAC_ADDR_RAND_SCAN BIT(0)
|
#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_cancel_auth_timeout(struct wpa_supplicant *wpa_s);
|
||||||
void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
|
void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
|
||||||
u16 reason_code);
|
u16 reason_code);
|
||||||
|
void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
struct wpa_ssid * wpa_supplicant_add_network(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);
|
int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id);
|
||||||
|
|
|
@ -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)
|
static void * wpa_supplicant_get_network_ctx(void *wpa_s)
|
||||||
{
|
{
|
||||||
return wpa_supplicant_get_ssid(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)
|
static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
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->cert_in_cb = wpa_s->conf->cert_in_cb;
|
||||||
ctx->status_cb = wpa_supplicant_status_cb;
|
ctx->status_cb = wpa_supplicant_status_cb;
|
||||||
ctx->eap_error_cb = wpa_supplicant_eap_error_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->set_anon_id = wpa_supplicant_set_anon_id;
|
||||||
ctx->cb_ctx = wpa_s;
|
ctx->cb_ctx = wpa_s;
|
||||||
wpa_s->eapol = eapol_sm_init(ctx);
|
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->set_state = _wpa_supplicant_set_state;
|
||||||
ctx->get_state = _wpa_supplicant_get_state;
|
ctx->get_state = _wpa_supplicant_get_state;
|
||||||
ctx->deauthenticate = _wpa_supplicant_deauthenticate;
|
ctx->deauthenticate = _wpa_supplicant_deauthenticate;
|
||||||
|
ctx->reconnect = _wpa_supplicant_reconnect;
|
||||||
ctx->set_key = wpa_supplicant_set_key;
|
ctx->set_key = wpa_supplicant_set_key;
|
||||||
ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
|
ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
|
||||||
ctx->get_bssid = wpa_supplicant_get_bssid;
|
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 = ssid->ssid;
|
||||||
conf.ssid_len = ssid->ssid_len;
|
conf.ssid_len = ssid->ssid_len;
|
||||||
conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
|
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;
|
conf.owe_ptk_workaround = ssid->owe_ptk_workaround;
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (ssid->p2p_group && wpa_s->current_bss &&
|
if (ssid->p2p_group && wpa_s->current_bss &&
|
||||||
|
|
Loading…
Reference in a new issue