diff options
author | Łukasz Zemczak <sil2100@vexillium.org> | 2020-03-20 10:27:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-20 10:27:35 +0100 |
commit | 2427ab267b24daa3504345be4ee6be7f286056a3 (patch) | |
tree | 4b0970d11ee0bbec59c81632ce139d985cbe9ae1 | |
parent | 261c379619b2128f62f8e8ae5d974fcf35677386 (diff) |
Fix quotation of WPA PSK 64 hex-digit keys for networkd (#120)
* Fix quotation of WPA PSK hex passthrough for networkd when supplied with a 64 hex-digit string
* Typo, was supposed to be 63
Co-authored-by: Łukasz 'sil2100' Zemczak <lukasz.zemczak@canonical.com>
-rw-r--r-- | src/networkd.c | 27 | ||||
-rw-r--r-- | tests/generator/test_auth.py | 61 | ||||
-rw-r--r-- | tests/generator/test_wifis.py | 26 |
3 files changed, 93 insertions, 21 deletions
diff --git a/src/networkd.c b/src/networkd.c index a91a329..7555db3 100644 --- a/src/networkd.c +++ b/src/networkd.c @@ -16,7 +16,9 @@ */ #include <stdlib.h> +#include <string.h> #include <unistd.h> +#include <ctype.h> #include <errno.h> #include <sys/stat.h> @@ -667,7 +669,7 @@ write_rules_file(net_definition* def, const char* rootdir) } static void -append_wpa_auth_conf(GString* s, const authentication_settings* auth) +append_wpa_auth_conf(GString* s, const authentication_settings* auth, const char* id) { switch (auth->key_management) { case KEY_MANAGEMENT_NONE: @@ -712,7 +714,24 @@ append_wpa_auth_conf(GString* s, const authentication_settings* auth) } if (auth->password) { if (auth->key_management == KEY_MANAGEMENT_WPA_PSK) { - g_string_append_printf(s, " psk=\"%s\"\n", auth->password); + size_t len = strlen(auth->password); + if (len == 64) { + /* must be a hex-digit key representation */ + for (unsigned i = 0; i < 64; ++i) + if (!isxdigit(auth->password[i])) { + g_fprintf(stderr, "ERROR: %s: PSK length of 64 is only supported for hex-digit representation\n", id); + exit(1); + } + /* this is required to be unquoted */ + g_string_append_printf(s, " psk=%s\n", auth->password); + } else if (len < 8 || len > 63) { + /* per wpa_supplicant spec, passphrase needs to be between 8 + and 63 characters */ + g_fprintf(stderr, "ERROR: %s: ASCII passphrase must be between 8 and 63 characters (inclusive)\n", id); + exit(1); + } else { + g_string_append_printf(s, " psk=\"%s\"\n", auth->password); + } } else { if (strncmp(auth->password, "hash:", 5) == 0) { g_string_append_printf(s, " password=%s\n", auth->password); @@ -802,7 +821,7 @@ write_wpa_conf(net_definition* def, const char* rootdir) /* wifi auth trumps netdef auth */ if (ap->has_auth) { - append_wpa_auth_conf(s, &ap->auth); + append_wpa_auth_conf(s, &ap->auth, ap->ssid); } else { g_string_append(s, " key_mgmt=NONE\n"); @@ -813,7 +832,7 @@ write_wpa_conf(net_definition* def, const char* rootdir) else { /* wired 802.1x auth or similar */ g_string_append(s, "network={\n"); - append_wpa_auth_conf(s, &def->auth); + append_wpa_auth_conf(s, &def->auth, def->id); g_string_append(s, "}\n"); } diff --git a/tests/generator/test_auth.py b/tests/generator/test_auth.py index 776bfcb..f35f3f8 100644 --- a/tests/generator/test_auth.py +++ b/tests/generator/test_auth.py @@ -31,11 +31,17 @@ class TestNetworkd(TestBase): wl0: access-points: "Joe's Home": - password: "s3kr1t" + password: "s0s3kr1t" "Luke's Home": auth: key-management: psk password: "4lsos3kr1t" + "BobsHome": + password: "e03ce667c87bc81ca968d9120ca37f89eb09aec3c55b80386e5d772efd6b926e" + "BillsHome": + auth: + key-management: psk + password: "db3b0acf5653aeaddd5fe034fb9f07175b2864f847b005aaa2f09182d9411b04" workplace: auth: key-management: eap @@ -102,6 +108,20 @@ network={ ''', new_config) self.assertIn(''' network={ + ssid="BobsHome" + key_mgmt=WPA-PSK + psk=e03ce667c87bc81ca968d9120ca37f89eb09aec3c55b80386e5d772efd6b926e +} +''', new_config) + self.assertIn(''' +network={ + ssid="BillsHome" + key_mgmt=WPA-PSK + psk=db3b0acf5653aeaddd5fe034fb9f07175b2864f847b005aaa2f09182d9411b04 +} +''', new_config) + self.assertIn(''' +network={ ssid="workplace2" key_mgmt=WPA-EAP eap=PEAP @@ -153,7 +173,7 @@ network={ network={ ssid="Joe's Home" key_mgmt=WPA-PSK - psk="s3kr1t" + psk="s0s3kr1t" } ''', new_config) self.assertEqual(stat.S_IMODE(os.fstat(f.fileno()).st_mode), 0o600) @@ -219,7 +239,7 @@ class TestNetworkManager(TestBase): wl0: access-points: "Joe's Home": - password: "s3kr1t" + password: "s0s3kr1t" "Luke's Home": auth: key-management: psk @@ -286,7 +306,7 @@ mode=infrastructure [wifi-security] key-mgmt=wpa-psk -psk=s3kr1t +psk=s0s3kr1t ''', 'wl0-Luke%27s%20Home': '''[connection] id=netplan-wl0-Luke's Home @@ -524,3 +544,36 @@ class TestConfigErrors(TestBase): auth: method: bogus''', expect_fail=True) self.assertIn("unknown EAP method 'bogus'", err) + + def test_auth_networkd_wifi_psk_too_big(self): + err = self.generate('''network: + version: 2 + wifis: + wl0: + access-points: + "Joe's Home": + password: "LoremipsumdolorsitametconsecteturadipiscingelitCrastemporvelitnunc" + dhcp4: yes''', expect_fail=True) + self.assertIn("ASCII passphrase must be between 8 and 63 characters (inclusive)", err) + + def test_auth_networkd_wifi_psk_too_small(self): + err = self.generate('''network: + version: 2 + wifis: + wl0: + access-points: + "Joe's Home": + password: "p4ss" + dhcp4: yes''', expect_fail=True) + self.assertIn("ASCII passphrase must be between 8 and 63 characters (inclusive)", err) + + def test_auth_networkd_wifi_psk_64_non_hexdigit(self): + err = self.generate('''network: + version: 2 + wifis: + wl0: + access-points: + "Joe's Home": + password: "LoremipsumdolorsitametconsecteturadipiscingelitCrastemporvelitnu" + dhcp4: yes''', expect_fail=True) + self.assertIn("PSK length of 64 is only supported for hex-digit representation", err) diff --git a/tests/generator/test_wifis.py b/tests/generator/test_wifis.py index 2182450..3e38be9 100644 --- a/tests/generator/test_wifis.py +++ b/tests/generator/test_wifis.py @@ -31,9 +31,9 @@ class TestNetworkd(TestBase): wl0: access-points: "Joe's Home": - password: "s3kr1t" + password: "s0s3kr1t" workplace: - password: "c0mpany" + password: "c0mpany1" peer2peer: mode: adhoc dhcp4: yes''') @@ -58,14 +58,14 @@ network={ network={ ssid="workplace" key_mgmt=WPA-PSK - psk="c0mpany" + psk="c0mpany1" } ''', new_config) self.assertIn(''' network={ ssid="Joe's Home" key_mgmt=WPA-PSK - psk="s3kr1t" + psk="s0s3kr1t" } ''', new_config) self.assertEqual(stat.S_IMODE(os.fstat(f.fileno()).st_mode), 0o600) @@ -81,7 +81,7 @@ network={ wl0: access-points: workplace: - password: "c0mpany" + password: "c0mpany1" dhcp4: yes routes: - to: 10.10.10.0/24 @@ -117,7 +117,7 @@ unmanaged-devices+=interface-name:wl0,''') driver: foo access-points: workplace: - password: "c0mpany" + password: "c0mpany1" dhcp4: yes''', expect_fail=True) self.assertIn('networkd backend does not support wifi with match:', err) @@ -128,7 +128,7 @@ unmanaged-devices+=interface-name:wl0,''') wl0: access-points: workplace: - password: "c0mpany" + password: "c0mpany1" mode: ap dhcp4: yes''', expect_fail=True) self.assertIn('networkd does not support wifi in access point mode', err) @@ -144,9 +144,9 @@ class TestNetworkManager(TestBase): wl0: access-points: "Joe's Home": - password: "s3kr1t" + password: "s0s3kr1t" workplace: - password: "c0mpany" + password: "c0mpany1" dhcp4: yes''') self.assert_nm({'wl0-Joe%27s%20Home': '''[connection] @@ -169,7 +169,7 @@ mode=infrastructure [wifi-security] key-mgmt=wpa-psk -psk=s3kr1t +psk=s0s3kr1t ''', 'wl0-workplace': '''[connection] id=netplan-wl0-workplace @@ -191,7 +191,7 @@ mode=infrastructure [wifi-security] key-mgmt=wpa-psk -psk=c0mpany +psk=c0mpany1 '''}) self.assert_networkd({}) self.assert_nm_udev(None) @@ -265,7 +265,7 @@ mode=infrastructure access-points: homenet: mode: ap - password: s3cret''') + password: s0s3cret''') self.assert_nm({'wl0-homenet': '''[connection] id=netplan-wl0-homenet @@ -287,7 +287,7 @@ mode=ap [wifi-security] key-mgmt=wpa-psk -psk=s3cret +psk=s0s3cret '''}) self.assert_networkd({}) self.assert_nm_udev(None) |