]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP2: Add an automatic peer_bi entry for CSR matching if needed
authorJouni Malinen <jouni@codeaurora.org>
Thu, 18 Jun 2020 21:08:33 +0000 (00:08 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 18 Jun 2020 21:13:48 +0000 (00:13 +0300)
This allows the DPP_CA_SET command to be targeting a specific DPP-CST
event in cases where the Configurator did not receive the bootstrapping
information for the peer.

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

index dc66ce913c9da36ccd9b7e0382a2962edaf1c7ab..2cf1f6a1351211a76ff1cbd1efe77c0a8983d4b6 100644 (file)
@@ -1293,9 +1293,14 @@ void dpp_auth_deinit(struct dpp_authentication *auth)
        wpabuf_free(auth->cacert);
        wpabuf_free(auth->certbag);
        os_free(auth->trusted_eap_server_name);
+       wpabuf_free(auth->conf_resp_tcp);
 #endif /* CONFIG_DPP2 */
        wpabuf_free(auth->net_access_key);
        dpp_bootstrap_info_free(auth->tmp_own_bi);
+       if (auth->tmp_peer_bi) {
+               dl_list_del(&auth->tmp_peer_bi->list);
+               dpp_bootstrap_info_free(auth->tmp_peer_bi);
+       }
 #ifdef CONFIG_TESTING_OPTIONS
        os_free(auth->config_obj_override);
        os_free(auth->discovery_override);
@@ -2044,6 +2049,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
        cert_req = json_get_member_base64(root, "pkcs10");
        if (cert_req) {
                char *txt;
+               int id;
 
                wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req);
                if (dpp_validate_csr(auth, cert_req) < 0) {
@@ -2051,13 +2057,31 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
                        auth->force_conf_resp_status = DPP_STATUS_CSR_BAD;
                        goto cont;
                }
+
+               if (auth->peer_bi) {
+                       id = auth->peer_bi->id;
+               } else if (auth->tmp_peer_bi) {
+                       id = auth->tmp_peer_bi->id;
+               } else {
+                       struct dpp_bootstrap_info *bi;
+
+                       bi = os_zalloc(sizeof(*bi));
+                       if (!bi)
+                               goto fail;
+                       bi->id = dpp_next_id(auth->global);
+                       dl_list_add(&auth->global->bootstrap, &bi->list);
+                       auth->tmp_peer_bi = bi;
+                       id = bi->id;
+               }
+
                wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA");
                txt = base64_encode_no_lf(wpabuf_head(cert_req),
                                          wpabuf_len(cert_req), NULL);
                if (!txt)
                        goto fail;
+
                wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_CSR "peer=%d csr=%s",
-                       auth->peer_bi ? (int) auth->peer_bi->id : -1, txt);
+                       id, txt);
                os_free(txt);
                auth->waiting_csr = false;
                auth->waiting_cert = true;
index 58a220dc6ca3e43d8e95defa27b69e97d36dc6d5..cff996095cc0f491e833f4b4aba6e6610e3fb941 100644 (file)
@@ -244,6 +244,7 @@ struct dpp_authentication {
        struct dpp_bootstrap_info *peer_bi;
        struct dpp_bootstrap_info *own_bi;
        struct dpp_bootstrap_info *tmp_own_bi;
+       struct dpp_bootstrap_info *tmp_peer_bi;
        u8 waiting_pubkey_hash[SHA256_MAC_LEN];
        int response_pending;
        int reconfig;
@@ -298,6 +299,7 @@ struct dpp_authentication {
        bool reconfig_success;
        struct wpabuf *conf_req;
        const struct wpabuf *conf_resp; /* owned by GAS server */
+       struct wpabuf *conf_resp_tcp;
        struct dpp_configuration *conf_ap;
        struct dpp_configuration *conf2_ap;
        struct dpp_configuration *conf_sta;
@@ -660,6 +662,8 @@ int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
 int dpp_controller_start(struct dpp_global *dpp,
                         struct dpp_controller_config *config);
 void dpp_controller_stop(struct dpp_global *dpp);
+struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
+                                                   unsigned int id);
 int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
                 const struct hostapd_ip_addr *addr, int port,
                 const char *name);
index b7d9294e34aa6ef8a400d035c6cc62671377db69..9994c67cda2d238df2997419759081a1745f057c 100644 (file)
@@ -40,7 +40,6 @@ struct dpp_connection {
        unsigned int on_tcp_tx_complete_auth_ok:1;
        unsigned int gas_comeback_in_progress:1;
        u8 gas_dialog_token;
-       struct wpabuf *gas_resp;
        char *name;
 };
 
@@ -91,7 +90,6 @@ static void dpp_connection_free(struct dpp_connection *conn)
        eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
        wpabuf_free(conn->msg);
        wpabuf_free(conn->msg_out);
-       wpabuf_free(conn->gas_resp);
        dpp_auth_deinit(conn->auth);
        os_free(conn->name);
        os_free(conn);
@@ -1148,7 +1146,7 @@ static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn,
                return -1;
        }
 
-       if (!conn->gas_resp) {
+       if (!auth->conf_resp_tcp) {
                wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
                return dpp_tcp_send_comeback_delay(conn,
                                                   WLAN_PA_GAS_COMEBACK_RESP);
@@ -1156,8 +1154,8 @@ static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn,
 
        wpa_printf(MSG_DEBUG,
                   "DPP: Configuration response is ready to be sent out");
-       resp = conn->gas_resp;
-       conn->gas_resp = NULL;
+       resp = auth->conf_resp_tcp;
+       auth->conf_resp_tcp = NULL;
        return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_COMEBACK_RESP, resp);
 }
 
@@ -1665,6 +1663,28 @@ void dpp_controller_stop(struct dpp_global *dpp)
 }
 
 
+struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
+                                                   unsigned int id)
+{
+       struct dpp_controller *ctrl = dpp->controller;
+       struct dpp_connection *conn;
+
+       if (!ctrl)
+               return NULL;
+
+       dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
+               struct dpp_authentication *auth = conn->auth;
+
+               if (auth &&
+                   ((auth->peer_bi && auth->peer_bi->id == id) ||
+                    (auth->tmp_peer_bi && auth->tmp_peer_bi->id == id)))
+                       return auth;
+       }
+
+       return NULL;
+}
+
+
 void dpp_tcp_init_flush(struct dpp_global *dpp)
 {
        struct dpp_connection *conn, *tmp;
index 68846e63d47ba5184b4b54ef3d178e6a8bb93840..b065ff7217c6a758ff6ec658101dc80602fb4eb3 100644 (file)
@@ -3632,7 +3632,7 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 
 
 static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
-                                   struct dpp_authentication *auth)
+                                   struct dpp_authentication *auth, bool tcp)
 {
        struct wpabuf *resp;
 
@@ -3640,6 +3640,12 @@ static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
                                   auth->e_netrole, true);
        if (!resp)
                return -1;
+
+       if (tcp) {
+               auth->conf_resp_tcp = resp;
+               return 0;
+       }
+
        if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx,
                                resp) < 0) {
                wpa_printf(MSG_DEBUG,
@@ -3654,12 +3660,23 @@ static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s,
 
 int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
 {
-       int peer;
+       int peer = -1;
        const char *pos, *value;
        struct dpp_authentication *auth = wpa_s->dpp_auth;
        u8 *bin;
        size_t bin_len;
        struct wpabuf *buf;
+       bool tcp = false;
+
+       pos = os_strstr(cmd, " peer=");
+       if (pos) {
+               peer = atoi(pos + 6);
+               if (!auth || !auth->waiting_cert ||
+                   (unsigned int) peer != auth->peer_bi->id) {
+                       auth = dpp_controller_get_auth(wpa_s->dpp, peer);
+                       tcp = true;
+               }
+       }
 
        if (!auth || !auth->waiting_cert) {
                wpa_printf(MSG_DEBUG,
@@ -3667,14 +3684,13 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
                return -1;
        }
 
-       pos = os_strstr(cmd, " peer=");
-       if (pos) {
-               peer = atoi(pos + 6);
-               if (!auth->peer_bi ||
-                   (unsigned int) peer != auth->peer_bi->id) {
-                       wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
-                       return -1;
-               }
+       if (peer >= 0 &&
+           (!auth->peer_bi ||
+            (unsigned int) peer != auth->peer_bi->id) &&
+           (!auth->tmp_peer_bi ||
+            (unsigned int) peer != auth->tmp_peer_bi->id)) {
+               wpa_printf(MSG_DEBUG, "DPP: Peer mismatch");
+               return -1;
        }
 
        pos = os_strstr(cmd, " value=");
@@ -3689,7 +3705,7 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
 
        if (os_strncmp(pos, "status ", 7) == 0) {
                auth->force_conf_resp_status = atoi(value);
-               return wpas_dpp_build_conf_resp(wpa_s, auth);
+               return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
        }
 
        if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) {
@@ -3713,7 +3729,7 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd)
        if (os_strncmp(pos, "certBag ", 8) == 0) {
                wpabuf_free(auth->certbag);
                auth->certbag = buf;
-               return wpas_dpp_build_conf_resp(wpa_s, auth);
+               return wpas_dpp_build_conf_resp(wpa_s, auth, tcp);
        }
 
        wpabuf_free(buf);