From 1f90a49d028debceb748ab91b7685ae774451e8f Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 10 Jan 2020 23:19:09 +0100 Subject: [PATCH] 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 --- src/eapol_supp/eapol_supp_sm.c | 14 ++++++++++++++ src/eapol_supp/eapol_supp_sm.h | 9 +++++++++ src/rsn_supp/wpa.c | 18 ++++++++++++++++++ src/rsn_supp/wpa.h | 3 +++ 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 | 13 +++++++++++++ wpa_supplicant/ctrl_iface.c | 2 ++ wpa_supplicant/events.c | 19 ++++++++++++------- wpa_supplicant/ibss_rsn.c | 7 +++++++ wpa_supplicant/preauth_test.c | 7 +++++++ wpa_supplicant/wpa_cli.c | 1 + wpa_supplicant/wpa_supplicant.c | 26 +++++++++++++++++++++++++- wpa_supplicant/wpa_supplicant.conf | 26 ++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ wpa_supplicant/wpas_glue.c | 23 +++++++++++++++++++++++ 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 f1ca0a859..a34cc0be2 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 c9d7522d5..67f82c60a 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 1e209ada5..263e2108a 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 e14f26e01..0bd14495a 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 bd4446402..7af678dcd 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 d1002d225..bbd8f05fd 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 9dad4ff72..938165465 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 29bd81f0a..d453ca541 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 5642d0ddf..ac08ad863 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 c9074a239..10c096129 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 e3fce8f72..2851ffc81 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 37368c4cb..d14304011 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 a73282841..7ed5860f0 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 6d3f56a87..490e77c96 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 7e06a22f6..634fb290e 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 d587bd340..15121c386 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 219568a7f..de2e6350b 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 e8747e613..5ddefce08 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 &&