From ca682f80a947c260bd9a1440c18e71af7944e07a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 23 Jul 2022 13:41:36 +0300 Subject: [PATCH] DPP: Dynamic Controller initiated connection on Relay Accept an incoming TCP connection from a Controller in a Relay that is configured with dpp_relay_port even if that Controller is not configured with a dpp_controller parameter. This allows more dynamic Controller initiated operations, e.g., when using mDNS to discover a Relay. This type of a dynamic Controller entry will not be used for exchanges that are initiated by an Enrollee (i.e., based on a DPP Public Action frame received by the Relay). Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 4 +- src/common/dpp.h | 3 +- src/common/dpp_i.h | 7 +++ src/common/dpp_tcp.c | 128 +++++++++++++++++++++++++++++++++---------- 4 files changed, 110 insertions(+), 32 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 32885ea7d..a0c6ab15b 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -3353,6 +3353,7 @@ static int hostapd_dpp_add_controllers(struct hostapd_data *hapd) struct dpp_relay_config config; os_memset(&config, 0, sizeof(config)); + config.msg_ctx = hapd->msg_ctx; config.cb_ctx = hapd; config.tx = hostapd_dpp_relay_tx; config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx; @@ -3366,7 +3367,8 @@ static int hostapd_dpp_add_controllers(struct hostapd_data *hapd) if (hapd->conf->dpp_relay_port) dpp_relay_listen(hapd->iface->interfaces->dpp, - hapd->conf->dpp_relay_port); + hapd->conf->dpp_relay_port, + &config); #endif /* CONFIG_DPP2 */ return 0; diff --git a/src/common/dpp.h b/src/common/dpp.h index d5f1f58e8..8eae58d73 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -749,7 +749,8 @@ struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp, const u8 *kid); int dpp_relay_add_controller(struct dpp_global *dpp, struct dpp_relay_config *config); -int dpp_relay_listen(struct dpp_global *dpp, int port); +int dpp_relay_listen(struct dpp_global *dpp, int port, + struct dpp_relay_config *config); void dpp_relay_stop_listen(struct dpp_global *dpp); int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq, diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index bdffc9d71..dfa4a3cb8 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -19,9 +19,16 @@ struct dpp_global { struct dl_list configurator; /* struct dpp_configurator */ #ifdef CONFIG_DPP2 struct dl_list controllers; /* struct dpp_relay_controller */ + struct dpp_relay_controller *tmp_controller; struct dpp_controller *controller; struct dl_list tcp_init; /* struct dpp_connection */ int relay_sock; + void *relay_msg_ctx; + void *relay_cb_ctx; + void (*relay_tx)(void *ctx, const u8 *addr, unsigned int freq, + const u8 *msg, size_t len); + void (*relay_gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token, + int prot, struct wpabuf *buf); void *cb_ctx; int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth); diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index fc5dfb973..84eab997a 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -211,6 +211,11 @@ dpp_relay_controller_get_addr(struct dpp_global *dpp, return ctrl; } + if (dpp->tmp_controller && + dpp->tmp_controller->ipaddr.af == AF_INET && + addr->sin_addr.s_addr == dpp->tmp_controller->ipaddr.u.v4.s_addr) + return dpp->tmp_controller; + return NULL; } @@ -548,6 +553,31 @@ static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr, } +static struct dpp_connection * +dpp_relay_match_ctrl(struct dpp_relay_controller *ctrl, const u8 *src, + unsigned int freq, u8 type) +{ + struct dpp_connection *conn; + + dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) { + if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0) + return conn; + if ((type == DPP_PA_PKEX_EXCHANGE_RESP || + type == DPP_PA_AUTHENTICATION_RESP) && + conn->freq == 0 && + is_broadcast_ether_addr(conn->mac_addr)) { + wpa_printf(MSG_DEBUG, + "DPP: Associate this peer to the new Controller initiated connection"); + os_memcpy(conn->mac_addr, src, ETH_ALEN); + conn->freq = freq; + return conn; + } + } + + return NULL; +} + + int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq, const u8 *i_bootstrap, const u8 *r_bootstrap, @@ -566,24 +596,16 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, type != DPP_PA_RECONFIG_ANNOUNCEMENT) { dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, list) { - dl_list_for_each(conn, &ctrl->conn, - struct dpp_connection, list) { - if (os_memcmp(src, conn->mac_addr, - ETH_ALEN) == 0) - return dpp_relay_tx(conn, hdr, buf, len); - if ((type == DPP_PA_PKEX_EXCHANGE_RESP || - type == DPP_PA_AUTHENTICATION_RESP) && - conn->freq == 0 && - is_broadcast_ether_addr(conn->mac_addr)) { - wpa_printf(MSG_DEBUG, - "DPP: Associate this peer to the new Controller initiated connection"); - os_memcpy(conn->mac_addr, src, - ETH_ALEN); - conn->freq = freq; - return dpp_relay_tx(conn, hdr, buf, - len); - } - } + conn = dpp_relay_match_ctrl(ctrl, src, freq, type); + if (conn) + return dpp_relay_tx(conn, hdr, buf, len); + } + + if (dpp->tmp_controller) { + conn = dpp_relay_match_ctrl(dpp->tmp_controller, src, + freq, type); + if (conn) + return dpp_relay_tx(conn, hdr, buf, len); } } @@ -619,11 +641,25 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, } +static struct dpp_connection * +dpp_relay_find_conn(struct dpp_relay_controller *ctrl, const u8 *src) +{ + struct dpp_connection *conn; + + dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) { + if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0) + return conn; + } + + return NULL; +} + + int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, size_t data_len) { struct dpp_relay_controller *ctrl; - struct dpp_connection *conn, *found = NULL; + struct dpp_connection *conn = NULL; struct wpabuf *msg; /* Check if there is a successfully completed authentication for this @@ -631,19 +667,15 @@ int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, */ dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, list) { - if (found) + conn = dpp_relay_find_conn(ctrl, src); + if (conn) break; - dl_list_for_each(conn, &ctrl->conn, - struct dpp_connection, list) { - if (os_memcmp(src, conn->mac_addr, - ETH_ALEN) == 0) { - found = conn; - break; - } - } } - if (!found) + if (!conn && dpp->tmp_controller) + conn = dpp_relay_find_conn(dpp->tmp_controller, src); + + if (!conn) return -1; msg = wpabuf_alloc(4 + 1 + data_len); @@ -2326,6 +2358,11 @@ void dpp_relay_flush_controllers(struct dpp_global *dpp) dl_list_del(&ctrl->list); dpp_relay_controller_free(ctrl); } + + if (dpp->tmp_controller) { + dpp_relay_controller_free(dpp->tmp_controller); + dpp->tmp_controller = NULL; + } } @@ -2351,6 +2388,32 @@ static void dpp_relay_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); ctrl = dpp_relay_controller_get_addr(dpp, &addr); + if (!ctrl && dpp->tmp_controller && + dl_list_len(&dpp->tmp_controller->conn)) { + char txt[100]; + + wpa_printf(MSG_DEBUG, + "DPP: Remove a temporaty Controller entry for %s", + hostapd_ip_txt(&dpp->tmp_controller->ipaddr, + txt, sizeof(txt))); + dpp_relay_controller_free(dpp->tmp_controller); + dpp->tmp_controller = NULL; + } + if (!ctrl && !dpp->tmp_controller) { + wpa_printf(MSG_DEBUG, "DPP: Add a temporary Controller entry"); + ctrl = os_zalloc(sizeof(*ctrl)); + if (!ctrl) + goto fail; + dl_list_init(&ctrl->conn); + ctrl->global = dpp; + ctrl->ipaddr.af = AF_INET; + ctrl->ipaddr.u.v4.s_addr = addr.sin_addr.s_addr; + ctrl->msg_ctx = dpp->relay_msg_ctx; + ctrl->cb_ctx = dpp->relay_cb_ctx; + ctrl->tx = dpp->relay_tx; + ctrl->gas_resp_tx = dpp->relay_gas_resp_tx; + dpp->tmp_controller = ctrl; + } if (!ctrl) { wpa_printf(MSG_DEBUG, "DPP: No Controller found for that address"); @@ -2396,7 +2459,8 @@ fail: } -int dpp_relay_listen(struct dpp_global *dpp, int port) +int dpp_relay_listen(struct dpp_global *dpp, int port, + struct dpp_relay_config *config) { int s; int on = 1; @@ -2451,6 +2515,10 @@ int dpp_relay_listen(struct dpp_global *dpp, int port) } dpp->relay_sock = s; + dpp->relay_msg_ctx = config->msg_ctx; + dpp->relay_cb_ctx = config->cb_ctx; + dpp->relay_tx = config->tx; + dpp->relay_gas_resp_tx = config->gas_resp_tx; wpa_printf(MSG_DEBUG, "DPP: Relay started on TCP port %d", port); return 0; }