DPP2: hostapd as TCP Relay

The new hostapd configuration parameter dpp_controller can now be used
with the following subparameter values: ipaddr=<IP address>
pkhash=<hexdump>. This adds a new Controller into the configuration
(i.e., more than one can be configured) and all incoming DPP exchanges
that match the specified Controller public key hash are relayed to the
particular Controller.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-03-24 22:17:49 +02:00 committed by Jouni Malinen
parent 88a78bdde4
commit e00f780e2b
7 changed files with 154 additions and 7 deletions

View file

@ -2376,6 +2376,36 @@ fail:
#endif /* CONFIG_SAE */ #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, static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss, struct hostapd_bss_config *bss,
const char *buf, char *pos, int line) 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) { } else if (os_strcmp(buf, "dpp_csign") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos)) if (parse_wpabuf_hex(line, buf, &bss->dpp_csign, pos))
return 1; 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 */ #endif /* CONFIG_DPP */
#ifdef CONFIG_OWE #ifdef CONFIG_OWE
} else if (os_strcmp(buf, "owe_transition_bssid") == 0) { } else if (os_strcmp(buf, "owe_transition_bssid") == 0) {

View file

@ -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) void hostapd_config_free_bss(struct hostapd_bss_config *conf)
{ {
if (conf == NULL) if (conf == NULL)
@ -740,6 +754,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->dpp_connector); os_free(conf->dpp_connector);
wpabuf_free(conf->dpp_netaccesskey); wpabuf_free(conf->dpp_netaccesskey);
wpabuf_free(conf->dpp_csign); wpabuf_free(conf->dpp_csign);
#ifdef CONFIG_DPP2
hostapd_dpp_controller_conf_free(conf->dpp_controller);
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */ #endif /* CONFIG_DPP */
hostapd_config_free_sae_passwords(conf); hostapd_config_free_sae_passwords(conf);

View file

@ -15,6 +15,7 @@
#include "common/wpa_common.h" #include "common/wpa_common.h"
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h" #include "common/ieee802_11_common.h"
#include "crypto/sha256.h"
#include "wps/wps.h" #include "wps/wps.h"
#include "fst/fst.h" #include "fst/fst.h"
#include "vlan.h" #include "vlan.h"
@ -252,6 +253,12 @@ struct sae_password_entry {
int vlan_id; 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 * struct hostapd_bss_config - Per-BSS configuration
*/ */
@ -692,6 +699,9 @@ struct hostapd_bss_config {
struct wpabuf *dpp_netaccesskey; struct wpabuf *dpp_netaccesskey;
unsigned int dpp_netaccesskey_expiry; unsigned int dpp_netaccesskey_expiry;
struct wpabuf *dpp_csign; struct wpabuf *dpp_csign;
#ifdef CONFIG_DPP2
struct dpp_controller_conf *dpp_controller;
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */ #endif /* CONFIG_DPP */
#ifdef CONFIG_OWE #ifdef CONFIG_OWE

View file

@ -16,6 +16,7 @@
#include "hostapd.h" #include "hostapd.h"
#include "ap_drv_ops.h" #include "ap_drv_ops.h"
#include "gas_query_ap.h" #include "gas_query_ap.h"
#include "gas_serv.h"
#include "wpa_auth.h" #include "wpa_auth.h"
#include "dpp_hostapd.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 */ * received hash values */
dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap, dpp_bootstrap_find_pair(hapd->iface->interfaces->dpp, i_bootstrap,
r_bootstrap, &own_bi, &peer_bi); 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) { if (!own_bi) {
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
"No matching own bootstrapping key found - ignore message"); "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 wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
" freq=%u type=%d", MAC2STR(src), freq, type); " 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) { switch (type) {
case DPP_PA_AUTHENTICATION_REQ: case DPP_PA_AUTHENTICATION_REQ:
hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq); 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 * struct wpabuf *
hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, 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 dpp_authentication *auth = hapd->dpp_auth;
struct wpabuf *resp; 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)); wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
if (!auth || !auth->auth_success || if (!auth || !auth->auth_success ||
os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { 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"); wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
return NULL; 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) int hostapd_dpp_init(struct hostapd_data *hapd)
{ {
hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE; hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
hapd->dpp_init_done = 1; hapd->dpp_init_done = 1;
return 0; return hostapd_dpp_add_controllers(hapd);
} }

View file

@ -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); const u8 *data, size_t data_len, int ok);
struct wpabuf * struct wpabuf *
hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, 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); 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_add(struct hostapd_data *hapd, const char *cmd);
int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id); int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id);

View file

@ -1522,7 +1522,7 @@ static void gas_serv_req_local_processing(struct hostapd_data *hapd,
#ifdef CONFIG_DPP #ifdef CONFIG_DPP
static void gas_serv_req_dpp_processing(struct hostapd_data *hapd, void gas_serv_req_dpp_processing(struct hostapd_data *hapd,
const u8 *sa, u8 dialog_token, const u8 *sa, u8 dialog_token,
int prot, struct wpabuf *buf) int prot, struct wpabuf *buf)
{ {
@ -1681,7 +1681,8 @@ static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
if (dpp) { if (dpp) {
struct wpabuf *msg; 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) if (!msg)
return; return;
gas_serv_req_dpp_processing(hapd, sa, dialog_token, prot, msg); gas_serv_req_dpp_processing(hapd, sa, dialog_token, prot, msg);

View file

@ -88,4 +88,8 @@ void gas_serv_dialog_clear(struct gas_dialog_info *dialog);
int gas_serv_init(struct hostapd_data *hapd); int gas_serv_init(struct hostapd_data *hapd);
void gas_serv_deinit(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 */ #endif /* GAS_SERV_H */