]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Fix connection result reporting when using TCP
authorJouni Malinen <quic_jouni@quicinc.com>
Fri, 28 Jan 2022 15:28:49 +0000 (17:28 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 28 Jan 2022 15:28:49 +0000 (17:28 +0200)
The TCP code path did not handle the postponed connection attempt on TX
status and the following result message from the Enrollee to the
Configurator. Fix this by adding TCP-versions of these operations to
match the way wpa_supplicant implemented this for the Public Action
frames.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
src/ap/dpp_hostapd.c
src/common/dpp.c
src/common/dpp.h
src/common/dpp_i.h
src/common/dpp_tcp.c
wpa_supplicant/dpp_supplicant.c

index 6239bebe5800004cbe8d9c4881650499187b30e2..96a13fb6fb1eabc48c0bb3720669f840700c502a 100644 (file)
@@ -2,6 +2,7 @@
  * hostapd / DPP integration
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -340,7 +341,7 @@ static int hostapd_dpp_pkex_done(void *ctx, void *conn,
 
        return dpp_tcp_auth(hapd->iface->interfaces->dpp, conn, auth,
                            hapd->conf->dpp_name, DPP_NETROLE_AP,
-                           hostapd_dpp_process_conf_obj);
+                           hostapd_dpp_process_conf_obj, NULL);
 }
 #endif /* CONFIG_DPP2 */
 
@@ -922,7 +923,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
                return dpp_tcp_init(hapd->iface->interfaces->dpp, auth,
                                    &ipaddr, tcp_port, hapd->conf->dpp_name,
                                    DPP_NETROLE_AP, hapd->msg_ctx, hapd,
-                                   hostapd_dpp_process_conf_obj);
+                                   hostapd_dpp_process_conf_obj, NULL);
 #endif /* CONFIG_DPP2 */
 
        hapd->dpp_auth = auth;
index ac6eae4c893edb5bfcf469951d7287cf44331c41..77964f2644355b8dac6296eca57898356174ce91 100644 (file)
@@ -2,6 +2,7 @@
  * DPP functionality shared between hostapd and wpa_supplicant
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
index ca488f391587d52ee7e19981d7fe0fe4b996545f..83f3d94afc019cedf407be70a34c5a055011f787 100644 (file)
@@ -2,6 +2,7 @@
  * DPP functionality shared between hostapd and wpa_supplicant
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -402,6 +403,7 @@ struct dpp_controller_config {
        void *msg_ctx;
        void *cb_ctx;
        int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+       bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
 };
 
 #ifdef CONFIG_TESTING_OPTIONS
@@ -703,12 +705,21 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
                 const char *name, enum dpp_netrole netrole, void *msg_ctx,
                 void *cb_ctx,
                 int (*process_conf_obj)(void *ctx,
-                                        struct dpp_authentication *auth));
+                                        struct dpp_authentication *auth),
+                bool (*tcp_msg_sent)(void *ctx,
+                                     struct dpp_authentication *auth));
 int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
                 struct dpp_authentication *auth, const char *name,
                 enum dpp_netrole netrole,
                 int (*process_conf_obj)(void *ctx,
-                                        struct dpp_authentication *auth));
+                                        struct dpp_authentication *auth),
+                bool (*tcp_msg_sent)(void *ctx,
+                                     struct dpp_authentication *auth));
+bool dpp_tcp_conn_status_requested(struct dpp_global *dpp);
+void dpp_tcp_send_conn_status(struct dpp_global *dpp,
+                             enum dpp_status_error result,
+                             const u8 *ssid, size_t ssid_len,
+                             const char *channel_list);
 
 struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi);
 void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src,
index c00b1ee41240184668478121e783ad5c4921a606..0f31ae56a5261ad604675fe6e89335e9206fabce 100644 (file)
@@ -2,6 +2,7 @@
  * DPP module internal definitions
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -22,6 +23,7 @@ struct dpp_global {
        struct dl_list tcp_init; /* struct dpp_connection */
        void *cb_ctx;
        int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+       bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
        void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi);
 #endif /* CONFIG_DPP2 */
 };
index 1a8a7c7d5677e863710cde287b0fbac9c1c5da2f..14ff2d9030804410c66630c0613771dba13ff680 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * DPP over TCP
  * Copyright (c) 2019-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -30,6 +31,7 @@ struct dpp_connection {
        void *cb_ctx;
        int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
        int (*pkex_done)(void *ctx, void *conn, struct dpp_bootstrap_info *bi);
+       bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
        int sock;
        u8 mac_addr[ETH_ALEN];
        unsigned int freq;
@@ -79,6 +81,7 @@ struct dpp_controller {
        void *msg_ctx;
        void *cb_ctx;
        int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
+       bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
 };
 
 static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
@@ -245,6 +248,10 @@ static int dpp_tcp_send(struct dpp_connection *conn)
                                dpp_controller_rx, conn, NULL) == 0)
                conn->read_eloop = 1;
        if (conn->on_tcp_tx_complete_remove) {
+               if (conn->auth && conn->auth->connect_on_tx_status &&
+                   conn->tcp_msg_sent &&
+                   conn->tcp_msg_sent(conn->cb_ctx, conn->auth))
+                       return 0;
                dpp_connection_remove(conn);
        } else if (conn->auth && (conn->ctrl || conn->auth->configurator) &&
                   conn->on_tcp_tx_complete_gas_done) {
@@ -781,6 +788,7 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
                wpa_msg(msg_ctx, MSG_INFO,
                        DPP_EVENT_CONF_SENT "wait_conn_status=1");
                wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
+               auth->waiting_conn_status_result = 1;
                eloop_cancel_timeout(
                        dpp_controller_conn_status_result_wait_timeout,
                        conn, NULL);
@@ -1697,6 +1705,7 @@ static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
        conn->msg_ctx = ctrl->msg_ctx;
        conn->cb_ctx = ctrl->cb_ctx;
        conn->process_conf_obj = ctrl->process_conf_obj;
+       conn->tcp_msg_sent = ctrl->tcp_msg_sent;
        conn->sock = fd;
        conn->netrole = ctrl->netrole;
 
@@ -1821,7 +1830,9 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
                 const struct hostapd_ip_addr *addr, int port, const char *name,
                 enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx,
                 int (*process_conf_obj)(void *ctx,
-                                        struct dpp_authentication *auth))
+                                        struct dpp_authentication *auth),
+                bool (*tcp_msg_sent)(void *ctx,
+                                     struct dpp_authentication *auth))
 {
        struct dpp_connection *conn;
        struct sockaddr_storage saddr;
@@ -1845,6 +1856,7 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
        conn->msg_ctx = msg_ctx;
        conn->cb_ctx = cb_ctx;
        conn->process_conf_obj = process_conf_obj;
+       conn->tcp_msg_sent = tcp_msg_sent;
        conn->name = os_strdup(name ? name : "Test");
        conn->netrole = netrole;
        conn->global = dpp;
@@ -1894,13 +1906,16 @@ int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
                 struct dpp_authentication *auth, const char *name,
                 enum dpp_netrole netrole,
                 int (*process_conf_obj)(void *ctx,
-                                        struct dpp_authentication *auth))
+                                        struct dpp_authentication *auth),
+                bool (*tcp_msg_sent)(void *ctx,
+                                     struct dpp_authentication *auth))
 {
        struct dpp_connection *conn = _conn;
 
        /* Continue with Authentication exchange on an existing TCP connection.
         */
        conn->process_conf_obj = process_conf_obj;
+       conn->tcp_msg_sent = tcp_msg_sent;
        os_free(conn->name);
        conn->name = os_strdup(name ? name : "Test");
        conn->netrole = netrole;
@@ -1939,6 +1954,7 @@ int dpp_controller_start(struct dpp_global *dpp,
        ctrl->msg_ctx = config->msg_ctx;
        ctrl->cb_ctx = config->cb_ctx;
        ctrl->process_conf_obj = config->process_conf_obj;
+       ctrl->tcp_msg_sent = config->tcp_msg_sent;
 
        ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
        if (ctrl->sock < 0)
@@ -2116,4 +2132,65 @@ void dpp_relay_flush_controllers(struct dpp_global *dpp)
        }
 }
 
+
+bool dpp_tcp_conn_status_requested(struct dpp_global *dpp)
+{
+       struct dpp_connection *conn;
+
+       dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
+               if (conn->auth && conn->auth->conn_status_requested)
+                       return true;
+       }
+
+       return false;
+}
+
+
+static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn,
+                                        enum dpp_status_error result,
+                                        const u8 *ssid, size_t ssid_len,
+                                        const char *channel_list)
+{
+       struct dpp_authentication *auth = conn->auth;
+       int res;
+       struct wpabuf *msg;
+
+       auth->conn_status_requested = 0;
+
+       msg = dpp_build_conn_status_result(auth, result, ssid, ssid_len,
+                                          channel_list);
+       if (!msg) {
+               dpp_connection_remove(conn);
+               return;
+       }
+
+       res = dpp_tcp_send_msg(conn, msg);
+       wpabuf_free(msg);
+
+       if (res < 0) {
+               dpp_connection_remove(conn);
+               return;
+       }
+
+       /* This exchange will be terminated in the TX status handler */
+       conn->on_tcp_tx_complete_remove = 1;
+}
+
+
+void dpp_tcp_send_conn_status(struct dpp_global *dpp,
+                             enum dpp_status_error result,
+                             const u8 *ssid, size_t ssid_len,
+                             const char *channel_list)
+{
+       struct dpp_connection *conn;
+
+       dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
+               if (conn->auth && conn->auth->conn_status_requested) {
+                       dpp_tcp_send_conn_status_msg(conn, result, ssid,
+                                                    ssid_len, channel_list);
+                       break;
+               }
+       }
+}
+
 #endif /* CONFIG_DPP2 */
index b8c7a671206a7483b670484b48af0da87842801b..acd8521c36e79e82c47f153de0a7c9b77e11f37c 100644 (file)
@@ -2,6 +2,7 @@
  * wpa_supplicant - DPP
  * Copyright (c) 2017, Qualcomm Atheros, Inc.
  * Copyright (c) 2018-2020, The Linux Foundation
+ * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -53,6 +54,7 @@ static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
 static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s);
 static int wpas_dpp_process_conf_obj(void *ctx,
                                     struct dpp_authentication *auth);
+static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth);
 #endif /* CONFIG_DPP2 */
 
 static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -295,7 +297,8 @@ static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx,
        struct dpp_authentication *auth = wpa_s->dpp_auth;
        enum dpp_status_error result;
 
-       if (!auth || !auth->conn_status_requested)
+       if ((!auth || !auth->conn_status_requested) &&
+           !dpp_tcp_conn_status_requested(wpa_s->dpp))
                return;
 
        wpa_printf(MSG_DEBUG,
@@ -371,9 +374,10 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
 
        eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
 
-       if (!auth || !auth->conn_status_requested)
+       if ((!auth || !auth->conn_status_requested) &&
+           !dpp_tcp_conn_status_requested(wpa_s->dpp))
                return;
-       auth->conn_status_requested = 0;
+
        wpa_printf(MSG_DEBUG, "DPP: Report connection status result %d",
                   result);
 
@@ -382,6 +386,19 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s,
                channel_list = channel_list_buf;
        }
 
+       if (!auth || !auth->conn_status_requested) {
+               dpp_tcp_send_conn_status(wpa_s->dpp, result,
+                                        ssid ? ssid->ssid :
+                                        wpa_s->dpp_last_ssid,
+                                        ssid ? ssid->ssid_len :
+                                        wpa_s->dpp_last_ssid_len,
+                                        channel_list);
+               os_free(channel_list_buf);
+               return;
+       }
+
+       auth->conn_status_requested = 0;
+
        msg = dpp_build_conn_status_result(auth, result,
                                           ssid ? ssid->ssid :
                                           wpa_s->dpp_last_ssid,
@@ -416,7 +433,8 @@ void wpas_dpp_connected(struct wpa_supplicant *wpa_s)
 {
        struct dpp_authentication *auth = wpa_s->dpp_auth;
 
-       if (auth && auth->conn_status_requested)
+       if ((auth && auth->conn_status_requested) ||
+           dpp_tcp_conn_status_requested(wpa_s->dpp))
                wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_OK);
 }
 
@@ -874,7 +892,8 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
        if (tcp)
                return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port,
                                    wpa_s->conf->dpp_name, DPP_NETROLE_STA,
-                                   wpa_s, wpa_s, wpas_dpp_process_conf_obj);
+                                   wpa_s, wpa_s, wpas_dpp_process_conf_obj,
+                                   wpas_dpp_tcp_msg_sent);
 #endif /* CONFIG_DPP2 */
 
        wpa_s->dpp_auth = auth;
@@ -2028,6 +2047,34 @@ static int wpas_dpp_process_conf_obj(void *ctx,
 }
 
 
+static bool wpas_dpp_tcp_msg_sent(void *ctx, struct dpp_authentication *auth)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+
+       wpa_printf(MSG_DEBUG, "DPP: TCP message sent callback");
+
+       if (auth->connect_on_tx_status) {
+               auth->connect_on_tx_status = 0;
+               wpa_printf(MSG_DEBUG,
+                          "DPP: Try to connect after completed configuration result");
+               wpas_dpp_try_to_connect(wpa_s);
+               if (auth->conn_status_requested) {
+                       wpa_printf(MSG_DEBUG,
+                                  "DPP: Start 15 second timeout for reporting connection status result");
+                       eloop_cancel_timeout(
+                               wpas_dpp_conn_status_result_timeout,
+                               wpa_s, NULL);
+                       eloop_register_timeout(
+                               15, 0, wpas_dpp_conn_status_result_timeout,
+                               wpa_s, NULL);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
 static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi)
 {
        struct wpa_supplicant *wpa_s = ctx;
@@ -2617,7 +2664,8 @@ static int wpas_dpp_pkex_done(void *ctx, void *conn,
        }
 
        return dpp_tcp_auth(wpa_s->dpp, conn, auth, wpa_s->conf->dpp_name,
-                           DPP_NETROLE_STA, wpas_dpp_process_conf_obj);
+                           DPP_NETROLE_STA, wpas_dpp_process_conf_obj,
+                           wpas_dpp_tcp_msg_sent);
 }
 #endif /* CONFIG_DPP2 */
 
@@ -3641,6 +3689,7 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd)
        config.msg_ctx = wpa_s;
        config.cb_ctx = wpa_s;
        config.process_conf_obj = wpas_dpp_process_conf_obj;
+       config.tcp_msg_sent = wpas_dpp_tcp_msg_sent;
        if (cmd) {
                pos = os_strstr(cmd, " tcp_port=");
                if (pos) {