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);
|
config->ctrl_interface = os_strdup(ctrl_interface);
|
||||||
if (driver_param)
|
if (driver_param)
|
||||||
config->driver_param = os_strdup(driver_param);
|
config->driver_param = os_strdup(driver_param);
|
||||||
|
config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
@ -4456,6 +4457,8 @@ static const struct global_parse_data global_fields[] = {
|
||||||
{ INT(gas_address3), 0 },
|
{ INT(gas_address3), 0 },
|
||||||
{ INT_RANGE(ftm_responder, 0, 1), 0 },
|
{ INT_RANGE(ftm_responder, 0, 1), 0 },
|
||||||
{ INT_RANGE(ftm_initiator, 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
|
#undef FUNC
|
||||||
|
|
|
@ -1328,6 +1328,21 @@ struct wpa_config {
|
||||||
* wpa_supplicant.
|
* wpa_supplicant.
|
||||||
*/
|
*/
|
||||||
int ftm_initiator;
|
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);
|
fprintf(f, "fst_priority=%d\n", config->fst_priority);
|
||||||
if (config->fst_llt)
|
if (config->fst_llt)
|
||||||
fprintf(f, "fst_llt=%d\n", 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 */
|
#endif /* CONFIG_NO_CONFIG_WRITE */
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct gas_query_pending {
|
||||||
const struct wpabuf *adv_proto,
|
const struct wpabuf *adv_proto,
|
||||||
const struct wpabuf *resp, u16 status_code);
|
const struct wpabuf *resp, u16 status_code);
|
||||||
void *ctx;
|
void *ctx;
|
||||||
|
u8 sa[ETH_ALEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,6 +64,9 @@ struct gas_query {
|
||||||
struct dl_list pending; /* struct gas_query_pending */
|
struct dl_list pending; /* struct gas_query_pending */
|
||||||
struct gas_query_pending *current;
|
struct gas_query_pending *current;
|
||||||
struct wpa_radio_work *work;
|
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 "
|
wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
|
||||||
"freq=%d prot=%d", MAC2STR(query->addr),
|
"freq=%d prot=%d using src addr " MACSTR,
|
||||||
(unsigned int) wpabuf_len(req), query->freq, prot);
|
MAC2STR(query->addr), (unsigned int) wpabuf_len(req),
|
||||||
|
query->freq, prot, MAC2STR(query->sa));
|
||||||
if (prot) {
|
if (prot) {
|
||||||
u8 *categ = wpabuf_mhead_u8(req);
|
u8 *categ = wpabuf_mhead_u8(req);
|
||||||
*categ = WLAN_ACTION_PROTECTED_DUAL;
|
*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;
|
bssid = query->addr;
|
||||||
else
|
else
|
||||||
bssid = wildcard_bssid;
|
bssid = wildcard_bssid;
|
||||||
|
|
||||||
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
|
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
|
||||||
gas->wpa_s->own_addr, bssid,
|
query->sa, bssid, wpabuf_head(req),
|
||||||
wpabuf_head(req), wpabuf_len(req),
|
wpabuf_len(req), wait_time,
|
||||||
wait_time, gas_query_tx_status, 0);
|
gas_query_tx_status, 0);
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
query->offchannel_tx_started = 1;
|
query->offchannel_tx_started = 1;
|
||||||
return res;
|
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_query_req - Request a GAS query
|
||||||
* @gas: GAS query data from gas_query_init()
|
* @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;
|
return -1;
|
||||||
|
|
||||||
query->gas = gas;
|
query->gas = gas;
|
||||||
|
if (gas_query_set_sa(gas, query)) {
|
||||||
|
os_free(query);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
os_memcpy(query->addr, dst, ETH_ALEN);
|
os_memcpy(query->addr, dst, ETH_ALEN);
|
||||||
query->dialog_token = dialog_token;
|
query->dialog_token = dialog_token;
|
||||||
query->freq = freq;
|
query->freq = freq;
|
||||||
|
|
|
@ -422,6 +422,15 @@ fast_reauth=1
|
||||||
# 2 = like 1, but maintain OUI (with local admin bit set)
|
# 2 = like 1, but maintain OUI (with local admin bit set)
|
||||||
#preassoc_mac_addr=0
|
#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)
|
# Interworking (IEEE 802.11u)
|
||||||
|
|
||||||
# Enable Interworking
|
# Enable Interworking
|
||||||
|
|
Loading…
Reference in a new issue