diff options
Diffstat (limited to 'src/settings.cpp')
| -rw-r--r-- | src/settings.cpp | 165 |
1 files changed, 117 insertions, 48 deletions
diff --git a/src/settings.cpp b/src/settings.cpp index 0ce647fd..7b4b3a67 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -57,6 +57,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QtDebug> // for qDebug, qWarning #include <Windows.h> // For ShellExecuteW, HINSTANCE, etc +#include <wincred.h> // For storage #include <algorithm> // for sort #include <memory> @@ -80,10 +81,6 @@ private: int m_SortRole; }; - -static const unsigned char Key2[20] = { 0x99, 0xb8, 0x76, 0x42, 0x3e, 0xc1, 0x60, 0xa4, 0x5b, 0x01, - 0xdb, 0xf8, 0x43, 0x3a, 0xb7, 0xb6, 0x98, 0xd4, 0x7d, 0xa2 }; - Settings *Settings::s_Instance = nullptr; @@ -175,26 +172,60 @@ void Settings::registerPlugin(IPlugin *plugin) } } -QString Settings::obfuscate(const QString &password) +bool Settings::obfuscate(const QString key, const QString data) { - QByteArray temp = password.toUtf8(); + QString finalKey("ModOrganizer2_" + key); + wchar_t* keyData = new wchar_t[finalKey.size()+1]; + finalKey.toWCharArray(keyData); + keyData[finalKey.size()] = L'\0'; + bool result = false; + if (data.isEmpty()) { + result = CredDeleteW(keyData, CRED_TYPE_GENERIC, 0); + if (!result) + if (GetLastError() == ERROR_NOT_FOUND) + result = true; + } else { + wchar_t* charData = new wchar_t[data.size()]; + data.toWCharArray(charData); + + CREDENTIALW cred = {}; + cred.Flags = 0; + cred.Type = CRED_TYPE_GENERIC; + cred.TargetName = keyData; + cred.CredentialBlob = (LPBYTE)charData; + cred.CredentialBlobSize = sizeof(wchar_t) * data.size(); + cred.Persist = CRED_PERSIST_LOCAL_MACHINE; - QByteArray buffer; - for (int i = 0; i < temp.length(); ++i) { - buffer.append(temp.at(i) ^ Key2[i % 20]); + result = CredWriteW(&cred, 0); + delete[] charData; } - return buffer.toBase64(); + delete[] keyData; + return result; } -QString Settings::deObfuscate(const QString &password) +QString Settings::deObfuscate(const QString key) { - QByteArray temp(QByteArray::fromBase64(password.toUtf8())); - - QByteArray buffer; - for (int i = 0; i < temp.length(); ++i) { - buffer.append(temp.at(i) ^ Key2[i % 20]); + QString result; + QString finalKey("ModOrganizer2_" + key); + wchar_t* keyData = new wchar_t[finalKey.size()+1]; + finalKey.toWCharArray(keyData); + keyData[finalKey.size()] = L'\0'; + PCREDENTIALW creds; + if (CredReadW(keyData, 1, 0, &creds)) { + wchar_t *charData = (wchar_t *)creds->CredentialBlob; + result = QString::fromWCharArray(charData, creds->CredentialBlobSize / sizeof(wchar_t)); + CredFree(creds); + } else { + if (GetLastError() != ERROR_NOT_FOUND) { + wchar_t buffer[256]; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buffer, (sizeof(buffer) / sizeof(wchar_t)), NULL); + qCritical() << "Retrieving encrypted data failed:" << buffer; + } } - return QString::fromUtf8(buffer.constData()); + delete[] keyData; + return result; } QColor Settings::getIdealTextColor(const QColor& rBackgroundColor) @@ -332,27 +363,26 @@ QString Settings::getNMMVersion() const return result; } -bool Settings::getNexusLogin(QString &username, QString &password) const +bool Settings::getNexusApiKey(QString &apiKey) const { - if (m_Settings.value("Settings/nexus_login", false).toBool()) { - username = m_Settings.value("Settings/nexus_username", "").toString(); - password = deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()); - return true; - } else { + QString tempKey = deObfuscate("APIKEY"); + if (tempKey.isEmpty()) return false; - } + apiKey = tempKey; + return true; } bool Settings::getSteamLogin(QString &username, QString &password) const { - if (m_Settings.contains("Settings/steam_username") - && m_Settings.contains("Settings/steam_password")) { - username = m_Settings.value("Settings/steam_username").toString(); - password = deObfuscate(m_Settings.value("Settings/steam_password").toString()); - return true; - } else { - return false; + if (m_Settings.contains("Settings/steam_username")) { + QString tempPass = deObfuscate("steam_password"); + if (!tempPass.isEmpty()) { + username = m_Settings.value("Settings/steam_username").toString(); + password = tempPass; + return true; + } } + return false; } bool Settings::compactDownloads() const { @@ -431,11 +461,15 @@ QString Settings::executablesBlacklist() const ).toString(); } -void Settings::setNexusLogin(QString username, QString password) +void Settings::setNexusApiKey(QString apiKey) { - m_Settings.setValue("Settings/nexus_login", true); - m_Settings.setValue("Settings/nexus_username", username); - m_Settings.setValue("Settings/nexus_password", obfuscate(password)); + if (!obfuscate("APIKEY", apiKey)) { + wchar_t buffer[256]; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buffer, (sizeof(buffer) / sizeof(wchar_t)), NULL); + qCritical() << "Storing API key failed:" << buffer; + } } void Settings::setSteamLogin(QString username, QString password) @@ -446,10 +480,12 @@ void Settings::setSteamLogin(QString username, QString password) } else { m_Settings.setValue("Settings/steam_username", username); } - if (password == "") { - m_Settings.remove("Settings/steam_password"); - } else { - m_Settings.setValue("Settings/steam_password", obfuscate(password)); + if (!obfuscate("steam_password", password)) { + wchar_t buffer[256]; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buffer, (sizeof(buffer) / sizeof(wchar_t)), NULL); + qCritical() << "Storing or deleting password failed:" << buffer; } } @@ -674,11 +710,43 @@ void Settings::resetDialogs() QuestionBoxMemory::resetDialogs(); } +void Settings::processApiKey(const QString &apiKey) +{ + if (!obfuscate("APIKEY", apiKey)) { + wchar_t buffer[256]; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buffer, (sizeof(buffer) / sizeof(wchar_t)), NULL); + qCritical() << "Storing or deleting API key failed:" << buffer; + } +} + +void Settings::clearApiKey(QPushButton *nexusButton) +{ + obfuscate("APIKEY", ""); + nexusButton->setEnabled(true); + nexusButton->setText("Connect to Nexus"); +} + +void Settings::checkApiKey(QPushButton *nexusButton) +{ + if (deObfuscate("APIKEY").isEmpty()) { + nexusButton->setEnabled(true); + nexusButton->setText("Connect to Nexus"); + QMessageBox::warning(qApp->activeWindow(), tr("Error"), + tr("Failed to retrieve a Nexus API key! Please try again." + "A browser window should open asking you to authorize.")); + } +} + void Settings::query(PluginContainer *pluginContainer, QWidget *parent) { SettingsDialog dialog(pluginContainer, parent); connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs())); + connect(&dialog, SIGNAL(processApiKey(const QString &)), this, SLOT(processApiKey(const QString &))); + connect(&dialog, SIGNAL(closeApiConnection(QPushButton *)), this, SLOT(checkApiKey(QPushButton *))); + connect(&dialog, SIGNAL(revokeApiKey(QPushButton *)), this, SLOT(clearApiKey(QPushButton *))); std::vector<std::unique_ptr<SettingsTab>> tabs; @@ -960,9 +1028,7 @@ void Settings::DiagnosticsTab::update() Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog) : Settings::SettingsTab(parent, dialog) - , m_loginCheckBox(dialog.findChild<QCheckBox *>("loginCheckBox")) - , m_usernameEdit(dialog.findChild<QLineEdit *>("usernameEdit")) - , m_passwordEdit(dialog.findChild<QLineEdit *>("passwordEdit")) + , m_nexusConnect(dialog.findChild<QPushButton *>("nexusConnect")) , m_offlineBox(dialog.findChild<QCheckBox *>("offlineBox")) , m_proxyBox(dialog.findChild<QCheckBox *>("proxyBox")) , m_knownServersList(dialog.findChild<QListWidget *>("knownServersList")) @@ -970,16 +1036,16 @@ Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog) dialog.findChild<QListWidget *>("preferredServersList")) , m_endorsementBox(dialog.findChild<QCheckBox *>("endorsementBox")) { - if (parent->automaticLoginEnabled()) { - m_loginCheckBox->setChecked(true); - m_usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString()); - m_passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString())); + if (!deObfuscate("APIKEY").isEmpty()) { + m_nexusConnect->setText("Nexus API Key Stored"); + m_nexusConnect->setDisabled(true); } m_offlineBox->setChecked(parent->offlineMode()); m_proxyBox->setChecked(parent->useProxy()); m_endorsementBox->setChecked(parent->endorsementIntegration()); + // display server preferences m_Settings.beginGroup("Servers"); for (const QString &key : m_Settings.childKeys()) { @@ -1009,6 +1075,7 @@ Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog) void Settings::NexusTab::update() { + /* if (m_loginCheckBox->isChecked()) { m_Settings.setValue("Settings/nexus_login", true); m_Settings.setValue("Settings/nexus_username", m_usernameEdit->text()); @@ -1018,6 +1085,7 @@ void Settings::NexusTab::update() m_Settings.remove("Settings/nexus_username"); m_Settings.remove("Settings/nexus_password"); } + */ m_Settings.setValue("Settings/offline_mode", m_offlineBox->isChecked()); m_Settings.setValue("Settings/use_proxy", m_proxyBox->isChecked()); m_Settings.setValue("Settings/endorsement_integration", m_endorsementBox->isChecked()); @@ -1047,8 +1115,9 @@ Settings::SteamTab::SteamTab(Settings *m_parent, SettingsDialog &m_dialog) { if (m_Settings.contains("Settings/steam_username")) { m_steamUserEdit->setText(m_Settings.value("Settings/steam_username", "").toString()); - if (m_Settings.contains("Settings/steam_password")) { - m_steamPassEdit->setText(deObfuscate(m_Settings.value("Settings/steam_password", "").toString())); + QString password = deObfuscate("steam_password"); + if (!password.isEmpty()) { + m_steamPassEdit->setText(password); } } } |
