Extend random MAC address support to allow OUI to be kept

mac_addr=2 and preassoc_mac_addr=2 parameters can now be used to
configure random MAC address to be generated by maintaining the OUI part
of the permanent MAC address (but with locally administered bit set to
1). Other than that, these values result in similar behavior with
mac_addr=1 and preassoc_mac_addr=1, respectively.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-09-29 23:24:19 +03:00
parent 1cbdb9d137
commit a313d17de9
6 changed files with 36 additions and 9 deletions

View file

@ -1754,7 +1754,7 @@ static const struct parse_data ssid_fields[] = {
#ifdef CONFIG_HS20 #ifdef CONFIG_HS20
{ INT(update_identifier) }, { INT(update_identifier) },
#endif /* CONFIG_HS20 */ #endif /* CONFIG_HS20 */
{ INT_RANGE(mac_addr, 0, 1) }, { INT_RANGE(mac_addr, 0, 2) },
}; };
#undef OFFSET #undef OFFSET

View file

@ -1058,6 +1058,7 @@ struct wpa_config {
* *
* 0 = use permanent MAC address * 0 = use permanent MAC address
* 1 = use random MAC address for each ESS connection * 1 = use random MAC address for each ESS connection
* 2 = like 1, but maintain OUI (with local admin bit set)
* *
* By default, permanent MAC address is used unless policy is changed by * By default, permanent MAC address is used unless policy is changed by
* the per-network mac_addr parameter. Global mac_addr=1 can be used to * the per-network mac_addr parameter. Global mac_addr=1 can be used to
@ -1075,6 +1076,7 @@ struct wpa_config {
* *
* 0 = use permanent MAC address * 0 = use permanent MAC address
* 1 = use random MAC address * 1 = use random MAC address
* 2 = like 1, but maintain OUI (with local admin bit set)
*/ */
int preassoc_mac_addr; int preassoc_mac_addr;
}; };

View file

@ -659,6 +659,7 @@ struct wpa_ssid {
* *
* 0 = use permanent MAC address * 0 = use permanent MAC address
* 1 = use random MAC address for each ESS connection * 1 = use random MAC address for each ESS connection
* 2 = like 1, but maintain OUI (with local admin bit set)
* *
* Internally, special value -1 is used to indicate that the parameter * Internally, special value -1 is used to indicate that the parameter
* was not specified in the configuration (i.e., default behavior is * was not specified in the configuration (i.e., default behavior is

View file

@ -1380,13 +1380,14 @@ void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
} }
int wpas_update_random_addr(struct wpa_supplicant *wpa_s) int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
{ {
struct os_reltime now; struct os_reltime now;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
os_get_reltime(&now); os_get_reltime(&now);
if (wpa_s->last_mac_addr_change.sec != 0 && if (wpa_s->last_mac_addr_style == style &&
wpa_s->last_mac_addr_change.sec != 0 &&
!os_reltime_expired(&now, &wpa_s->last_mac_addr_change, !os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
wpa_s->conf->rand_addr_lifetime)) { wpa_s->conf->rand_addr_lifetime)) {
wpa_msg(wpa_s, MSG_DEBUG, wpa_msg(wpa_s, MSG_DEBUG,
@ -1394,8 +1395,19 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s)
return 0; return 0;
} }
if (random_mac_addr(addr) < 0) switch (style) {
case 1:
if (random_mac_addr(addr) < 0)
return -1;
break;
case 2:
os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN);
if (random_mac_addr_keep_oui(addr) < 0)
return -1;
break;
default:
return -1; return -1;
}
if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) { if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) {
wpa_msg(wpa_s, MSG_INFO, wpa_msg(wpa_s, MSG_INFO,
@ -1405,6 +1417,7 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s)
os_get_reltime(&wpa_s->last_mac_addr_change); os_get_reltime(&wpa_s->last_mac_addr_change);
wpa_s->mac_addr_changed = 1; wpa_s->mac_addr_changed = 1;
wpa_s->last_mac_addr_style = style;
if (wpa_supplicant_update_mac_addr(wpa_s) < 0) { if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
wpa_msg(wpa_s, MSG_INFO, wpa_msg(wpa_s, MSG_INFO,
@ -1425,7 +1438,7 @@ int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
!wpa_s->conf->preassoc_mac_addr) !wpa_s->conf->preassoc_mac_addr)
return 0; return 0;
return wpas_update_random_addr(wpa_s); return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
} }
@ -1443,12 +1456,17 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, struct wpa_ssid *ssid) struct wpa_bss *bss, struct wpa_ssid *ssid)
{ {
struct wpa_connect_work *cwork; struct wpa_connect_work *cwork;
int rand_style;
if (ssid->mac_addr == -1)
rand_style = wpa_s->conf->mac_addr;
else
rand_style = ssid->mac_addr;
if (wpa_s->last_ssid == ssid) { if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS"); wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
} else if (ssid->mac_addr == 1 || } else if (rand_style > 0) {
(ssid->mac_addr == -1 && wpa_s->conf->mac_addr == 1)) { if (wpas_update_random_addr(wpa_s, rand_style) < 0)
if (wpas_update_random_addr(wpa_s) < 0)
return; return;
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
} else if (wpa_s->mac_addr_changed) { } else if (wpa_s->mac_addr_changed) {
@ -2783,6 +2801,7 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR, wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
MAC2STR(wpa_s->own_addr)); MAC2STR(wpa_s->own_addr));
os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN);
wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
if (wpa_s->bridge_ifname[0]) { if (wpa_s->bridge_ifname[0]) {

View file

@ -335,6 +335,7 @@ fast_reauth=1
# MAC address policy default # MAC address policy default
# 0 = use permanent MAC address # 0 = use permanent MAC address
# 1 = use random MAC address for each ESS connection # 1 = use random MAC address for each ESS connection
# 2 = like 1, but maintain OUI (with local admin bit set)
# #
# By default, permanent MAC address is used unless policy is changed by # By default, permanent MAC address is used unless policy is changed by
# the per-network mac_addr parameter. Global mac_addr=1 can be used to # the per-network mac_addr parameter. Global mac_addr=1 can be used to
@ -347,6 +348,7 @@ fast_reauth=1
# MAC address policy for pre-association operations (scanning, ANQP) # MAC address policy for pre-association operations (scanning, ANQP)
# 0 = use permanent MAC address # 0 = use permanent MAC address
# 1 = use random MAC address # 1 = use random MAC address
# 2 = like 1, but maintain OUI (with local admin bit set)
#preassoc_mac_addr=0 #preassoc_mac_addr=0
# Interworking (IEEE 802.11u) # Interworking (IEEE 802.11u)
@ -982,6 +984,7 @@ fast_reauth=1
# MAC address policy # MAC address policy
# 0 = use permanent MAC address # 0 = use permanent MAC address
# 1 = use random MAC address for each ESS connection # 1 = use random MAC address for each ESS connection
# 2 = like 1, but maintain OUI (with local admin bit set)
#mac_addr=0 #mac_addr=0
# disable_ht: Whether HT (802.11n) should be disabled. # disable_ht: Whether HT (802.11n) should be disabled.

View file

@ -391,6 +391,7 @@ struct wpa_supplicant {
struct l2_packet_data *l2; struct l2_packet_data *l2;
struct l2_packet_data *l2_br; struct l2_packet_data *l2_br;
unsigned char own_addr[ETH_ALEN]; unsigned char own_addr[ETH_ALEN];
unsigned char perm_addr[ETH_ALEN];
char ifname[100]; char ifname[100];
#ifdef CONFIG_CTRL_IFACE_DBUS #ifdef CONFIG_CTRL_IFACE_DBUS
char *dbus_path; char *dbus_path;
@ -613,6 +614,7 @@ struct wpa_supplicant {
unsigned int mac_addr_changed:1; unsigned int mac_addr_changed:1;
struct os_reltime last_mac_addr_change; struct os_reltime last_mac_addr_change;
int last_mac_addr_style;
struct ibss_rsn *ibss_rsn; struct ibss_rsn *ibss_rsn;
@ -962,7 +964,7 @@ int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
size_t ssid_len); size_t ssid_len);
void wpas_request_connection(struct wpa_supplicant *wpa_s); void wpas_request_connection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen); int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
int wpas_update_random_addr(struct wpa_supplicant *wpa_s); int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style);
int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s); int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
/** /**