diff --git a/src/network.c b/src/network.c index 22c9cfdd..114e4746 100644 --- a/src/network.c +++ b/src/network.c @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -53,6 +54,7 @@ #include "src/blacklist.h" #include "src/util.h" #include "src/erp.h" +#include "src/handshake.h" static uint32_t known_networks_watch; static uint32_t anqp_watch; @@ -259,7 +261,7 @@ enum security network_get_security(const struct network *network) return network->security; } -const uint8_t *network_get_psk(struct network *network) +static const uint8_t *network_get_psk(struct network *network) { int r; @@ -281,11 +283,6 @@ const uint8_t *network_get_psk(struct network *network) return network->psk; } -const char *network_get_passphrase(const struct network *network) -{ - return network->passphrase; -} - static bool __network_set_passphrase(struct network *network, const char *passphrase) { @@ -388,6 +385,113 @@ static bool network_set_8021x_secrets(struct network *network) 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) { const char *ssid = network_get_ssid(network); diff --git a/src/network.h b/src/network.h index 5d23216e..14a8fdc8 100644 --- a/src/network.h +++ b/src/network.h @@ -28,6 +28,7 @@ struct device; struct station; struct network; struct scan_bss; +struct handshake_state; void network_connected(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_path(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); struct l_queue *network_get_secrets(const struct network *network); int network_get_signal_strength(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); + +int network_handshake_setup(struct network *network, + struct handshake_state *hs); + void network_sync_settings(struct network *network); const struct network_info *network_get_info(const struct network *network); diff --git a/src/station.c b/src/station.c index 32fe0374..9bf3bbce 100644 --- a/src/station.c +++ b/src/station.c @@ -865,16 +865,8 @@ static struct handshake_state *station_handshake_setup(struct station *station, struct network *network, 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 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); @@ -883,45 +875,8 @@ static struct handshake_state *station_handshake_setup(struct station *station, if (station_build_handshake_rsn(hs, wiphy, network, bss) < 0) goto not_supported; - ssid = network_get_ssid(network); - handshake_state_set_ssid(hs, (void *) ssid, strlen(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); - } - - 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 (network_handshake_setup(network, hs) < 0) + goto not_supported; /* * 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)) 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; -no_psk: - l_warn("Missing network PSK/passphrase"); not_supported: handshake_state_free(hs); - return NULL; }