network: Move handshake parameter setup from station

Most parameters set into the handshake object are actually known by the
network object itself and not station.  This includes address
randomization settings, EAPoL settings, passphrase/psk/8021x settings,
etc.  Since the number of these settings will only keep growing, move
the handshake setup into network itself.  This also helps keep network
internals better encapsulated.
This commit is contained in:
Denis Kenzior 2021-07-08 16:47:50 -05:00
parent 869bcf59d5
commit 2a66b3bfe5
3 changed files with 117 additions and 94 deletions

View File

@ -29,6 +29,7 @@
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <alloca.h> #include <alloca.h>
#include <linux/if_ether.h>
#include <ell/ell.h> #include <ell/ell.h>
@ -53,6 +54,7 @@
#include "src/blacklist.h" #include "src/blacklist.h"
#include "src/util.h" #include "src/util.h"
#include "src/erp.h" #include "src/erp.h"
#include "src/handshake.h"
static uint32_t known_networks_watch; static uint32_t known_networks_watch;
static uint32_t anqp_watch; static uint32_t anqp_watch;
@ -259,7 +261,7 @@ enum security network_get_security(const struct network *network)
return network->security; return network->security;
} }
const uint8_t *network_get_psk(struct network *network) static const uint8_t *network_get_psk(struct network *network)
{ {
int r; int r;
@ -281,11 +283,6 @@ const uint8_t *network_get_psk(struct network *network)
return network->psk; return network->psk;
} }
const char *network_get_passphrase(const struct network *network)
{
return network->passphrase;
}
static bool __network_set_passphrase(struct network *network, static bool __network_set_passphrase(struct network *network,
const char *passphrase) const char *passphrase)
{ {
@ -388,6 +385,113 @@ static bool network_set_8021x_secrets(struct network *network)
return true; return true;
} }
static int network_set_handshake_secrets_psk(struct network *network,
struct handshake_state *hs)
{
/* SAE will generate/set the PMK */
if (IE_AKM_IS_SAE(hs->akm_suite)) {
if (!network->passphrase)
return -ENOKEY;
handshake_state_set_passphrase(hs, network->passphrase);
} else {
const uint8_t *psk = network_get_psk(network);
if (!psk)
return -ENOKEY;
handshake_state_set_pmk(hs, psk, 32);
}
return 0;
}
int network_handshake_setup(struct network *network,
struct handshake_state *hs)
{
struct station *station = network->station;
struct wiphy *wiphy = station_get_wiphy(station);
struct l_settings *settings = network->settings;
uint32_t eapol_proto_version;
const char *value;
bool full_random;
bool override = false;
uint8_t new_addr[ETH_ALEN];
int r;
switch (network->security) {
case SECURITY_PSK:
r = network_set_handshake_secrets_psk(network, hs);
if (r < 0)
return r;
break;
case SECURITY_8021X:
handshake_state_set_8021x_config(hs, settings);
break;
case SECURITY_NONE:
break;
case SECURITY_WEP:
return -ENOTSUP;
}
handshake_state_set_ssid(hs, (void *) network->ssid,
strlen(network->ssid));
if (settings && l_settings_get_uint(settings, "EAPoL",
"ProtocolVersion",
&eapol_proto_version)) {
if (eapol_proto_version > 3) {
l_warn("Invalid ProtocolVersion value - should be 0-3");
eapol_proto_version = 0;
}
if (eapol_proto_version)
l_debug("Overriding EAPoL protocol version to: %u",
eapol_proto_version);
handshake_state_set_protocol_version(hs, eapol_proto_version);
}
/*
* We have three possible options here:
* 1. per-network MAC generation (default, no option in network config)
* 2. per-network full MAC randomization
* 3. per-network MAC override
*/
if (!l_settings_get_bool(settings, "Settings",
"AlwaysRandomizeAddress",
&full_random))
full_random = false;
value = l_settings_get_value(settings, "Settings",
"AddressOverride");
if (value) {
if (util_string_to_address(value, new_addr) &&
util_is_valid_sta_address(new_addr))
override = true;
else
l_warn("[Network].AddressOverride is not a valid "
"MAC address");
}
if (override && full_random) {
l_warn("Cannot use both AlwaysRandomizeAddress and "
"AddressOverride concurrently, defaulting to override");
full_random = false;
}
if (override)
handshake_state_set_supplicant_address(hs, new_addr);
else if (full_random) {
wiphy_generate_random_address(wiphy, new_addr);
handshake_state_set_supplicant_address(hs, new_addr);
}
return 0;
}
static int network_load_psk(struct network *network, bool need_passphrase) static int network_load_psk(struct network *network, bool need_passphrase)
{ {
const char *ssid = network_get_ssid(network); const char *ssid = network_get_ssid(network);

View File

@ -28,6 +28,7 @@ struct device;
struct station; struct station;
struct network; struct network;
struct scan_bss; struct scan_bss;
struct handshake_state;
void network_connected(struct network *network); void network_connected(struct network *network);
void network_disconnected(struct network *network); void network_disconnected(struct network *network);
@ -39,14 +40,16 @@ struct network *network_create(struct station *station, const char *ssid,
const char *network_get_ssid(const struct network *network); const char *network_get_ssid(const struct network *network);
const char *network_get_path(const struct network *network); const char *network_get_path(const struct network *network);
enum security network_get_security(const struct network *network); enum security network_get_security(const struct network *network);
const uint8_t *network_get_psk(struct network *network);
const char *network_get_passphrase(const struct network *network);
bool network_set_passphrase(struct network *network, const char *passphrase); bool network_set_passphrase(struct network *network, const char *passphrase);
struct l_queue *network_get_secrets(const struct network *network); struct l_queue *network_get_secrets(const struct network *network);
int network_get_signal_strength(const struct network *network); int network_get_signal_strength(const struct network *network);
struct l_settings *network_get_settings(const struct network *network); struct l_settings *network_get_settings(const struct network *network);
bool network_set_psk(struct network *network, const uint8_t *psk); bool network_set_psk(struct network *network, const uint8_t *psk);
int network_handshake_setup(struct network *network,
struct handshake_state *hs);
void network_sync_settings(struct network *network); void network_sync_settings(struct network *network);
const struct network_info *network_get_info(const struct network *network); const struct network_info *network_get_info(const struct network *network);

View File

@ -865,16 +865,8 @@ static struct handshake_state *station_handshake_setup(struct station *station,
struct network *network, struct network *network,
struct scan_bss *bss) struct scan_bss *bss)
{ {
enum security security = network_get_security(network);
struct l_settings *settings = network_get_settings(network);
struct wiphy *wiphy = station->wiphy; struct wiphy *wiphy = station->wiphy;
struct handshake_state *hs; struct handshake_state *hs;
const char *ssid;
uint32_t eapol_proto_version;
const char *value;
bool full_random;
bool override = false;
uint8_t new_addr[ETH_ALEN];
hs = netdev_handshake_state_new(station->netdev); hs = netdev_handshake_state_new(station->netdev);
@ -883,45 +875,8 @@ static struct handshake_state *station_handshake_setup(struct station *station,
if (station_build_handshake_rsn(hs, wiphy, network, bss) < 0) if (station_build_handshake_rsn(hs, wiphy, network, bss) < 0)
goto not_supported; goto not_supported;
ssid = network_get_ssid(network); if (network_handshake_setup(network, hs) < 0)
handshake_state_set_ssid(hs, (void *) ssid, strlen(ssid)); goto not_supported;
if (settings && l_settings_get_uint(settings, "EAPoL",
"ProtocolVersion",
&eapol_proto_version)) {
if (eapol_proto_version > 3) {
l_warn("Invalid ProtocolVersion value - should be 0-3");
eapol_proto_version = 0;
}
if (eapol_proto_version)
l_debug("Overriding EAPoL protocol version to: %u",
eapol_proto_version);
handshake_state_set_protocol_version(hs, eapol_proto_version);
}
if (security == SECURITY_PSK) {
/* SAE will generate/set the PMK */
if (IE_AKM_IS_SAE(hs->akm_suite)) {
const char *passphrase =
network_get_passphrase(network);
if (!passphrase)
goto no_psk;
handshake_state_set_passphrase(hs, passphrase);
} else {
const uint8_t *psk = network_get_psk(network);
if (!psk)
goto no_psk;
handshake_state_set_pmk(hs, psk, 32);
}
} else if (security == SECURITY_8021X)
handshake_state_set_8021x_config(hs,
network_get_settings(network));
/* /*
* If FILS was chosen, the ERP cache has been verified to exist. We * If FILS was chosen, the ERP cache has been verified to exist. We
@ -934,49 +889,10 @@ static struct handshake_state *station_handshake_setup(struct station *station,
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384)) IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384))
hs->erp_cache = erp_cache_get(network_get_ssid(network)); hs->erp_cache = erp_cache_get(network_get_ssid(network));
/*
* We have three possible options here:
* 1. per-network MAC generation (default, no option in network config)
* 2. per-network full MAC randomization
* 3. per-network MAC override
*/
if (!l_settings_get_bool(settings, "Settings",
"AlwaysRandomizeAddress",
&full_random))
full_random = false;
value = l_settings_get_value(settings, "Settings",
"AddressOverride");
if (value) {
if (util_string_to_address(value, new_addr) &&
util_is_valid_sta_address(new_addr))
override = true;
else
l_warn("[Network].AddressOverride is not a valid "
"MAC address");
}
if (override && full_random) {
l_warn("Cannot use both AlwaysRandomizeAddress and "
"AddressOverride concurrently, defaulting to override");
full_random = false;
}
if (override)
handshake_state_set_supplicant_address(hs, new_addr);
else if (full_random) {
wiphy_generate_random_address(wiphy, new_addr);
handshake_state_set_supplicant_address(hs, new_addr);
}
return hs; return hs;
no_psk:
l_warn("Missing network PSK/passphrase");
not_supported: not_supported:
handshake_state_free(hs); handshake_state_free(hs);
return NULL; return NULL;
} }