]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
GAS: Add support to randomize transmitter address
authorVamsi Krishna <vamsin@qti.qualcomm.com>
Thu, 8 Dec 2016 16:21:25 +0000 (21:51 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 7 Feb 2017 17:41:32 +0000 (19:41 +0200)
Add support to send GAS requests with a randomized transmitter address
if supported by the driver. The following control interface commands
(and matching configuration file parameters) can be used to configure
different types of randomization:

"SET gas_rand_mac_addr 0" to disable randomizing TX MAC address,
"SET gas_rand_mac_addr 1" to randomize the complete TX MAC address,
"SET gas_rand_mac_addr 2" to randomize the TX MAC address except for OUI.

A new random MAC address will be generated for every
gas_rand_addr_lifetime seconds and this can be configured with
"SET gas_rand_addr_lifetime <timeout>".

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/gas_query.c
wpa_supplicant/wpa_supplicant.conf

index bdaaa5430a152c74e5fdc1ad5986c26d2d4e9cf5..58ecf19fd5fbe4dbd13ac9c0e0197afa8e160aec 100644 (file)
@@ -3748,6 +3748,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
                config->ctrl_interface = os_strdup(ctrl_interface);
        if (driver_param)
                config->driver_param = os_strdup(driver_param);
+       config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
 
        return config;
 }
@@ -4456,6 +4457,8 @@ static const struct global_parse_data global_fields[] = {
        { INT(gas_address3), 0 },
        { INT_RANGE(ftm_responder, 0, 1), 0 },
        { INT_RANGE(ftm_initiator, 0, 1), 0 },
+       { INT(gas_rand_addr_lifetime), 0 },
+       { INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
 };
 
 #undef FUNC
index 48e64be5da1a1d0e900c0b693e9d3fa9a6801c09..2f2bb01c6de68438fe3d33dee2ec432baca77629 100644 (file)
@@ -1328,6 +1328,21 @@ struct wpa_config {
         * wpa_supplicant.
         */
        int ftm_initiator;
+
+       /**
+        * gas_rand_addr_lifetime - Lifetime of random MAC address for ANQP in
+        *      seconds
+        */
+       unsigned int gas_rand_addr_lifetime;
+
+       /**
+        * gas_rand_mac_addr - GAS MAC address policy
+        *
+        * 0 = use permanent MAC address
+        * 1 = use random MAC address
+        * 2 = like 1, but maintain OUI (with local admin bit set)
+        */
+       int gas_rand_mac_addr;
 };
 
 
index 920bdc07f6d79543f967ef292494573a3c296b16..84a1ee945bb4d30829ef3321aa318375e0d3f388 100644 (file)
@@ -1413,6 +1413,13 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
                fprintf(f, "fst_priority=%d\n", config->fst_priority);
        if (config->fst_llt)
                fprintf(f, "fst_llt=%d\n", config->fst_llt);
+
+       if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME)
+               fprintf(f, "gas_rand_addr_lifetime=%u\n",
+                       config->gas_rand_addr_lifetime);
+       if (config->gas_rand_mac_addr)
+               fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr);
+
 }
 
 #endif /* CONFIG_NO_CONFIG_WRITE */
index 1b57d889208df337917784a6e9c337de600f3411..db481a59197af89d20a63453d9f50e68df03ebb4 100644 (file)
@@ -53,6 +53,7 @@ struct gas_query_pending {
                   const struct wpabuf *adv_proto,
                   const struct wpabuf *resp, u16 status_code);
        void *ctx;
+       u8 sa[ETH_ALEN];
 };
 
 /**
@@ -63,6 +64,9 @@ struct gas_query {
        struct dl_list pending; /* struct gas_query_pending */
        struct gas_query_pending *current;
        struct wpa_radio_work *work;
+       struct os_reltime last_mac_addr_rand;
+       int last_rand_sa_type;
+       u8 rand_addr[ETH_ALEN];
 };
 
 
@@ -278,8 +282,9 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
        };
 
        wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
-                  "freq=%d prot=%d", MAC2STR(query->addr),
-                  (unsigned int) wpabuf_len(req), query->freq, prot);
+                  "freq=%d prot=%d using src addr " MACSTR,
+                  MAC2STR(query->addr), (unsigned int) wpabuf_len(req),
+                  query->freq, prot, MAC2STR(query->sa));
        if (prot) {
                u8 *categ = wpabuf_mhead_u8(req);
                *categ = WLAN_ACTION_PROTECTED_DUAL;
@@ -295,10 +300,12 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
                bssid = query->addr;
        else
                bssid = wildcard_bssid;
+
        res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
-                                    gas->wpa_s->own_addr, bssid,
-                                    wpabuf_head(req), wpabuf_len(req),
-                                    wait_time, gas_query_tx_status, 0);
+                                    query->sa, bssid, wpabuf_head(req),
+                                    wpabuf_len(req), wait_time,
+                                    gas_query_tx_status, 0);
+
        if (res == 0)
                query->offchannel_tx_started = 1;
        return res;
@@ -725,6 +732,58 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
 }
 
 
+static int gas_query_set_sa(struct gas_query *gas,
+                           struct gas_query_pending *query)
+{
+       struct wpa_supplicant *wpa_s = gas->wpa_s;
+       struct os_reltime now;
+
+       if (!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 */
+               os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN);
+               return 0;
+       }
+
+       os_get_reltime(&now);
+
+       if (wpa_s->conf->gas_rand_mac_addr == gas->last_rand_sa_type &&
+           gas->last_mac_addr_rand.sec != 0 &&
+           !os_reltime_expired(&now, &gas->last_mac_addr_rand,
+                               wpa_s->conf->gas_rand_addr_lifetime)) {
+               wpa_printf(MSG_DEBUG,
+                          "GAS: Use the previously selected random transmitter address "
+                          MACSTR, MAC2STR(gas->rand_addr));
+               os_memcpy(query->sa, gas->rand_addr, ETH_ALEN);
+               return 0;
+       }
+
+       if (wpa_s->conf->gas_rand_mac_addr == 1 &&
+           random_mac_addr(gas->rand_addr) < 0) {
+               wpa_printf(MSG_ERROR, "GAS: Failed to get random address");
+               return -1;
+       }
+
+       if (wpa_s->conf->gas_rand_mac_addr == 2 &&
+           random_mac_addr_keep_oui(gas->rand_addr) < 0) {
+               wpa_printf(MSG_ERROR,
+                          "GAS: Failed to get random address with same OUI");
+               return -1;
+       }
+
+       wpa_printf(MSG_DEBUG, "GAS: Use a new random transmitter address "
+                  MACSTR, MAC2STR(gas->rand_addr));
+       os_memcpy(query->sa, gas->rand_addr, ETH_ALEN);
+       os_get_reltime(&gas->last_mac_addr_rand);
+       gas->last_rand_sa_type = wpa_s->conf->gas_rand_mac_addr;
+
+       return 0;
+}
+
+
 /**
  * gas_query_req - Request a GAS query
  * @gas: GAS query data from gas_query_init()
@@ -759,6 +818,10 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
                return -1;
 
        query->gas = gas;
+       if (gas_query_set_sa(gas, query)) {
+               os_free(query);
+               return -1;
+       }
        os_memcpy(query->addr, dst, ETH_ALEN);
        query->dialog_token = dialog_token;
        query->freq = freq;
index c90fa629ac494a02d1a7a75eeac05624b8228efd..6faa7af1ff0a31ab29e398b39722555c0a1672a5 100644 (file)
@@ -422,6 +422,15 @@ fast_reauth=1
 # 2 = like 1, but maintain OUI (with local admin bit set)
 #preassoc_mac_addr=0
 
+# MAC address policy for GAS operations
+# 0 = use permanent MAC address
+# 1 = use random MAC address
+# 2 = like 1, but maintain OUI (with local admin bit set)
+#gas_rand_mac_addr=0
+
+# Lifetime of GAS random MAC address in seconds (default: 60)
+#gas_rand_addr_lifetime=60
+
 # Interworking (IEEE 802.11u)
 
 # Enable Interworking