]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
STA: Allow PTK rekeying without Ext KeyID to be disabled as a workaround
authorAlexander Wetzel <alexander@wetzel-home.de>
Fri, 10 Jan 2020 22:19:09 +0000 (23:19 +0100)
committerJouni Malinen <j@w1.fi>
Sun, 23 Feb 2020 11:05:19 +0000 (13:05 +0200)
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>
18 files changed:
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/ap.c
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/config_ssid.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/events.c
wpa_supplicant/ibss_rsn.c
wpa_supplicant/preauth_test.c
wpa_supplicant/wpa_cli.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wpa_supplicant_i.h
wpa_supplicant/wpas_glue.c

index f1ca0a859bde22874f63afe066ec0b7db5991380..a34cc0be297231a90602eae3f739e0c89b33008c 100644 (file)
@@ -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) {
index c9d7522d5f4e8c23451ec5cfcf006f6cc2b84aff..67f82c60ae338552deb9ece9e1df82710f6f82f7 100644 (file)
@@ -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);
 };
 
 
index 1e209ada59207fbc2b451826b1856e4ea6cedf6c..263e2108a00e6c643a4769b4b14d7a9397ca5759 100644 (file)
@@ -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;
        }
index e14f26e01ec558837fe157d0114f0a673acb5cd3..0bd14495aebe9b3ff29e351ad700435b6f44a3bb 100644 (file)
@@ -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;
index bd44464023bfb5fd333bbe94a253c9735b5bfd6c..7af678dcd93d88578cd811ea400f0a4ab1b2b826 100644 (file)
@@ -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);
index d1002d225584377417c3b2a482858e11809e536a..bbd8f05fd6e5ff73abcb7bb9b3a56d57750fac9f 100644 (file)
@@ -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);
index 9dad4ff7231d9667313de1de2d3e5bc80851aa29..938165465d823b820fa1042502eba6cc193928a0 100644 (file)
@@ -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
index 29bd81f0a8ff6286fb3fd0ccdeca87af1c434043..d453ca5410668f7e141126f16eb8be505f5eb493 100644 (file)
@@ -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
index 5642d0ddf98f80aca23ce3b29c6bfc30eb028881..ac08ad86345b1db956ba855779698e239ebc025c 100644 (file)
@@ -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
         *
index c9074a239ff9c1eca603b923a4cd89c94a515055..10c09612979021f577081b243a28b8bf8ae33205 100644 (file)
@@ -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;
index e3fce8f72689dcf8da1c067a2dee49b942af9dad..2851ffc810198e7213169050b10fc5d4a23c0aac 100644 (file)
@@ -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");
index 37368c4cb388146802ddd33dc9ddc393d3b2b0ff..d143040119cf3504139127ca645ae9d139c71736 100644 (file)
@@ -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");
index a73282841f7e460e6a42b806bcbbb4f50739d363..7ed5860f0b21c8728af2bf6b4915f82dd1ffca81 100644 (file)
@@ -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);
index 6d3f56a8728e763869f394247693940844746570..490e77c962dd81bb26dc60666905bc7fd7c54e67 100644 (file)
@@ -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",
index 7e06a22f6806176214e58480a43b2666c0d381e8..634fb290e0cbc38db90c441eec617dbde4409824 100644 (file)
@@ -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");
index d587bd340332846fdaea19c4834d8458d5cf1233..15121c3869dd2dab8e5ebeb6efc8f45bc0a55291 100644 (file)
@@ -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.
index 219568a7f25315049138d53d89c7607ca5fbaf25..de2e6350b8aa6ba39c98cea473a9ba9d78b6dec1 100644 (file)
@@ -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);
index e8747e613a3078e2f90b407d30bb3d4c232a1ce7..5ddefce0828ff1245094313279a03a4f4b580404 100644 (file)
@@ -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 &&