ifcfg-rh: handle quotes of WPA_PSK key inside shvar.h

It is wrong to move the handling of quotes outside of shvar.h.
The ifcfg-rh core library (shvar.h) should handle quotation
transparently.

It is also wrong to encode meaning of the WPA_PSK depending on whether
the value is quoted or not. A psk that is 64 chars *must* be in hex
representation, and anything else is taken literal.

Also, the special handling of bash-syntax with $' was wrong. Including
the unit test "keys-test-wifi-wpa-psk-2" which contained invalid shell.
Support for $' must be done inside of shvar.h, for all properties alike
not just for WPA_PSK.
This commit is contained in:
Thomas Haller 2016-10-28 21:26:24 +02:00
parent 5a43b733b9
commit 39a79b0ee7
4 changed files with 27 additions and 72 deletions

View file

@ -2416,9 +2416,8 @@ parse_wpa_psk (shvarFile *ifcfg,
GError **error)
{
shvarFile *keys_ifcfg;
char *psk = NULL, *p, *hashed = NULL;
gs_free char *psk = NULL;
size_t plen;
gboolean quoted = FALSE;
/* Passphrase must be between 10 and 66 characters in length because WPA
* hex keys are exactly 64 characters (no quoting), and WPA passphrases
@ -2429,64 +2428,36 @@ parse_wpa_psk (shvarFile *ifcfg,
/* Try to get keys from the "shadow" key file */
keys_ifcfg = utils_get_keys_ifcfg (file, FALSE);
if (keys_ifcfg) {
psk = svGetValue (keys_ifcfg, "WPA_PSK", TRUE);
psk = svGetValue (keys_ifcfg, "WPA_PSK", FALSE);
svCloseFile (keys_ifcfg);
}
/* Fall back to the original ifcfg */
if (!psk)
psk = svGetValue (ifcfg, "WPA_PSK", TRUE);
psk = svGetValue (ifcfg, "WPA_PSK", FALSE);
if (!psk)
return NULL;
p = psk;
plen = strlen (p);
plen = strlen (psk);
if ( (plen >= 2 && (p[0] == '"' || p[0] == '\'') && p[0] == p[plen - 1])
|| (plen >= 3 && p[0] == '$' && p[1] == '\'' && p[1] == p[plen - 1]))
quoted = TRUE;
if (!quoted && (strlen (psk) == 64)) {
if (plen == 64) {
/* Verify the hex PSK; 64 digits */
while (*p) {
if (!g_ascii_isxdigit (*p++)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid WPA_PSK (contains non-hexadecimal characters)");
goto out;
}
if (!NM_STRCHAR_ALL (psk, ch, g_ascii_isxdigit (ch))) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid WPA_PSK (contains non-hexadecimal characters)");
return NULL;
}
hashed = g_strdup (psk);
} else {
/* Prior to 4f6eef9e77265484555663cf666cde4fa8323469 and
* 28e2e446868b94b92edc4a82aa0bf1e3eda8ec54 the writer may not have
* properly quoted passphrases, so just handle anything that's unquoted
* and between 8 and 63 characters as a passphrase.
*/
/* Get rid of the quotes */
hashed = utils_single_unquote_string (p);
/* Length check */
if (strlen (hashed) < 8 || strlen (hashed) > 63) {
if (plen < 8 || plen > 63) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid WPA_PSK (passphrases must be between "
"8 and 63 characters long (inclusive))");
g_free (hashed);
hashed = NULL;
goto out;
return NULL;
}
}
if (!hashed) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid WPA_PSK (doesn't look like a passphrase or hex key)");
goto out;
}
out:
g_free (psk);
return hashed;
return g_steal_pointer (&psk);
}
static gboolean

View file

@ -562,7 +562,8 @@ write_wireless_security_setting (NMConnection *connection,
GError **error)
{
NMSettingWirelessSecurity *s_wsec;
const char *key_mgmt, *auth_alg, *key, *proto, *cipher, *psk;
const char *key_mgmt, *auth_alg, *key, *proto, *cipher;
const char *psk = NULL;
gboolean wep = FALSE, wpa = FALSE, dynamic_wep = FALSE;
char *tmp;
guint32 i, num;
@ -739,30 +740,15 @@ write_wireless_security_setting (NMConnection *connection,
svSetValue (ifcfg, "CIPHER_GROUP", str->str, FALSE);
g_string_free (str, TRUE);
/* WPA Passphrase */
if (wpa) {
char *quoted = NULL;
if (wpa)
psk = nm_setting_wireless_security_get_psk (s_wsec);
if (psk && (strlen (psk) != 64)) {
/* Quote the PSK since it's a passphrase */
quoted = utils_single_quote_string (psk);
}
set_secret (ifcfg,
"WPA_PSK",
quoted ? quoted : psk,
"WPA_PSK_FLAGS",
nm_setting_wireless_security_get_psk_flags (s_wsec),
TRUE);
g_free (quoted);
} else {
set_secret (ifcfg,
"WPA_PSK",
NULL,
"WPA_PSK_FLAGS",
NM_SETTING_SECRET_FLAG_NONE,
FALSE);
}
set_secret (ifcfg,
"WPA_PSK",
psk,
"WPA_PSK_FLAGS",
wpa ? nm_setting_wireless_security_get_psk_flags (s_wsec) : NM_SETTING_SECRET_FLAG_NONE,
FALSE);
return TRUE;
}

View file

@ -1,2 +1,2 @@
WPA_PSK=$'They\'re really saying I love you. >>`<< \'
WPA_PSK="They're really saying I love you. >>\`<< '"

View file

@ -2547,7 +2547,7 @@ test_read_wifi_wpa_psk_2 (void)
s_wsec = nm_connection_get_setting_wireless_security (connection);
g_assert (s_wsec);
g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "They're really saying I love you. >>`<< \\");
g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "They're really saying I love you. >>`<< '");
g_object_unref (connection);
}
@ -2586,12 +2586,10 @@ test_read_wifi_wpa_psk_unquoted (void)
static void
test_read_wifi_wpa_psk_unquoted2 (void)
{
/* Ensure a quoted 64-character WPA passphrase will fail since passphrases
* must be between 8 and 63 ASCII characters inclusive per the WPA spec.
*/
gs_unref_object NMConnection *connection = NULL;
_connection_from_file_fail (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2",
NULL, TYPE_WIRELESS, NULL);
connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2",
NULL, TYPE_WIRELESS, NULL);
}
static void