From f0fb1d2c89d95f4732e44b8587c9fcac9548bc96 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Sat, 29 Apr 2017 03:53:29 +0200 Subject: [PATCH] autotests: Add a Preauthentication test Unfortunately this doesn't currently ensure that the preauthentication has succeeded and that later the PMKSA from the preauthentication was used in the transition, only that the preauthentication process doesn't break the transition. For now this can be confirmed by looking at the testrunner -v output to see that the line "EAP completed with eapSuccess" appears before the following line, and not after: src/device.c:device_enter_state() Old State: connected, new state: roaming --- autotests/misc/certs/radius-clients.text | 1 + autotests/testPreauth-roam/TestPreauth.8021x | 6 + .../testPreauth-roam/eaptls-preauth-1.conf | 36 +++++ .../testPreauth-roam/eaptls-preauth-2.conf | 32 +++++ autotests/testPreauth-roam/hw.conf | 8 ++ autotests/testPreauth-roam/test.py | 135 ++++++++++++++++++ 6 files changed, 218 insertions(+) create mode 100644 autotests/misc/certs/radius-clients.text create mode 100644 autotests/testPreauth-roam/TestPreauth.8021x create mode 100644 autotests/testPreauth-roam/eaptls-preauth-1.conf create mode 100644 autotests/testPreauth-roam/eaptls-preauth-2.conf create mode 100644 autotests/testPreauth-roam/hw.conf create mode 100644 autotests/testPreauth-roam/test.py diff --git a/autotests/misc/certs/radius-clients.text b/autotests/misc/certs/radius-clients.text new file mode 100644 index 00000000..3bb0e980 --- /dev/null +++ b/autotests/misc/certs/radius-clients.text @@ -0,0 +1 @@ +0.0.0.0/0 secret diff --git a/autotests/testPreauth-roam/TestPreauth.8021x b/autotests/testPreauth-roam/TestPreauth.8021x new file mode 100644 index 00000000..fe8a2e46 --- /dev/null +++ b/autotests/testPreauth-roam/TestPreauth.8021x @@ -0,0 +1,6 @@ +[Security] +EAP-Method=TLS +EAP-TLS-CACert=/tmp/certs/cert-ca.pem +EAP-TLS-ClientCert=/tmp/certs/cert-client.pem +EAP-TLS-ClientKey=/tmp/certs/cert-client-key-pkcs8.pem +EAP-Identity=abc@example.com diff --git a/autotests/testPreauth-roam/eaptls-preauth-1.conf b/autotests/testPreauth-roam/eaptls-preauth-1.conf new file mode 100644 index 00000000..0c7f96a7 --- /dev/null +++ b/autotests/testPreauth-roam/eaptls-preauth-1.conf @@ -0,0 +1,36 @@ +hw_mode=g +channel=1 +ssid=TestPreauth +utf8_ssid=1 +ctrl_interface=/var/run/hostapd + +wpa=2 +wpa_key_mgmt=WPA-EAP +wpa_pairwise=CCMP +ieee8021x=1 +wpa_ptk_rekey=30 +wpa_group_rekey=80 +ieee80211w=1 + +# Run the RADIUS server in the BSS 0 hostapd only, listen for BSS 1 connections +eap_server=1 +eap_user_file=/tmp/certs/eap-user-tls.text +ca_cert=/tmp/certs/cert-ca.pem +server_cert=/tmp/certs/cert-server.pem +private_key=/tmp/certs/cert-server-key.pem +server_id=testeap +radius_server_clients=/tmp/certs/radius-clients.text +radius_server_auth_port=1812 +nas_identifier=testeap1 + +rsn_preauth=1 +rsn_preauth_interfaces=wln0 wln1 +disable_pmksa_caching=0 + +# Allow PMK cache to be shared opportunistically among configured interfaces +# and BSSes (i.e., all configurations within a single hostapd process). +okc=1 + +ap_table_expiration_time=36000 +ap_table_max_size=10 +rrm_neighbor_report=1 diff --git a/autotests/testPreauth-roam/eaptls-preauth-2.conf b/autotests/testPreauth-roam/eaptls-preauth-2.conf new file mode 100644 index 00000000..bddcca69 --- /dev/null +++ b/autotests/testPreauth-roam/eaptls-preauth-2.conf @@ -0,0 +1,32 @@ +hw_mode=g +channel=2 +ssid=TestPreauth +utf8_ssid=1 +ctrl_interface=/var/run/hostapd + +wpa=2 +wpa_key_mgmt=WPA-EAP +wpa_pairwise=CCMP +ieee8021x=1 +wpa_ptk_rekey=30 +wpa_group_rekey=80 +ieee80211w=1 + +# For EAP connect to the RADIUS server in the BSS 0 +own_ip_addr=127.0.0.1 +nas_identifier=testeap2 +auth_server_addr=127.0.0.1 +auth_server_port=1812 +auth_server_shared_secret=secret + +rsn_preauth=1 +rsn_preauth_interfaces=wln0 wln1 +disable_pmksa_caching=0 + +# Allow PMK cache to be shared opportunistically among configured interfaces +# and BSSes (i.e., all configurations within a single hostapd process). +okc=1 + +ap_table_expiration_time=36000 +ap_table_max_size=10 +rrm_neighbor_report=1 diff --git a/autotests/testPreauth-roam/hw.conf b/autotests/testPreauth-roam/hw.conf new file mode 100644 index 00000000..eba07167 --- /dev/null +++ b/autotests/testPreauth-roam/hw.conf @@ -0,0 +1,8 @@ +[SETUP] +num_radios=3 +max_test_exec_interval_sec=30 +tmpfs_extra_stuff=../misc/certs + +[HOSTAPD] +rad0=eaptls-preauth-1.conf +rad1=eaptls-preauth-2.conf diff --git a/autotests/testPreauth-roam/test.py b/autotests/testPreauth-roam/test.py new file mode 100644 index 00000000..b95d605f --- /dev/null +++ b/autotests/testPreauth-roam/test.py @@ -0,0 +1,135 @@ +#! /usr/bin/python3 + +import unittest +import sys, os + +sys.path.append('../util') +import iwd +from iwd import IWD +from iwd import PSKAgent +from iwd import NetworkType +from hwsim import Hwsim +from hostapd import HostapdCLI +from wiphy import wiphy_map + +class Test(unittest.TestCase): + def test_preauth_success(self): + hwsim = Hwsim() + + bss_hostapd = [None, None] + bss_radio = [None, None] + for wname in wiphy_map: + wiphy = wiphy_map[wname] + intf = list(wiphy.values())[0] + if intf.config and '1' in intf.config: + bss_idx = 0 + elif intf.config and '2' in intf.config: + bss_idx = 1 + else: + continue + + for path in hwsim.radios: + radio = hwsim.radios[path] + if radio.name == wname: + break + + bss_hostapd[bss_idx] = HostapdCLI(intf) + bss_radio[bss_idx] = radio + + rule0 = hwsim.rules.create() + rule0.source = bss_radio[0].addresses[0] + rule0.bidirectional = True + + rule1 = hwsim.rules.create() + rule1.source = bss_radio[1].addresses[0] + rule1.bidirectional = True + + # Fill in the neighbor AP tables in both BSSes. By default each + # instance knows only about current BSS, even inside one hostapd + # process. + # Roaming still works without the neighbor AP table but neighbor + # reports have to be disabled in the .conf files + bss0_nr = ''.join(bss_radio[0].addresses[0].split(':')) + \ + '8f0000005101060603000000' + bss1_nr = ''.join(bss_radio[1].addresses[0].split(':')) + \ + '8f0000005102060603000000' + + bss_hostapd[0].set_neighbor(bss_radio[1].addresses[0], 'TestPreauth', + bss1_nr) + bss_hostapd[1].set_neighbor(bss_radio[0].addresses[0], 'TestPreauth', + bss0_nr) + + wd = IWD() + + device = wd.list_devices()[0]; + + # Check that iwd selects BSS 0 first + rule0.signal = -2500 + rule1.signal = -3500 + + condition = 'not obj.scanning' + wd.wait_for_object_condition(device, condition) + + device.scan() + + condition = 'obj.scanning' + wd.wait_for_object_condition(device, condition) + + condition = 'not obj.scanning' + wd.wait_for_object_condition(device, condition) + + ordered_networks = device.get_ordered_networks() + + self.assertEqual(len(ordered_networks), 1) + ordered_network = ordered_networks[0] + self.assertEqual(ordered_network.name, "TestPreauth") + self.assertEqual(ordered_network.type, NetworkType.eap) + self.assertEqual(ordered_network.signal_strength, -2500) + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertFalse(bss_hostapd[0].list_sta()) + self.assertFalse(bss_hostapd[1].list_sta()) + + ordered_network.network_object.connect() + + condition = 'obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + self.assertTrue(bss_hostapd[0].list_sta()) + self.assertFalse(bss_hostapd[1].list_sta()) + + # Check that iwd starts transition to BSS 1 in less than 15 seconds + rule0.signal = -8000 + + condition = 'obj.state == DeviceState.roaming' + wd.wait_for_object_condition(device, condition, 15) + + # TODO: verify that the PMK from preauthentication was used + + # Check that iwd is on BSS 1 once out of roaming state and doesn't + # go through 'disconnected', 'autoconnect', 'connecting' in between + condition = 'obj.state != DeviceState.roaming' + wd.wait_for_object_condition(device, condition, 5) + + self.assertEqual(device.state, iwd.DeviceState.connected) + self.assertTrue(bss_hostapd[1].list_sta()) + + device.disconnect() + + condition = 'not obj.connected' + wd.wait_for_object_condition(ordered_network.network_object, condition) + + @classmethod + def setUpClass(cls): + IWD.copy_to_storage('TestPreauth.8021x') + + os.system('ifconfig lo up') + + @classmethod + def tearDownClass(cls): + IWD.clear_storage() + +if __name__ == '__main__': + unittest.main(exit=True)