]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP2: Connection status result (Configurator)
authorJouni Malinen <jouni@codeaurora.org>
Sun, 15 Sep 2019 13:19:45 +0000 (16:19 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 16 Sep 2019 14:13:46 +0000 (17:13 +0300)
A new argument to the DPP_AUTH_INIT command (conn_status=1) can now be
used to set Configurator to request a station Enrollee to report
connection result after a successfully completed provisioning step. If
the peer supports this, the DPP-CONF-SENT event indicates this with a
new argument (wait_conn_status=1) and the Configurator remains waiting
for the connection result for up to 16 seconds.

Once the Enrollee reports the result, a new DPP-CONN-STATUS-RESULT event
is generated with arguments result, ssid, and channel_list indicating
what the Enrollee reported. result=0 means success while non-zero codes
are for various error cases as specified in the DPP tech spec. If no
report is received from the Enrollee, the event with "timeout" argument
is generated locally.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/ap/dpp_hostapd.c
src/common/dpp.c
src/common/dpp.h
src/common/wpa_ctrl.h
wpa_supplicant/dpp_supplicant.c

index 697c3bad34ab366d428a8d49c2e16938f37b5d75..6c3e11e2df65a8286f4c17f9d694e732d1794ea2 100644 (file)
@@ -922,6 +922,24 @@ static void hostapd_dpp_config_result_wait_timeout(void *eloop_ctx,
 }
 
 
+static void hostapd_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
+                                                       void *timeout_ctx)
+{
+       struct hostapd_data *hapd = eloop_ctx;
+       struct dpp_authentication *auth = hapd->dpp_auth;
+
+       if (!auth || !auth->waiting_conf_result)
+               return;
+
+       wpa_printf(MSG_DEBUG,
+                  "DPP: Timeout while waiting for Connection Status Result");
+       wpa_msg(hapd->msg_ctx, MSG_INFO,
+               DPP_EVENT_CONN_STATUS_RESULT "timeout");
+       dpp_auth_deinit(auth);
+       hapd->dpp_auth = NULL;
+}
+
+
 static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
                                       const u8 *hdr, const u8 *buf, size_t len)
 {
@@ -945,6 +963,20 @@ static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
 
        status = dpp_conf_result_rx(auth, hdr, buf, len);
 
+       if (status == DPP_STATUS_OK && auth->send_conn_status) {
+               wpa_msg(hapd->msg_ctx, MSG_INFO,
+                       DPP_EVENT_CONF_SENT "wait_conn_status=1");
+               wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
+               eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout,
+                                    hapd, NULL);
+               eloop_cancel_timeout(
+                       hostapd_dpp_conn_status_result_wait_timeout,
+                       hapd, NULL);
+               eloop_register_timeout(
+                       16, 0, hostapd_dpp_conn_status_result_wait_timeout,
+                       hapd, NULL);
+               return;
+       }
        hostapd_drv_send_action_cancel_wait(hapd);
        hostapd_dpp_listen_stop(hapd);
        if (status == DPP_STATUS_OK)
@@ -957,6 +989,41 @@ static void hostapd_dpp_rx_conf_result(struct hostapd_data *hapd, const u8 *src,
                             NULL);
 }
 
+
+static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd,
+                                             const u8 *src, const u8 *hdr,
+                                             const u8 *buf, size_t len)
+{
+       struct dpp_authentication *auth = hapd->dpp_auth;
+       enum dpp_status_error status;
+       u8 ssid[SSID_MAX_LEN];
+       size_t ssid_len = 0;
+       char *channel_list = NULL;
+
+       wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
+
+       if (!auth || !auth->waiting_conn_status_result) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: No DPP Configuration waiting for connection status result - drop");
+               return;
+       }
+
+       status = dpp_conn_status_result_rx(auth, hdr, buf, len,
+                                          ssid, &ssid_len, &channel_list);
+       wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
+               "result=%d ssid=%s channel_list=%s",
+               status, wpa_ssid_txt(ssid, ssid_len),
+               channel_list ? channel_list : "N/A");
+       os_free(channel_list);
+       hostapd_drv_send_action_cancel_wait(hapd);
+       hostapd_dpp_listen_stop(hapd);
+       dpp_auth_deinit(auth);
+       hapd->dpp_auth = NULL;
+       eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout,
+                            hapd, NULL);
+}
+
+
 #endif /* CONFIG_DPP2 */
 
 
@@ -1403,6 +1470,9 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
        case DPP_PA_CONFIGURATION_RESULT:
                hostapd_dpp_rx_conf_result(hapd, src, hdr, buf, len);
                break;
+       case DPP_PA_CONNECTION_STATUS_RESULT:
+               hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len);
+               break;
 #endif /* CONFIG_DPP2 */
        default:
                wpa_printf(MSG_DEBUG,
@@ -1715,6 +1785,8 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd)
 #ifdef CONFIG_DPP2
        eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd,
                             NULL);
+       eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd,
+                            NULL);
 #endif /* CONFIG_DPP2 */
        dpp_auth_deinit(hapd->dpp_auth);
        hapd->dpp_auth = NULL;
index 5500cb24cec097eccbf7ad40b42ce6e2296e705f..ca84bea91612aff0bb0f8d58d60b2d99757125df 100644 (file)
@@ -4446,6 +4446,12 @@ int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx,
                }
        }
 
+       pos = os_strstr(cmd, " conn_status=");
+       if (pos) {
+               pos += 13;
+               auth->send_conn_status = atoi(pos);
+       }
+
        if (dpp_configuration_parse(auth, cmd) < 0) {
                wpa_msg(msg_ctx, MSG_INFO,
                        "DPP: Failed to set configurator parameters");
@@ -4861,10 +4867,12 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
        status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
        auth->conf_resp_status = status;
 
-       /* { E-nonce, configurationObject}ke */
+       /* { E-nonce, configurationObject[, sendConnStatus]}ke */
        clear_len = 4 + e_nonce_len;
        if (conf)
                clear_len += 4 + wpabuf_len(conf);
+       if (auth->peer_version >= 2 && auth->send_conn_status && !ap)
+               clear_len += 4;
        clear = wpabuf_alloc(clear_len);
        attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE;
 #ifdef CONFIG_TESTING_OPTIONS
@@ -4913,6 +4921,12 @@ skip_e_nonce:
                wpabuf_put_buf(clear, conf);
        }
 
+       if (auth->peer_version >= 2 && auth->send_conn_status && !ap) {
+               wpa_printf(MSG_DEBUG, "DPP: sendConnStatus");
+               wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS);
+               wpabuf_put_le16(clear, 0);
+       }
+
 #ifdef CONFIG_TESTING_OPTIONS
 skip_config_obj:
        if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) {
@@ -6148,6 +6162,135 @@ fail:
        return NULL;
 }
 
+
+static int valid_channel_list(const char *val)
+{
+       while (*val) {
+               if (!((*val >= '0' && *val <= '9') ||
+                     *val == '/' || *val == ','))
+                       return 0;
+               val++;
+       }
+
+       return 1;
+}
+
+
+enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth,
+                                               const u8 *hdr,
+                                               const u8 *attr_start,
+                                               size_t attr_len,
+                                               u8 *ssid, size_t *ssid_len,
+                                               char **channel_list)
+{
+       const u8 *wrapped_data, *status, *e_nonce;
+       u16 wrapped_data_len, status_len, e_nonce_len;
+       const u8 *addr[2];
+       size_t len[2];
+       u8 *unwrapped = NULL;
+       size_t unwrapped_len = 0;
+       enum dpp_status_error ret = 256;
+       struct json_token *root = NULL, *token;
+
+       *ssid_len = 0;
+       *channel_list = NULL;
+
+       wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
+                                   &wrapped_data_len);
+       if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
+               dpp_auth_fail(auth,
+                             "Missing or invalid required Wrapped Data attribute");
+               goto fail;
+       }
+       wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
+                   wrapped_data, wrapped_data_len);
+
+       attr_len = wrapped_data - 4 - attr_start;
+
+       addr[0] = hdr;
+       len[0] = DPP_HDR_LEN;
+       addr[1] = attr_start;
+       len[1] = attr_len;
+       wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
+       wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
+       wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
+                   wrapped_data, wrapped_data_len);
+       unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
+       unwrapped = os_malloc(unwrapped_len);
+       if (!unwrapped)
+               goto fail;
+       if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
+                           wrapped_data, wrapped_data_len,
+                           2, addr, len, unwrapped) < 0) {
+               dpp_auth_fail(auth, "AES-SIV decryption failed");
+               goto fail;
+       }
+       wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
+                   unwrapped, unwrapped_len);
+
+       if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
+               dpp_auth_fail(auth, "Invalid attribute in unwrapped data");
+               goto fail;
+       }
+
+       e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
+                              DPP_ATTR_ENROLLEE_NONCE,
+                              &e_nonce_len);
+       if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
+               dpp_auth_fail(auth,
+                             "Missing or invalid Enrollee Nonce attribute");
+               goto fail;
+       }
+       wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
+       if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
+               dpp_auth_fail(auth, "Enrollee Nonce mismatch");
+               wpa_hexdump(MSG_DEBUG, "DPP: Expected Enrollee Nonce",
+                           auth->e_nonce, e_nonce_len);
+               goto fail;
+       }
+
+       status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONN_STATUS,
+                             &status_len);
+       if (!status) {
+               dpp_auth_fail(auth,
+                             "Missing required DPP Connection Status attribute");
+               goto fail;
+       }
+       wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON",
+                         status, status_len);
+
+       root = json_parse((const char *) status, status_len);
+       if (!root) {
+               dpp_auth_fail(auth, "Could not parse connStatus");
+               goto fail;
+       }
+
+       token = json_get_member(root, "ssid");
+       if (token && token->type == JSON_STRING &&
+           os_strlen(token->string) <= SSID_MAX_LEN) {
+               *ssid_len = os_strlen(token->string);
+               os_memcpy(ssid, token->string, *ssid_len);
+       }
+
+       token = json_get_member(root, "channelList");
+       if (token && token->type == JSON_STRING &&
+           valid_channel_list(token->string))
+               *channel_list = os_strdup(token->string);
+
+       token = json_get_member(root, "result");
+       if (!token || token->type != JSON_NUMBER) {
+               dpp_auth_fail(auth, "No connStatus - result");
+               goto fail;
+       }
+       wpa_printf(MSG_DEBUG, "DPP: result %d", token->number);
+       ret = token->number;
+
+fail:
+       json_free(root);
+       bin_clear_free(unwrapped, unwrapped_len);
+       return ret;
+}
+
 #endif /* CONFIG_DPP2 */
 
 
@@ -8721,6 +8864,10 @@ int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id,
 
 #ifdef CONFIG_DPP2
 
+static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
+                                                          void *timeout_ctx);
+
+
 static void dpp_connection_free(struct dpp_connection *conn)
 {
        if (conn->sock >= 0) {
@@ -8730,6 +8877,8 @@ static void dpp_connection_free(struct dpp_connection *conn)
                eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
                close(conn->sock);
        }
+       eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout,
+                            conn, NULL);
        wpabuf_free(conn->msg);
        wpabuf_free(conn->msg_out);
        dpp_auth_deinit(conn->auth);
@@ -9454,6 +9603,22 @@ static int dpp_controller_rx_auth_conf(struct dpp_connection *conn,
 }
 
 
+static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
+                                                          void *timeout_ctx)
+{
+       struct dpp_connection *conn = eloop_ctx;
+
+       if (!conn->auth->waiting_conf_result)
+               return;
+
+       wpa_printf(MSG_DEBUG,
+                  "DPP: Timeout while waiting for Connection Status Result");
+       wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
+               DPP_EVENT_CONN_STATUS_RESULT "timeout");
+       dpp_connection_remove(conn);
+}
+
+
 static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
                                         const u8 *hdr, const u8 *buf,
                                         size_t len)
@@ -9473,6 +9638,18 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
        }
 
        status = dpp_conf_result_rx(auth, hdr, buf, len);
+       if (status == DPP_STATUS_OK && auth->send_conn_status) {
+               wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
+                       DPP_EVENT_CONF_SENT "wait_conn_status=1");
+               wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
+               eloop_cancel_timeout(
+                       dpp_controller_conn_status_result_wait_timeout,
+                       conn, NULL);
+               eloop_register_timeout(
+                       16, 0, dpp_controller_conn_status_result_wait_timeout,
+                       conn, NULL);
+               return 0;
+       }
        if (status == DPP_STATUS_OK)
                wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
                        DPP_EVENT_CONF_SENT);
@@ -9483,6 +9660,39 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
 }
 
 
+static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn,
+                                               const u8 *hdr, const u8 *buf,
+                                               size_t len)
+{
+       struct dpp_authentication *auth = conn->auth;
+       enum dpp_status_error status;
+       u8 ssid[SSID_MAX_LEN];
+       size_t ssid_len = 0;
+       char *channel_list = NULL;
+
+       if (!conn->ctrl)
+               return 0;
+
+       wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
+
+       if (!auth || !auth->waiting_conn_status_result) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: No DPP Configuration waiting for connection status result - drop");
+               return -1;
+       }
+
+       status = dpp_conn_status_result_rx(auth, hdr, buf, len,
+                                          ssid, &ssid_len, &channel_list);
+       wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO,
+               DPP_EVENT_CONN_STATUS_RESULT
+               "result=%d ssid=%s channel_list=%s",
+               status, wpa_ssid_txt(ssid, ssid_len),
+               channel_list ? channel_list : "N/A");
+       os_free(channel_list);
+       return -1; /* to remove the completed connection */
+}
+
+
 static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
                                    size_t len)
 {
@@ -9530,6 +9740,9 @@ static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
                return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos);
        case DPP_PA_CONFIGURATION_RESULT:
                return dpp_controller_rx_conf_result(conn, msg, pos, end - pos);
+       case DPP_PA_CONNECTION_STATUS_RESULT:
+               return dpp_controller_rx_conn_status_result(conn, msg, pos,
+                                                           end - pos);
        default:
                /* TODO: missing messages types */
                wpa_printf(MSG_DEBUG,
index 7e8d9554f690d979aa6dcdfa978586198d2c57a5..fa3fd76a097aa96d6796dbda46b2f1ec0c5b04bb 100644 (file)
@@ -226,6 +226,7 @@ struct dpp_authentication {
        int remove_on_tx_status;
        int connect_on_tx_status;
        int waiting_conf_result;
+       int waiting_conn_status_result;
        int auth_success;
        struct wpabuf *conf_req;
        const struct wpabuf *conf_resp; /* owned by GAS server */
@@ -242,6 +243,7 @@ struct dpp_authentication {
        struct wpabuf *net_access_key;
        os_time_t net_access_key_expiry;
        struct wpabuf *c_sign_key;
+       int send_conn_status;
 #ifdef CONFIG_TESTING_OPTIONS
        char *config_obj_override;
        char *discovery_override;
@@ -443,6 +445,12 @@ enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth,
                                         const u8 *attr_start, size_t attr_len);
 struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth,
                                      enum dpp_status_error status);
+enum dpp_status_error dpp_conn_status_result_rx(struct dpp_authentication *auth,
+                                               const u8 *hdr,
+                                               const u8 *attr_start,
+                                               size_t attr_len,
+                                               u8 *ssid, size_t *ssid_len,
+                                               char **channel_list);
 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
                              size_t len);
 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len);
index b24ae63e59ea1ba1a604efb764a40b2f19603ca5..70ecf5d82720f8fb1e703cc81f4f100988366cd5 100644 (file)
@@ -168,6 +168,7 @@ extern "C" {
 #define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED "
 #define DPP_EVENT_CONF_SENT "DPP-CONF-SENT "
 #define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED "
+#define DPP_EVENT_CONN_STATUS_RESULT "DPP-CONN-STATUS-RESULT "
 #define DPP_EVENT_CONFOBJ_AKM "DPP-CONFOBJ-AKM "
 #define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID "
 #define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS "
index 1f65658eff76bf971b35fa8456b03fc59d61fdff..b9f46708c117557e3493dd5f8428650e68e6c516 100644 (file)
@@ -1270,6 +1270,24 @@ static void wpas_dpp_config_result_wait_timeout(void *eloop_ctx,
 }
 
 
+static void wpas_dpp_conn_status_result_wait_timeout(void *eloop_ctx,
+                                                    void *timeout_ctx)
+{
+       struct wpa_supplicant *wpa_s = eloop_ctx;
+       struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+       if (!auth || !auth->waiting_conn_status_result)
+               return;
+
+       wpa_printf(MSG_DEBUG,
+                  "DPP: Timeout while waiting for Connection Status Result");
+       wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout");
+       wpas_dpp_listen_stop(wpa_s);
+       dpp_auth_deinit(auth);
+       wpa_s->dpp_auth = NULL;
+}
+
+
 static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
                                    const u8 *hdr, const u8 *buf, size_t len)
 {
@@ -1293,6 +1311,23 @@ static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
 
        status = dpp_conf_result_rx(auth, hdr, buf, len);
 
+       if (status == DPP_STATUS_OK && auth->send_conn_status) {
+               wpa_msg(wpa_s, MSG_INFO,
+                       DPP_EVENT_CONF_SENT "wait_conn_status=1");
+               wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
+               eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout,
+                                    wpa_s, NULL);
+               auth->waiting_conn_status_result = 1;
+               eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
+                                    wpa_s, NULL);
+               eloop_register_timeout(16, 0,
+                                      wpas_dpp_conn_status_result_wait_timeout,
+                                      wpa_s, NULL);
+               offchannel_send_action_done(wpa_s);
+               wpas_dpp_listen_start(wpa_s, auth->neg_freq ? auth->neg_freq :
+                                     auth->curr_freq);
+               return;
+       }
        offchannel_send_action_done(wpa_s);
        wpas_dpp_listen_stop(wpa_s);
        if (status == DPP_STATUS_OK)
@@ -1305,6 +1340,40 @@ static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
 }
 
 
+static void wpas_dpp_rx_conn_status_result(struct wpa_supplicant *wpa_s,
+                                          const u8 *src, const u8 *hdr,
+                                          const u8 *buf, size_t len)
+{
+       struct dpp_authentication *auth = wpa_s->dpp_auth;
+       enum dpp_status_error status;
+       u8 ssid[SSID_MAX_LEN];
+       size_t ssid_len = 0;
+       char *channel_list = NULL;
+
+       wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
+
+       if (!auth || !auth->waiting_conn_status_result) {
+               wpa_printf(MSG_DEBUG,
+                          "DPP: No DPP Configuration waiting for connection status result - drop");
+               return;
+       }
+
+       status = dpp_conn_status_result_rx(auth, hdr, buf, len,
+                                          ssid, &ssid_len, &channel_list);
+       wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
+               "result=%d ssid=%s channel_list=%s",
+               status, wpa_ssid_txt(ssid, ssid_len),
+               channel_list ? channel_list : "N/A");
+       os_free(channel_list);
+       offchannel_send_action_done(wpa_s);
+       wpas_dpp_listen_stop(wpa_s);
+       dpp_auth_deinit(auth);
+       wpa_s->dpp_auth = NULL;
+       eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
+                            wpa_s, NULL);
+}
+
+
 static int wpas_dpp_process_conf_obj(void *ctx,
                                     struct dpp_authentication *auth)
 {
@@ -1848,6 +1917,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
        case DPP_PA_CONFIGURATION_RESULT:
                wpas_dpp_rx_conf_result(wpa_s, src, hdr, buf, len);
                break;
+       case DPP_PA_CONNECTION_STATUS_RESULT:
+               wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len);
+               break;
 #endif /* CONFIG_DPP2 */
        default:
                wpa_printf(MSG_DEBUG,
@@ -2294,6 +2366,8 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
        eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
 #ifdef CONFIG_DPP2
        eloop_cancel_timeout(wpas_dpp_config_result_wait_timeout, wpa_s, NULL);
+       eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout,
+                            wpa_s, NULL);
        dpp_pfs_free(wpa_s->dpp_pfs);
        wpa_s->dpp_pfs = NULL;
 #endif /* CONFIG_DPP2 */