From b57da413a62b6c175807278dc0996e11372399de Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Sun, 11 Apr 2021 14:09:28 +0200 Subject: [PATCH] Fix handling of wifi password with special characters We could cover the backtic case by using nowdoc instead of heredoc, but then there may still be problems with double quotes. Put the PBKDF2 hash instead of plaintext password in wpa_supplicant.conf to solve such problems. Closes #206 --- OptionsPopup.qml | 36 +++++++++++++++++++++++++++++++----- imagewriter.cpp | 22 ++++++++++++++++++++++ imagewriter.h | 1 + 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/OptionsPopup.qml b/OptionsPopup.qml index fa47de7..992fe66 100644 --- a/OptionsPopup.qml +++ b/OptionsPopup.qml @@ -241,21 +241,29 @@ Popup { Text { text: qsTr("SSID:") - color: parent.enabled ? "black" : "grey" + color: parent.enabled ? (fieldWifiSSID.indicateError ? "red" : "black") : "grey" } TextField { id: fieldWifiSSID Layout.minimumWidth: 200 + property bool indicateError: false + onTextEdited: { + indicateError = false + } } Text { text: qsTr("Password:") - color: parent.enabled ? "black" : "grey" + color: parent.enabled ? (fieldWifiPassword.indicateError ? "red" : "black") : "grey" } TextField { id: fieldWifiPassword Layout.minimumWidth: 200 echoMode: chkShowPassword.checked ? TextInput.Normal : TextInput.Password + property bool indicateError: false + onTextEdited: { + indicateError = false + } } CheckBox { @@ -351,6 +359,23 @@ Popup { fieldUserPassword.forceActiveFocus() return } + if (chkWifi.checked) + { + if (fieldWifiPassword.text.length < 8 || fieldWifiPassword.text.length > 64) + { + fieldWifiPassword.indicateError = true + fieldWifiPassword.forceActiveFocus() + } + if (fieldWifiSSID.text.length == 0) + { + fieldWifiSSID.indicateError = true + fieldWifiSSID.forceActiveFocus() + } + if (fieldWifiSSID.indicateError || fieldWifiPassword.indicateError) + { + return + } + } applySettings() saveSettings() @@ -508,10 +533,11 @@ Popup { wpaconfig += "update_config=1\n" wpaconfig += "network={\n" wpaconfig += "\tssid=\""+fieldWifiSSID.text+"\"\n" - wpaconfig += "\tpsk=\""+fieldWifiPassword.text+"\"\n" + var cryptedPsk = fieldWifiPassword.text.length == 64 ? fieldWifiPassword.text : imageWriter.pbkdf2(fieldWifiPassword.text, fieldWifiSSID.text) + wpaconfig += "\tpsk="+cryptedPsk+"\n" wpaconfig += "}\n" - addFirstRun("cat >/etc/wpa_supplicant/wpa_supplicant.conf </etc/wpa_supplicant/wpa_supplicant.conf <<'WPAEOF'") addFirstRun(wpaconfig) addFirstRun("WPAEOF") addFirstRun("chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf") @@ -528,7 +554,7 @@ Popup { addFirstRun("rm -f /etc/localtime") addFirstRun("echo \""+fieldTimezone.editText+"\" >/etc/timezone") addFirstRun("dpkg-reconfigure -f noninteractive tzdata") - addFirstRun("cat >/etc/default/keyboard </etc/default/keyboard <<'KBEOF'") addFirstRun("XKBMODEL=\"pc105\"") addFirstRun("XKBLAYOUT=\""+fieldKeyboardLayout.text+"\"") addFirstRun("XKBVARIANT=\"\"") diff --git a/imagewriter.cpp b/imagewriter.cpp index 5b7a2b9..0f7921f 100644 --- a/imagewriter.cpp +++ b/imagewriter.cpp @@ -35,6 +35,12 @@ #include #include #endif +#ifdef Q_OS_DARWIN +#include +#else +#include "openssl/evp.h" +#include "openssl/sha.h" +#endif #ifdef Q_OS_WIN #include @@ -926,6 +932,22 @@ QString ImageWriter::crypt(const QByteArray &password) return sha256_crypt(password.constData(), salt.constData()); } +QString ImageWriter::pbkdf2(const QByteArray &psk, const QByteArray &ssid) +{ + /* Qt has support for calculating Pbkdf2 starting from Qt 5.12 but + * older Linux distributions may not have that. + * We can use OpenSSL instead on platforms that have that. + * But Mac OS X lacks that, so do use Qt there */ + +#ifdef Q_OS_DARWIN + return QPasswordDigestor::deriveKeyPbkdf2(QCryptographicHash::Sha1, psk, ssid, 4096, 32).toHex(); +#else + QByteArray digest(32, 0); + PKCS5_PBKDF2_HMAC_SHA1(psk.constData(), psk.length(), (const unsigned char*) ssid.constData(), ssid.length(), 4096, digest.length(), (unsigned char *) digest.data()); + return digest.toHex(); +#endif +} + void ImageWriter::setSavedCustomizationSettings(const QVariantMap &map) { _settings.beginGroup("imagecustomization"); diff --git a/imagewriter.h b/imagewriter.h index 6f0c42f..914cfb5 100644 --- a/imagewriter.h +++ b/imagewriter.h @@ -109,6 +109,7 @@ public: Q_INVOKABLE bool hasSavedCustomizationSettings(); Q_INVOKABLE QString crypt(const QByteArray &password); + Q_INVOKABLE QString pbkdf2(const QByteArray &psk, const QByteArray &ssid); signals: /* We are emiting signals with QVariant as parameters because QML likes it that way */