GAS: Add support to randomize transmitter address
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>
This commit is contained in:
parent
8331c9b316
commit
1d9d21f376
5 changed files with 102 additions and 5 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue