diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 42f3b40ef..3f61cb625 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2376,6 +2376,36 @@ fail: #endif /* CONFIG_SAE */ +#ifdef CONFIG_DPP2 +static int hostapd_dpp_controller_parse(struct hostapd_bss_config *bss, + const char *pos) +{ + struct dpp_controller_conf *conf; + char *val; + + conf = os_zalloc(sizeof(*conf)); + if (!conf) + return -1; + val = get_param(pos, "ipaddr="); + if (!val || hostapd_parse_ip_addr(val, &conf->ipaddr)) + goto fail; + os_free(val); + val = get_param(pos, "pkhash="); + if (!val || os_strlen(val) != 2 * SHA256_MAC_LEN || + hexstr2bin(val, conf->pkhash, SHA256_MAC_LEN) < 0) + goto fail; + os_free(val); + conf->next = bss->dpp_controller; + bss->dpp_controller = conf; + return 0; +fail: + os_free(val); + os_free(conf); + return -1; +} +#endif /* CONFIG_DPP2 */ + + static int hostapd_config_fill(struct hostapd_config *conf, struct hostapd_bss_config *bss, const char *buf, char *pos, int line) @@ -4298,6 +4328,11 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "dpp_csign") == 0) { if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos)) return 1; +#ifdef CONFIG_DPP2 + } else if (os_strcmp(buf, "dpp_controller") == 0) { + if (hostapd_dpp_controller_parse(bss, pos)) + return 1; +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #ifdef CONFIG_OWE } else if (os_strcmp(buf, "owe_transition_bssid") == 0) { diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index e640e9984..07b818eb3 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -559,6 +559,20 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf) } +#ifdef CONFIG_DPP2 +static void hostapd_dpp_controller_conf_free(struct dpp_controller_conf *conf) +{ + struct dpp_controller_conf *prev; + + while (conf) { + prev = conf; + conf = conf->next; + os_free(prev); + } +} +#endif /* CONFIG_DPP2 */ + + void hostapd_config_free_bss(struct hostapd_bss_config *conf) { if (conf == NULL) @@ -740,6 +754,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) os_free(conf->dpp_connector); wpabuf_free(conf->dpp_netaccesskey); wpabuf_free(conf->dpp_csign); +#ifdef CONFIG_DPP2 + hostapd_dpp_controller_conf_free(conf->dpp_controller); +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ hostapd_config_free_sae_passwords(conf); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 509677a45..19eda67e1 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -15,6 +15,7 @@ #include "common/wpa_common.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" +#include "crypto/sha256.h" #include "wps/wps.h" #include "fst/fst.h" #include "vlan.h" @@ -252,6 +253,12 @@ struct sae_password_entry { int vlan_id; }; +struct dpp_controller_conf { + struct dpp_controller_conf *next; + u8 pkhash[SHA256_MAC_LEN]; + struct hostapd_ip_addr ipaddr; +}; + /** * struct hostapd_bss_config - Per-BSS configuration */ @@ -692,6 +699,9 @@ struct hostapd_bss_config { struct wpabuf *dpp_netaccesskey; unsigned int dpp_netaccesskey_expiry; struct wpabuf *dpp_csign; +#ifdef CONFIG_DPP2 + struct dpp_controller_conf *dpp_controller; +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #ifdef CONFIG_OWE diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 75edbc909..697c3bad3 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -16,6 +16,7 @@ #include "hostapd.h" #include "ap_drv_ops.h" #include "gas_query_ap.h" +#include "gas_serv.h" #include "wpa_auth.h" #include "dpp_hostapd.h" @@ -557,6 +558,14 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, * received hash values */ dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap, r_bootstrap, &own_bi, &peer_bi); +#ifdef CONFIG_DPP2 + if (!own_bi) { + if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, + src, hdr, buf, len, freq, i_bootstrap, + r_bootstrap) == 0) + return; + } +#endif /* CONFIG_DPP2 */ if (!own_bi) { wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "No matching own bootstrapping key found - ignore message"); @@ -1357,6 +1366,12 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR " freq=%u type=%d", MAC2STR(src), freq, type); +#ifdef CONFIG_DPP2 + if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, + src, hdr, buf, len, freq, NULL, NULL) == 0) + return; +#endif /* CONFIG_DPP2 */ + switch (type) { case DPP_PA_AUTHENTICATION_REQ: hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq); @@ -1410,7 +1425,8 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, struct wpabuf * hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, - const u8 *query, size_t query_len) + const u8 *query, size_t query_len, + const u8 *data, size_t data_len) { struct dpp_authentication *auth = hapd->dpp_auth; struct wpabuf *resp; @@ -1418,6 +1434,13 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); if (!auth || !auth->auth_success || os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { +#ifdef CONFIG_DPP2 + if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data, + data_len) == 0) { + /* Response will be forwarded once received over TCP */ + return NULL; + } +#endif /* CONFIG_DPP2 */ wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return NULL; } @@ -1609,11 +1632,67 @@ void hostapd_dpp_stop(struct hostapd_data *hapd) } +#ifdef CONFIG_DPP2 + +static void hostapd_dpp_relay_tx(void *ctx, const u8 *addr, unsigned int freq, + const u8 *msg, size_t len) +{ + struct hostapd_data *hapd = ctx; + u8 *buf; + + wpa_printf(MSG_DEBUG, "DPP: Send action frame dst=" MACSTR " freq=%u", + MAC2STR(addr), freq); + buf = os_malloc(2 + len); + if (!buf) + return; + buf[0] = WLAN_ACTION_PUBLIC; + buf[1] = WLAN_PA_VENDOR_SPECIFIC; + os_memcpy(buf + 2, msg, len); + hostapd_drv_send_action(hapd, freq, 0, addr, buf, 2 + len); + os_free(buf); +} + + +static void hostapd_dpp_relay_gas_resp_tx(void *ctx, const u8 *addr, + u8 dialog_token, int prot, + struct wpabuf *buf) +{ + struct hostapd_data *hapd = ctx; + + gas_serv_req_dpp_processing(hapd, addr, dialog_token, prot, buf); +} + +#endif /* CONFIG_DPP2 */ + + +static int hostapd_dpp_add_controllers(struct hostapd_data *hapd) +{ +#ifdef CONFIG_DPP2 + struct dpp_controller_conf *ctrl; + struct dpp_relay_config config; + + os_memset(&config, 0, sizeof(config)); + config.cb_ctx = hapd; + config.tx = hostapd_dpp_relay_tx; + config.gas_resp_tx = hostapd_dpp_relay_gas_resp_tx; + for (ctrl = hapd->conf->dpp_controller; ctrl; ctrl = ctrl->next) { + config.ipaddr = &ctrl->ipaddr; + config.pkhash = ctrl->pkhash; + if (dpp_relay_add_controller(hapd->iface->interfaces->dpp, + &config) < 0) + return -1; + } +#endif /* CONFIG_DPP2 */ + + return 0; +} + + int hostapd_dpp_init(struct hostapd_data *hapd) { hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE; hapd->dpp_init_done = 1; - return 0; + return hostapd_dpp_add_controllers(hapd); } diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h index 449ca16d1..c1ec5d70e 100644 --- a/src/ap/dpp_hostapd.h +++ b/src/ap/dpp_hostapd.h @@ -19,7 +19,8 @@ void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst, const u8 *data, size_t data_len, int ok); struct wpabuf * hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, - const u8 *query, size_t query_len); + const u8 *query, size_t query_len, + const u8 *data, size_t data_len); void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok); int hostapd_dpp_configurator_add(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id); diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c index a7df81032..9567e202a 100644 --- a/src/ap/gas_serv.c +++ b/src/ap/gas_serv.c @@ -1522,9 +1522,9 @@ static void gas_serv_req_local_processing(struct hostapd_data *hapd, #ifdef CONFIG_DPP -static void gas_serv_req_dpp_processing(struct hostapd_data *hapd, - const u8 *sa, u8 dialog_token, - int prot, struct wpabuf *buf) +void gas_serv_req_dpp_processing(struct hostapd_data *hapd, + const u8 *sa, u8 dialog_token, + int prot, struct wpabuf *buf) { struct wpabuf *tx_buf; @@ -1681,7 +1681,8 @@ static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd, if (dpp) { struct wpabuf *msg; - msg = hostapd_dpp_gas_req_handler(hapd, sa, pos, slen); + msg = hostapd_dpp_gas_req_handler(hapd, sa, pos, slen, + data, len); if (!msg) return; gas_serv_req_dpp_processing(hapd, sa, dialog_token, prot, msg); diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h index 2cf181729..1528af4af 100644 --- a/src/ap/gas_serv.h +++ b/src/ap/gas_serv.h @@ -88,4 +88,8 @@ void gas_serv_dialog_clear(struct gas_dialog_info *dialog); int gas_serv_init(struct hostapd_data *hapd); void gas_serv_deinit(struct hostapd_data *hapd); +void gas_serv_req_dpp_processing(struct hostapd_data *hapd, + const u8 *sa, u8 dialog_token, + int prot, struct wpabuf *buf); + #endif /* GAS_SERV_H */