diff --git a/src/common/dpp.c b/src/common/dpp.c index dc66ce913..2cf1f6a13 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -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; diff --git a/src/common/dpp.h b/src/common/dpp.h index 58a220dc6..cff996095 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -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); diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index b7d9294e3..9994c67cd 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -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; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 68846e63d..b065ff721 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -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);