Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion autotests/testPMKSA-SAE/connection_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys

sys.path.append('../util')
from iwd import IWD
from iwd import IWD, FailedEx
from iwd import PSKAgent
from iwd import NetworkType
from hostapd import HostapdCLI
Expand Down Expand Up @@ -94,6 +94,36 @@ def test_pmksa_sae(self):
self.hostapd.wait_for_event("AP-ENABLED")
self.validate_connection(self.wd, "ssidSAE", self.hostapd, 19)

def test_pmksa_forget_network(self):
psk_agent = PSKAgent(["secret123", "wrong_password"])
self.wd.register_psk_agent(psk_agent)

devices = self.wd.list_devices(1)
self.assertIsNotNone(devices)
device = devices[0]

device.disconnect()

network = device.get_ordered_network("ssidSAE", full_scan=True)

self.assertEqual(network.type, NetworkType.psk)

network.network_object.connect()

condition = 'obj.state == DeviceState.connected'
self.wd.wait_for_object_condition(device, condition)

self.wd.wait(2)

testutil.test_iface_operstate(intf=device.name)
testutil.test_ifaces_connected(if0=device.name, if1=self.hostapd.ifname)

known_network = self.wd.list_known_networks()[0]
known_network.forget()

with self.assertRaises(FailedEx):
network.network_object.connect()

def setUp(self):
self.hostapd.default()
self.wd = IWD(True)
Expand Down
41 changes: 31 additions & 10 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <stdbool.h>
#include <string.h>

#include <ell/ell.h>

#include "src/iwd.h"
#include "src/common.h"
#include "src/ie.h"
Expand Down Expand Up @@ -64,27 +66,27 @@ bool security_from_str(const char *str, enum security *security)
return true;
}

#define AKM_IS_PSK(akm) \
( \
akm & (IE_RSN_AKM_SUITE_PSK | \
#define AKMS_PSK \
(IE_RSN_AKM_SUITE_PSK | \
IE_RSN_AKM_SUITE_PSK_SHA256 | \
IE_RSN_AKM_SUITE_FT_USING_PSK | \
IE_RSN_AKM_SUITE_SAE_SHA256 | \
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256) \
)
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)

#define AKM_IS_8021X(akm) \
( \
akm & (IE_RSN_AKM_SUITE_8021X | \
#define AKMS_8021X \
(IE_RSN_AKM_SUITE_8021X | \
IE_RSN_AKM_SUITE_8021X_SHA256 | \
IE_RSN_AKM_SUITE_FT_OVER_8021X | \
IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384 | \
IE_RSN_AKM_SUITE_FILS_SHA256 | \
IE_RSN_AKM_SUITE_FILS_SHA384 | \
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA256 | \
IE_RSN_AKM_SUITE_FT_OVER_FILS_SHA384 | \
IE_RSN_AKM_SUITE_OSEN) \
)
IE_RSN_AKM_SUITE_OSEN)

#define AKM_IS_PSK(akm) (akm & AKMS_PSK)

#define AKM_IS_8021X(akm) (akm & AKMS_8021X)

enum security security_determine(uint16_t bss_capability,
const struct ie_rsn_info *info)
Expand All @@ -103,3 +105,22 @@ enum security security_determine(uint16_t bss_capability,

return SECURITY_NONE;
}

/* Returns all possible AKMs (as bitmask) for a given security type */
uint32_t security_to_akms(enum security security)
{
switch (security) {
case SECURITY_WEP:
l_warn("WEP security type not supported");
/* Fall through */
case SECURITY_NONE:
return 0;
case SECURITY_PSK:
return AKMS_PSK;
case SECURITY_8021X:
return AKMS_8021X;
default:
l_warn("Unhandled security type: %u", security);
return 0;
}
}
1 change: 1 addition & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ const char *security_to_str(enum security security);
bool security_from_str(const char *str, enum security *security);
enum security security_determine(uint16_t bss_capability,
const struct ie_rsn_info *info);
uint32_t security_to_akms(enum security security);
5 changes: 5 additions & 0 deletions src/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "src/handshake.h"
#include "src/band.h"
#include "src/util.h"
#include "src/pmksa.h"

#define SAE_PT_SETTING "SAE-PT-Group%u"

Expand Down Expand Up @@ -2051,6 +2052,10 @@ static void emit_known_network_removed(struct station *station, void *user_data)

l_queue_destroy(network->secrets, eap_secret_info_free);
network->secrets = NULL;

pmksa_cache_flush_ssid((uint8_t *)info->ssid,
sizeof(info->ssid),
security_to_akms(network->security));
}

connected_network = station_get_connected_network(station);
Expand Down
30 changes: 30 additions & 0 deletions src/pmksa.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,36 @@ int pmksa_cache_flush(void)
return 0;
}

/*
* Flushes all PMKSA entries that match an SSID
*/
int pmksa_cache_flush_ssid(const uint8_t *ssid, size_t ssid_len, uint32_t akms)
{
int i;
int used = cache.used;
int remaining = 0;

for (i = 0; i < used; i++) {
/* Check that the both the AKM matches as well as the SSID */
if ((cache.data[i]->akm & akms) &&
!memcmp(ssid, cache.data[i]->ssid,
cache.data[i]->ssid_len)) {
pmksa_cache_free(cache.data[i]);
continue;
}

cache.data[remaining] = cache.data[i];
remaining += 1;
}

cache.used = remaining;

for (i = cache.used >> 1; i >= 0; i--)
__minheap_sift_down(cache.data, cache.used, i, &ops);

return used - remaining;
}

int pmksa_cache_free(struct pmksa *pmksa)
{
if (driver_remove)
Expand Down
1 change: 1 addition & 0 deletions src/pmksa.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct pmksa *pmksa_cache_get(const uint8_t spa[static 6],
int pmksa_cache_put(struct pmksa *pmksa);
int pmksa_cache_expire(uint64_t cutoff);
int pmksa_cache_flush(void);
int pmksa_cache_flush_ssid(const uint8_t *ssid, size_t ssid_len, uint32_t akms);
int pmksa_cache_free(struct pmksa *pmksa);

uint64_t pmksa_lifetime(void);
Expand Down
Loading