From 0c5edededa319e6bba5a555dcee2e08a9de759a0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 22 Apr 2020 17:04:43 +0300 Subject: [PATCH] DPP: Fix config exchange with gas_rand_mac_addr Do not use a random MAC address for the GAS exchange that is used as part of the DPP protocol exchange since that would break DPP. Configurator expects the same MAC address to be used for DPP Authentication exchange and DPP Configuration exchange (GAS). Since the DPP Authentication exchange has already used the MAC address configured on the interface, use of a random address for the GAS exchange would not provide any additional privacy protection. If a random MAC address needs to be used for this type of an exchange, that random address would need to be first configured on the interface before starting DPP exchange. This does not change GAS query behavior for any other use case, i.e., the gas_rand_mac_addr configuration continues to apply to all the Interworking/Hotspot 2.0 uses. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 2 +- wpa_supplicant/gas_query.c | 23 ++++++++++++++++++++--- wpa_supplicant/gas_query.h | 2 +- wpa_supplicant/hs20_supplicant.c | 3 ++- wpa_supplicant/interworking.c | 8 +++++--- wpa_supplicant/wpa_supplicant.conf | 5 +++++ 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 351f8da9d..291b96b75 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1428,7 +1428,7 @@ static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s) MAC2STR(auth->peer_mac_addr), auth->curr_freq); res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq, - 1, buf, wpas_dpp_gas_resp_cb, wpa_s); + 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); wpabuf_free(buf); diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index 8e977a3ec..759b9b9cd 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -43,6 +43,7 @@ struct gas_query_pending { unsigned int offchannel_tx_started:1; unsigned int retry:1; unsigned int wildcard_bssid:1; + unsigned int maintain_addr:1; int freq; u16 status_code; struct wpabuf *req; @@ -693,7 +694,8 @@ static void gas_query_start_cb(struct wpa_radio_work *work, int deinit) return; } - if (wpas_update_random_addr_disassoc(wpa_s) < 0) { + if (!query->maintain_addr && + wpas_update_random_addr_disassoc(wpa_s) < 0) { wpa_msg(wpa_s, MSG_INFO, "Failed to assign random MAC address for GAS"); gas_query_free(query, 1); @@ -749,12 +751,23 @@ static int gas_query_set_sa(struct gas_query *gas, struct wpa_supplicant *wpa_s = gas->wpa_s; struct os_reltime now; - if (!wpa_s->conf->gas_rand_mac_addr || + if (query->maintain_addr || + !wpa_s->conf->gas_rand_mac_addr || !(wpa_s->current_bss ? (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA))) { /* Use own MAC address as the transmitter address */ + wpa_printf(MSG_DEBUG, + "GAS: Use own MAC address as the transmitter address%s%s%s", + query->maintain_addr ? " (maintain_addr)" : "", + !wpa_s->conf->gas_rand_mac_addr ? " (no gas_rand_mac_adr set)" : "", + !(wpa_s->current_bss ? + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) : + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA)) ? + " (no driver rand capa" : ""); os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN); return 0; } @@ -800,6 +813,9 @@ static int gas_query_set_sa(struct gas_query *gas, * @gas: GAS query data from gas_query_init() * @dst: Destination MAC address for the query * @freq: Frequency (in MHz) for the channel on which to send the query + * @wildcard_bssid: Force use of wildcard BSSID value + * @maintain_addr: Maintain own MAC address for exchange (i.e., ignore MAC + * address randomization rules) * @req: GAS query payload (to be freed by gas_query module in case of success * return) * @cb: Callback function for reporting GAS query result and response @@ -807,7 +823,7 @@ static int gas_query_set_sa(struct gas_query *gas, * Returns: dialog token (>= 0) on success or -1 on failure */ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - int wildcard_bssid, struct wpabuf *req, + int wildcard_bssid, int maintain_addr, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, @@ -829,6 +845,7 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, return -1; query->gas = gas; + query->maintain_addr = !!maintain_addr; if (gas_query_set_sa(gas, query)) { os_free(query); return -1; diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h index d2b455442..f9ce7b680 100644 --- a/wpa_supplicant/gas_query.h +++ b/wpa_supplicant/gas_query.h @@ -35,7 +35,7 @@ enum gas_query_result { }; int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - int wildcard_bssid, struct wpabuf *req, + int wildcard_bssid, int maintain_addr, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 47a1d0175..3bf777e6a 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -288,7 +288,8 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb, + wpa_s); if (res < 0) { wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 49b9907b0..c48525cec 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -316,7 +316,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, buf, + res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, 0, buf, interworking_anqp_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); @@ -2804,7 +2804,8 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb, + wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); @@ -3243,7 +3244,8 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, } else wpabuf_put_le16(buf, 0); - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, gas_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, gas_resp_cb, + wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); wpabuf_free(buf); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index f242c3a9e..3b9056770 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -481,6 +481,11 @@ fast_reauth=1 # 0 = use permanent MAC address # 1 = use random MAC address # 2 = like 1, but maintain OUI (with local admin bit set) +# Note that this setting is ignored when a specific MAC address is needed for +# a full protocol exchange that includes GAS, e.g., when going through a DPP +# exchange that exposes the configured interface address as part of the DP +# Public Action frame exchanges before using GAS. That same address is then used +# during the GAS exchange as well to avoid breaking the protocol expectations. #gas_rand_mac_addr=0 # Lifetime of GAS random MAC address in seconds (default: 60)