mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-17 09:29:22 +01:00
wiphy: Check early that a BSS supports compatible ciphers.
In the D-bus .Connect call return an error immediately if we find that there's no common cipher supported between iwd, the network adapter and the AP. This is to avoid asking the agent for the passkey if we know the connection will fail. An alternative would be to only show networks that we can connect to in the scan results on D-bus but I suspect that would cause more pain to users debugging their wifi setups on average. For now, if a passphrase is needed we check once before querying for passphrase and recheck afterwards when we're about to associate.
This commit is contained in:
parent
4bf109a7ce
commit
00cafb2cc5
116
src/wiphy.c
116
src/wiphy.c
@ -230,10 +230,60 @@ static void genl_connect_cb(struct l_genl_msg *msg, void *user_data)
|
||||
}
|
||||
}
|
||||
|
||||
static int mlme_authenticate_cmd(struct network *network)
|
||||
static enum ie_rsn_cipher_suite wiphy_select_cipher(struct wiphy *wiphy,
|
||||
uint16_t mask)
|
||||
{
|
||||
mask &= wiphy->pairwise_ciphers;
|
||||
|
||||
/* CCMP is our first choice, TKIP second */
|
||||
if (mask & IE_RSN_CIPHER_SUITE_CCMP)
|
||||
return IE_RSN_CIPHER_SUITE_CCMP;
|
||||
|
||||
if (mask & IE_RSN_CIPHER_SUITE_TKIP)
|
||||
return IE_RSN_CIPHER_SUITE_TKIP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct scan_bss *network_select_bss(struct wiphy *wiphy,
|
||||
struct network *network)
|
||||
{
|
||||
struct l_queue *bss_list = network->bss_list;
|
||||
const struct l_queue_entry *bss_entry;
|
||||
|
||||
/* TODO: sort the list by RSSI, potentially other criteria. */
|
||||
|
||||
switch (network->ssid_security) {
|
||||
case SCAN_SSID_SECURITY_NONE:
|
||||
/* Pick the first bss (strongest signal) */
|
||||
return l_queue_peek_head(bss_list);
|
||||
|
||||
case SCAN_SSID_SECURITY_PSK:
|
||||
/* Pick the first bss that advertises any cipher we support. */
|
||||
for (bss_entry = l_queue_get_entries(bss_list); bss_entry;
|
||||
bss_entry = bss_entry->next) {
|
||||
struct scan_bss *bss = bss_entry->data;
|
||||
uint16_t pairwise_ciphers, group_ciphers;
|
||||
|
||||
bss_get_supported_ciphers(bss, &pairwise_ciphers,
|
||||
&group_ciphers);
|
||||
|
||||
if (wiphy_select_cipher(wiphy, pairwise_ciphers) &&
|
||||
wiphy_select_cipher(wiphy,
|
||||
group_ciphers))
|
||||
return bss;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int mlme_authenticate_cmd(struct network *network, struct scan_bss *bss)
|
||||
{
|
||||
struct netdev *netdev = network->netdev;
|
||||
struct scan_bss *bss = l_queue_peek_head(network->bss_list);
|
||||
uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
|
||||
struct l_genl_msg *msg;
|
||||
|
||||
@ -257,6 +307,8 @@ static void passphrase_callback(enum agent_result result,
|
||||
{
|
||||
struct network *network = user_data;
|
||||
struct netdev *netdev = network->netdev;
|
||||
struct wiphy *wiphy = netdev->wiphy;
|
||||
struct scan_bss *bss;
|
||||
|
||||
l_debug("result %d", result);
|
||||
|
||||
@ -265,9 +317,16 @@ static void passphrase_callback(enum agent_result result,
|
||||
if (result != AGENT_RESULT_OK) {
|
||||
dbus_pending_reply(&netdev->connect_pending,
|
||||
dbus_error_aborted(netdev->connect_pending));
|
||||
l_settings_free(network->settings);
|
||||
network->settings = NULL;
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
|
||||
bss = network_select_bss(wiphy, network);
|
||||
|
||||
/* Did all good BSSes go away while we waited */
|
||||
if (!bss) {
|
||||
dbus_pending_reply(&netdev->connect_pending,
|
||||
dbus_error_failed(netdev->connect_pending));
|
||||
goto err;
|
||||
}
|
||||
|
||||
l_free(network->psk);
|
||||
@ -280,13 +339,8 @@ static void passphrase_callback(enum agent_result result,
|
||||
"Ensure Crypto Engine is properly configured");
|
||||
dbus_pending_reply(&netdev->connect_pending,
|
||||
dbus_error_failed(netdev->connect_pending));
|
||||
l_settings_free(network->settings);
|
||||
network->settings = NULL;
|
||||
|
||||
l_free(network->psk);
|
||||
network->psk = NULL;
|
||||
|
||||
return;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -296,25 +350,19 @@ static void passphrase_callback(enum agent_result result,
|
||||
*/
|
||||
network->update_psk = true;
|
||||
|
||||
mlme_authenticate_cmd(network);
|
||||
}
|
||||
mlme_authenticate_cmd(network, bss);
|
||||
return;
|
||||
|
||||
static enum ie_rsn_cipher_suite wiphy_select_cipher(struct wiphy *wiphy,
|
||||
uint16_t mask)
|
||||
{
|
||||
mask &= wiphy->pairwise_ciphers;
|
||||
err:
|
||||
l_settings_free(network->settings);
|
||||
network->settings = NULL;
|
||||
|
||||
/* CCMP is our first choice, TKIP second */
|
||||
if (mask & IE_RSN_CIPHER_SUITE_CCMP)
|
||||
return IE_RSN_CIPHER_SUITE_CCMP;
|
||||
|
||||
if (mask & IE_RSN_CIPHER_SUITE_TKIP)
|
||||
return IE_RSN_CIPHER_SUITE_TKIP;
|
||||
|
||||
return 0;
|
||||
l_free(network->psk);
|
||||
network->psk = NULL;
|
||||
}
|
||||
|
||||
static struct l_dbus_message *network_connect_psk(struct network *network,
|
||||
struct scan_bss *bss,
|
||||
struct l_dbus_message *message)
|
||||
{
|
||||
struct netdev *netdev = network->netdev;
|
||||
@ -356,7 +404,7 @@ static struct l_dbus_message *network_connect_psk(struct network *network,
|
||||
if (!network->agent_request)
|
||||
return dbus_error_no_agent(message);
|
||||
} else
|
||||
mlme_authenticate_cmd(network);
|
||||
mlme_authenticate_cmd(network, bss);
|
||||
|
||||
netdev->connect_pending = l_dbus_message_ref(message);
|
||||
return NULL;
|
||||
@ -368,17 +416,29 @@ static struct l_dbus_message *network_connect(struct l_dbus *dbus,
|
||||
{
|
||||
struct network *network = user_data;
|
||||
struct netdev *netdev = network->netdev;
|
||||
struct scan_bss *bss;
|
||||
|
||||
l_debug("");
|
||||
|
||||
if (netdev->connect_pending)
|
||||
return dbus_error_busy(message);
|
||||
|
||||
/*
|
||||
* Select the best BSS to use at this time. If we have to query the
|
||||
* agent this may not be the final choice because BSS visibility can
|
||||
* change while we wait for the agent.
|
||||
*/
|
||||
bss = network_select_bss(netdev->wiphy, network);
|
||||
|
||||
/* None of the BSSes is compatible with our stack */
|
||||
if (!bss)
|
||||
return dbus_error_not_supported(message);
|
||||
|
||||
switch (network->ssid_security) {
|
||||
case SCAN_SSID_SECURITY_PSK:
|
||||
return network_connect_psk(network, message);
|
||||
return network_connect_psk(network, bss, message);
|
||||
case SCAN_SSID_SECURITY_NONE:
|
||||
mlme_authenticate_cmd(network);
|
||||
mlme_authenticate_cmd(network, bss);
|
||||
netdev->connect_pending = l_dbus_message_ref(message);
|
||||
return NULL;
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user