]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP2: hostapd as TCP Relay
authorJouni Malinen <jouni@codeaurora.org>
Sun, 24 Mar 2019 20:17:49 +0000 (22:17 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 22 Apr 2019 18:08:59 +0000 (21:08 +0300)
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>
hostapd/config_file.c
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/dpp_hostapd.c
src/ap/dpp_hostapd.h
src/ap/gas_serv.c
src/ap/gas_serv.h

index 42f3b40ef48b2b641a8cc8ba741f159610bb31d8..3f61cb625f7929f279a4deeb177c4819dfb4486e 100644 (file)
@@ -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) {
index e640e9984b70ef8bded3e18eda042f037d671dbf..07b818eb36b8dbf6f03100bbfbbc4278f865731d 100644 (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)
 {
        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);
index 509677a45f0564cebf952fa27da48b93d12d3501..19eda67e131d0a3d3c2df9df582465e90c306e3e 100644 (file)
@@ -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
index 75edbc909e7a022429f6feb4ae68deaddbb59ddd..697c3bad34ab366d428a8d49c2e16938f37b5d75 100644 (file)
@@ -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);
 }
 
 
index 449ca16d118ff079a29b46f0118597c40b7f6c33..c1ec5d70e4114b70bef2e52e13936e0ace8fb584 100644 (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);
 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);
index a7df810324777555384f0b7541ccadb3f337ef17..9567e202a7f0335dbdef329ac7565f7441a3ae94 100644 (file)
@@ -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);
index 2cf1817298f7da643e66c5f4f3702cd296d7c62f..1528af4afd91ceed320052ae9de2121f2cb6d608 100644 (file)
@@ -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 */