wpa_supplicant: Add support for pregenerated MAC
Add new 'mac_addr' policy (3) with which supplicant expects to also obtain 'mac_value' with pregenerated value of MAC address to be used for given SSID. The main difference between this policy and policy 1 is the ability to control persistence of the MAC address used. For example if there is a requirement to always use the same (but random) MAC address for given SSID (even if user removes/forgets the network) this could be handled outside of the wpa_supplicant by using some SSID based hashing scheme to generate MAC (or by just storing the randomly generated one) and providing it to wpa_supplicant together with mac_addr=3 policy. Signed-off-by: Andrzej Ostruszka <amo@semihalf.com>
This commit is contained in:
parent
5da3e1ca44
commit
9025def55c
5 changed files with 93 additions and 6 deletions
|
@ -2345,6 +2345,50 @@ static char * wpa_config_write_peerkey(const struct parse_data *data,
|
|||
#endif /* NO_CONFIG_WRITE */
|
||||
|
||||
|
||||
static int wpa_config_parse_mac_value(const struct parse_data *data,
|
||||
struct wpa_ssid *ssid, int line,
|
||||
const char *value)
|
||||
{
|
||||
u8 mac_value[ETH_ALEN];
|
||||
|
||||
if (hwaddr_aton(value, mac_value) == 0) {
|
||||
if (os_memcmp(mac_value, ssid->mac_value, ETH_ALEN) == 0)
|
||||
return 1;
|
||||
os_memcpy(ssid->mac_value, mac_value, ETH_ALEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_ERROR, "Line %d: Invalid MAC address '%s'",
|
||||
line, value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_CONFIG_WRITE
|
||||
static char * wpa_config_write_mac_value(const struct parse_data *data,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
const size_t size = 3 * ETH_ALEN;
|
||||
char *value;
|
||||
int res;
|
||||
|
||||
if (ssid->mac_addr != 3)
|
||||
return NULL;
|
||||
|
||||
value = os_malloc(size);
|
||||
if (!value)
|
||||
return NULL;
|
||||
res = os_snprintf(value, size, MACSTR, MAC2STR(ssid->mac_value));
|
||||
if (os_snprintf_error(size, res)) {
|
||||
os_free(value);
|
||||
return NULL;
|
||||
}
|
||||
value[size - 1] = '\0';
|
||||
return value;
|
||||
}
|
||||
#endif /* NO_CONFIG_WRITE */
|
||||
|
||||
|
||||
/* Helper macros for network block parser */
|
||||
|
||||
#ifdef OFFSET
|
||||
|
@ -2643,7 +2687,8 @@ static const struct parse_data ssid_fields[] = {
|
|||
{ INT(update_identifier) },
|
||||
{ STR_RANGE(roaming_consortium_selection, 0, MAX_ROAMING_CONS_OI_LEN) },
|
||||
#endif /* CONFIG_HS20 */
|
||||
{ INT_RANGE(mac_addr, 0, 2) },
|
||||
{ INT_RANGE(mac_addr, 0, 3) },
|
||||
{ FUNC_KEY(mac_value) },
|
||||
{ INT_RANGE(pbss, 0, 2) },
|
||||
{ INT_RANGE(wps_disabled, 0, 1) },
|
||||
{ INT_RANGE(fils_dh_group, 0, 65535) },
|
||||
|
|
|
@ -974,6 +974,7 @@ struct wpa_ssid {
|
|||
* 0 = use permanent MAC address
|
||||
* 1 = use random MAC address for each ESS connection
|
||||
* 2 = like 1, but maintain OUI (with local admin bit set)
|
||||
* 3 = use dedicated/pregenerated MAC address (see mac_value)
|
||||
*
|
||||
* Internally, special value -1 is used to indicate that the parameter
|
||||
* was not specified in the configuration (i.e., default behavior is
|
||||
|
@ -981,6 +982,14 @@ struct wpa_ssid {
|
|||
*/
|
||||
int mac_addr;
|
||||
|
||||
/**
|
||||
* mac_value - Specific MAC address to be used
|
||||
*
|
||||
* When mac_addr policy is equal to 3 this is the value of the MAC
|
||||
* address that should be used.
|
||||
*/
|
||||
u8 mac_value[ETH_ALEN];
|
||||
|
||||
/**
|
||||
* no_auto_peer - Do not automatically peer with compatible mesh peers
|
||||
*
|
||||
|
|
|
@ -152,7 +152,7 @@ static const char * const dont_quote[] = {
|
|||
#ifdef CONFIG_INTERWORKING
|
||||
"roaming_consortium", "required_roaming_consortium",
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
NULL
|
||||
"mac_value", NULL
|
||||
};
|
||||
|
||||
static dbus_bool_t should_quote_opt(const char *key)
|
||||
|
@ -206,6 +206,8 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
|
|||
struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
|
||||
DBusMessageIter iter_dict;
|
||||
char *value = NULL;
|
||||
bool mac_addr3_set = false;
|
||||
bool mac_value_set = false;
|
||||
|
||||
if (!wpa_dbus_dict_open_read(iter, &iter_dict, error))
|
||||
return FALSE;
|
||||
|
@ -315,12 +317,30 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
|
|||
else if (os_strcmp(entry.key, "priority") == 0)
|
||||
wpa_config_update_prio_list(wpa_s->conf);
|
||||
|
||||
/*
|
||||
* MAC address policy "3" needs to come with mac_value in
|
||||
* the message so make sure that it is present (checked after
|
||||
* the loop - here we just note what has been supplied).
|
||||
*/
|
||||
if (os_strcmp(entry.key, "mac_addr") == 0 &&
|
||||
atoi(value) == 3)
|
||||
mac_addr3_set = true;
|
||||
if (os_strcmp(entry.key, "mac_value") == 0)
|
||||
mac_value_set = true;
|
||||
|
||||
skip_update:
|
||||
os_free(value);
|
||||
value = NULL;
|
||||
wpa_dbus_dict_entry_clear(&entry);
|
||||
}
|
||||
|
||||
if (mac_addr3_set && !mac_value_set) {
|
||||
wpa_printf(MSG_INFO, "dbus: Invalid mac_addr policy config");
|
||||
dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid mac_addr policy config");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
|
|
|
@ -2222,13 +2222,16 @@ void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
|
|||
}
|
||||
|
||||
|
||||
int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
|
||||
int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
struct os_reltime now;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
os_get_reltime(&now);
|
||||
if (wpa_s->last_mac_addr_style == style &&
|
||||
/* Pregenerated addresses do not expire */
|
||||
wpa_s->last_mac_addr_style != 3 &&
|
||||
wpa_s->last_mac_addr_change.sec != 0 &&
|
||||
!os_reltime_expired(&now, &wpa_s->last_mac_addr_change,
|
||||
wpa_s->conf->rand_addr_lifetime)) {
|
||||
|
@ -2247,6 +2250,14 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style)
|
|||
if (random_mac_addr_keep_oui(addr) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case 3:
|
||||
if (!ssid) {
|
||||
wpa_msg(wpa_s, MSG_INFO,
|
||||
"Invalid 'ssid' for address policy 3");
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(addr, ssid->mac_value, ETH_ALEN);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -2280,7 +2291,8 @@ int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s)
|
|||
!wpa_s->conf->preassoc_mac_addr)
|
||||
return 0;
|
||||
|
||||
return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr);
|
||||
return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2417,7 +2429,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
|
|||
#endif /* CONFIG_SAE */
|
||||
|
||||
if (rand_style > 0 && !wpa_s->reassoc_same_ess) {
|
||||
if (wpas_update_random_addr(wpa_s, rand_style) < 0)
|
||||
if (wpas_update_random_addr(wpa_s, rand_style, ssid) < 0)
|
||||
return;
|
||||
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
|
||||
} else if (rand_style == 0 && wpa_s->mac_addr_changed) {
|
||||
|
|
|
@ -1640,7 +1640,8 @@ int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
|
|||
void wpas_request_connection(struct wpa_supplicant *wpa_s);
|
||||
void wpas_request_disconnection(struct wpa_supplicant *wpa_s);
|
||||
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 style);
|
||||
int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style,
|
||||
struct wpa_ssid *ssid);
|
||||
int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
|
||||
void add_freq(int *freqs, int *num_freqs, int freq);
|
||||
|
||||
|
|
Loading…
Reference in a new issue