From dd41f093e65ab54befff63008c26ba78be409f7e Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sun, 17 Oct 2021 09:53:25 +0300 Subject: [PATCH] Launch KeePassXC password generator popup from the extension * Closes #6473 --- src/browser/BrowserAction.cpp | 35 ++-- src/browser/BrowserAction.h | 2 +- src/browser/BrowserService.cpp | 28 +++ src/browser/BrowserService.h | 7 +- src/browser/BrowserSettings.cpp | 273 +--------------------------- src/browser/BrowserSettings.h | 49 +---- src/gui/PasswordGeneratorWidget.cpp | 10 +- src/gui/PasswordGeneratorWidget.h | 3 +- 8 files changed, 66 insertions(+), 341 deletions(-) diff --git a/src/browser/BrowserAction.cpp b/src/browser/BrowserAction.cpp index f66c29aae..c84248469 100644 --- a/src/browser/BrowserAction.cpp +++ b/src/browser/BrowserAction.cpp @@ -23,6 +23,7 @@ #include "config-keepassx.h" #include "core/Global.h" #include "core/Tools.h" +#include "gui/PasswordGeneratorWidget.h" #include #include @@ -59,6 +60,20 @@ namespace const int BrowserAction::MaxUrlLength = 256; +BrowserAction::BrowserAction() +{ + QObject::connect(browserService(), + &BrowserService::passwordGenerated, + browserService(), + [=](const QString& password, const QString& nonce) { + auto newNonce = incrementNonce(nonce); + QJsonObject message = buildMessage(newNonce); + message["password"] = password; + + browserService()->sendPassword(buildResponse("generate-password", message, newNonce)); + }); +} + QJsonObject BrowserAction::processClientMessage(const QJsonObject& json) { if (json.isEmpty()) { @@ -315,25 +330,11 @@ QJsonObject BrowserAction::handleGetLogins(const QJsonObject& json, const QStrin QJsonObject BrowserAction::handleGeneratePassword(const QJsonObject& json, const QString& action) { + auto errorMessage = getErrorReply(action, ERROR_KEEPASS_ACTION_CANCELLED_OR_DENIED); auto nonce = json.value("nonce").toString(); - auto password = browserSettings()->generatePassword(); - if (nonce.isEmpty() || password.isEmpty()) { - return QJsonObject(); - } - - // For backwards compatibility - password["login"] = password["entropy"]; - - QJsonArray arr; - arr.append(password); - - const QString newNonce = incrementNonce(nonce); - - QJsonObject message = buildMessage(newNonce); - message["entries"] = arr; - - return buildResponse(action, message, newNonce); + browserService()->showPasswordGenerator(errorMessage, nonce); + return QJsonObject(); } QJsonObject BrowserAction::handleSetLogin(const QJsonObject& json, const QString& action) diff --git a/src/browser/BrowserAction.h b/src/browser/BrowserAction.h index 67ddad7cd..86b1884a2 100644 --- a/src/browser/BrowserAction.h +++ b/src/browser/BrowserAction.h @@ -25,7 +25,7 @@ class QJsonObject; class BrowserAction { public: - explicit BrowserAction() = default; + explicit BrowserAction(); ~BrowserAction() = default; QJsonObject processClientMessage(const QJsonObject& json); diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index b6ffdb55c..46de0a9d3 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -311,6 +311,34 @@ QString BrowserService::getCurrentTotp(const QString& uuid) return {}; } +void BrowserService::showPasswordGenerator(const QJsonObject& errorMessage, const QString& nonce) +{ + if (!m_passwordGenerator) { + m_passwordGenerator.reset(PasswordGeneratorWidget::popupGenerator()); + + connect(m_passwordGenerator.data(), &PasswordGeneratorWidget::closed, m_passwordGenerator.data(), [=] { + m_passwordGenerator.reset(); + m_browserHost->sendClientMessage(errorMessage); + hideWindow(); + }); + + connect(m_passwordGenerator.data(), + &PasswordGeneratorWidget::appliedPassword, + m_passwordGenerator.data(), + [=](const QString& password) { emit passwordGenerated(password, nonce); }); + } + + raiseWindow(); + m_passwordGenerator->raise(); + m_passwordGenerator->activateWindow(); +} + +void BrowserService::sendPassword(const QJsonObject& message) +{ + m_browserHost->sendClientMessage(message); + hideWindow(); +} + QString BrowserService::storeKey(const QString& key) { auto db = getDatabase(); diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h index 150b147f5..829f3b108 100644 --- a/src/browser/BrowserService.h +++ b/src/browser/BrowserService.h @@ -21,6 +21,7 @@ #define BROWSERSERVICE_H #include "core/Entry.h" +#include "gui/PasswordGeneratorWidget.h" typedef QPair StringPair; typedef QList StringPairList; @@ -55,6 +56,8 @@ public: QJsonObject getDatabaseGroups(); QJsonObject createNewGroup(const QString& groupName); QString getCurrentTotp(const QString& uuid); + void showPasswordGenerator(const QJsonObject& errorMessage, const QString& nonce); + void sendPassword(const QJsonObject& message); void addEntry(const QString& dbid, const QString& login, @@ -93,6 +96,7 @@ public: signals: void requestUnlock(); + void passwordGenerated(const QString& password, const QString& nonce); public slots: void databaseLocked(DatabaseWidget* dbWidget); @@ -145,9 +149,9 @@ private: QString getDatabaseRecycleBinUuid(); bool checkLegacySettings(QSharedPointer db); QStringList getEntryURLs(const Entry* entry); - void hideWindow() const; void raiseWindow(const bool force = false); + void updateWindowState(); static bool moveSettingsToCustomData(Entry* entry, const QString& name); @@ -162,6 +166,7 @@ private: QUuid m_keepassBrowserUUID; QPointer m_currentDatabaseWidget; + QScopedPointer m_passwordGenerator; Q_DISABLE_COPY(BrowserService); diff --git a/src/browser/BrowserSettings.cpp b/src/browser/BrowserSettings.cpp index 4595d5c0e..7b5704e78 100644 --- a/src/browser/BrowserSettings.cpp +++ b/src/browser/BrowserSettings.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2013 Francois Ferrand * Copyright (C) 2017 Sami Vänttinen - * Copyright (C) 2017 KeePassXC Team + * Copyright (C) 2021 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -242,277 +242,6 @@ void BrowserSettings::setBrowserSupport(BrowserShared::SupportedBrowsers browser m_nativeMessageInstaller.setBrowserEnabled(browser, enabled); } -bool BrowserSettings::passwordUseNumbers() -{ - return config()->get(Config::PasswordGenerator_Numbers).toBool(); -} - -void BrowserSettings::setPasswordUseNumbers(bool useNumbers) -{ - config()->set(Config::PasswordGenerator_Numbers, useNumbers); -} - -bool BrowserSettings::passwordUseLowercase() -{ - return config()->get(Config::PasswordGenerator_LowerCase).toBool(); -} - -void BrowserSettings::setPasswordUseLowercase(bool useLowercase) -{ - config()->set(Config::PasswordGenerator_LowerCase, useLowercase); -} - -bool BrowserSettings::passwordUseUppercase() -{ - return config()->get(Config::PasswordGenerator_UpperCase).toBool(); -} - -void BrowserSettings::setPasswordUseUppercase(bool useUppercase) -{ - config()->set(Config::PasswordGenerator_UpperCase, useUppercase); -} - -bool BrowserSettings::passwordUseSpecial() -{ - return config()->get(Config::PasswordGenerator_SpecialChars).toBool(); -} - -void BrowserSettings::setPasswordUseSpecial(bool useSpecial) -{ - config()->set(Config::PasswordGenerator_SpecialChars, useSpecial); -} - -bool BrowserSettings::passwordUseBraces() -{ - return config()->get(Config::PasswordGenerator_Braces).toBool(); -} - -void BrowserSettings::setPasswordUseBraces(bool useBraces) -{ - config()->set(Config::PasswordGenerator_Braces, useBraces); -} - -bool BrowserSettings::passwordUsePunctuation() -{ - return config()->get(Config::PasswordGenerator_Punctuation).toBool(); -} - -void BrowserSettings::setPasswordUsePunctuation(bool usePunctuation) -{ - config()->set(Config::PasswordGenerator_Punctuation, usePunctuation); -} - -bool BrowserSettings::passwordUseQuotes() -{ - return config()->get(Config::PasswordGenerator_Quotes).toBool(); -} - -void BrowserSettings::setPasswordUseQuotes(bool useQuotes) -{ - config()->set(Config::PasswordGenerator_Quotes, useQuotes); -} - -bool BrowserSettings::passwordUseDashes() -{ - return config()->get(Config::PasswordGenerator_Dashes).toBool(); -} - -void BrowserSettings::setPasswordUseDashes(bool useDashes) -{ - config()->set(Config::PasswordGenerator_Dashes, useDashes); -} - -bool BrowserSettings::passwordUseMath() -{ - return config()->get(Config::PasswordGenerator_Math).toBool(); -} - -void BrowserSettings::setPasswordUseMath(bool useMath) -{ - config()->set(Config::PasswordGenerator_Math, useMath); -} - -bool BrowserSettings::passwordUseLogograms() -{ - return config()->get(Config::PasswordGenerator_Logograms).toBool(); -} - -void BrowserSettings::setPasswordUseLogograms(bool useLogograms) -{ - config()->set(Config::PasswordGenerator_Logograms, useLogograms); -} - -bool BrowserSettings::passwordUseEASCII() -{ - return config()->get(Config::PasswordGenerator_EASCII).toBool(); -} - -void BrowserSettings::setPasswordUseEASCII(bool useEASCII) -{ - config()->set(Config::PasswordGenerator_EASCII, useEASCII); -} - -bool BrowserSettings::advancedMode() -{ - return config()->get(Config::PasswordGenerator_AdvancedMode).toBool(); -} - -void BrowserSettings::setAdvancedMode(bool advancedMode) -{ - config()->set(Config::PasswordGenerator_AdvancedMode, advancedMode); -} - -QString BrowserSettings::passwordAdditionalChars() -{ - return config()->get(Config::PasswordGenerator_AdditionalChars).toString(); -} - -void BrowserSettings::setPasswordAdditionalChars(const QString& chars) -{ - config()->set(Config::PasswordGenerator_AdditionalChars, chars); -} - -QString BrowserSettings::passwordExcludedChars() -{ - return config()->get(Config::PasswordGenerator_ExcludedChars).toString(); -} - -void BrowserSettings::setPasswordExcludedChars(const QString& chars) -{ - config()->set(Config::PasswordGenerator_ExcludedChars, chars); -} - -int BrowserSettings::passPhraseWordCount() -{ - return config()->get(Config::PasswordGenerator_WordCount).toInt(); -} - -void BrowserSettings::setPassPhraseWordCount(int wordCount) -{ - config()->set(Config::PasswordGenerator_WordCount, wordCount); -} - -QString BrowserSettings::passPhraseWordSeparator() -{ - return config()->get(Config::PasswordGenerator_WordSeparator).toString(); -} - -void BrowserSettings::setPassPhraseWordSeparator(const QString& separator) -{ - config()->set(Config::PasswordGenerator_WordSeparator, separator); -} - -int BrowserSettings::generatorType() -{ - return config()->get(Config::PasswordGenerator_Type).toInt(); -} - -void BrowserSettings::setGeneratorType(int type) -{ - config()->set(Config::PasswordGenerator_Type, type); -} - -bool BrowserSettings::passwordEveryGroup() -{ - return config()->get(Config::PasswordGenerator_EnsureEvery).toBool(); -} - -void BrowserSettings::setPasswordEveryGroup(bool everyGroup) -{ - config()->set(Config::PasswordGenerator_EnsureEvery, everyGroup); -} - -bool BrowserSettings::passwordExcludeAlike() -{ - return config()->get(Config::PasswordGenerator_ExcludeAlike).toBool(); -} - -void BrowserSettings::setPasswordExcludeAlike(bool excludeAlike) -{ - config()->set(Config::PasswordGenerator_ExcludeAlike, excludeAlike); -} - -int BrowserSettings::passwordLength() -{ - return config()->get(Config::PasswordGenerator_Length).toInt(); -} - -void BrowserSettings::setPasswordLength(int length) -{ - config()->set(Config::PasswordGenerator_Length, length); - m_passwordGenerator.setLength(length); -} - -PasswordGenerator::CharClasses BrowserSettings::passwordCharClasses() -{ - PasswordGenerator::CharClasses classes; - if (passwordUseLowercase()) { - classes |= PasswordGenerator::LowerLetters; - } - if (passwordUseUppercase()) { - classes |= PasswordGenerator::UpperLetters; - } - if (passwordUseNumbers()) { - classes |= PasswordGenerator::Numbers; - } - if (passwordUseSpecial()) { - classes |= PasswordGenerator::SpecialCharacters; - } - if (passwordUseBraces()) { - classes |= PasswordGenerator::Braces; - } - if (passwordUsePunctuation()) { - classes |= PasswordGenerator::Punctuation; - } - if (passwordUseQuotes()) { - classes |= PasswordGenerator::Quotes; - } - if (passwordUseDashes()) { - classes |= PasswordGenerator::Dashes; - } - if (passwordUseMath()) { - classes |= PasswordGenerator::Math; - } - if (passwordUseLogograms()) { - classes |= PasswordGenerator::Logograms; - } - if (passwordUseEASCII()) { - classes |= PasswordGenerator::EASCII; - } - return classes; -} - -PasswordGenerator::GeneratorFlags BrowserSettings::passwordGeneratorFlags() -{ - PasswordGenerator::GeneratorFlags flags; - if (passwordExcludeAlike()) { - flags |= PasswordGenerator::ExcludeLookAlike; - } - if (passwordEveryGroup()) { - flags |= PasswordGenerator::CharFromEveryGroup; - } - return flags; -} - -QJsonObject BrowserSettings::generatePassword() -{ - QJsonObject password; - if (generatorType() == 0) { - m_passwordGenerator.setLength(passwordLength()); - m_passwordGenerator.setCharClasses(passwordCharClasses()); - m_passwordGenerator.setFlags(passwordGeneratorFlags()); - const QString pw = m_passwordGenerator.generatePassword(); - password["entropy"] = PasswordHealth(pw).entropy(); - password["password"] = pw; - } else { - m_passPhraseGenerator.setWordCount(passPhraseWordCount()); - m_passPhraseGenerator.setWordSeparator(passPhraseWordSeparator()); - password["entropy"] = m_passPhraseGenerator.estimateEntropy(); - password["password"] = m_passPhraseGenerator.generatePassphrase(); - } - return password; -} - void BrowserSettings::updateBinaryPaths() { m_nativeMessageInstaller.updateBinaryPaths(); diff --git a/src/browser/BrowserSettings.h b/src/browser/BrowserSettings.h index 63a4846ae..18ededb4c 100644 --- a/src/browser/BrowserSettings.h +++ b/src/browser/BrowserSettings.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2013 Francois Ferrand * Copyright (C) 2017 Sami Vänttinen - * Copyright (C) 2017 KeePassXC Team + * Copyright (C) 2021 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,6 @@ #define BROWSERSETTINGS_H #include "NativeMessageInstaller.h" -#include "core/PassphraseGenerator.h" -#include "core/PasswordGenerator.h" class BrowserSettings { @@ -76,49 +74,6 @@ public: void setCustomBrowserType(int type); QString customBrowserLocation(); void setCustomBrowserLocation(const QString& location); - bool passwordUseNumbers(); - void setPasswordUseNumbers(bool useNumbers); - bool passwordUseLowercase(); - void setPasswordUseLowercase(bool useLowercase); - bool passwordUseUppercase(); - void setPasswordUseUppercase(bool useUppercase); - bool passwordUseSpecial(); - void setPasswordUseSpecial(bool useSpecial); - bool passwordUseBraces(); - void setPasswordUseBraces(bool useBraces); - bool passwordUsePunctuation(); - void setPasswordUsePunctuation(bool usePunctuation); - bool passwordUseQuotes(); - void setPasswordUseQuotes(bool useQuotes); - bool passwordUseDashes(); - void setPasswordUseDashes(bool useDashes); - bool passwordUseMath(); - void setPasswordUseMath(bool useMath); - bool passwordUseLogograms(); - void setPasswordUseLogograms(bool useLogograms); - bool passwordUseEASCII(); - void setPasswordUseEASCII(bool useEASCII); - bool advancedMode(); - void setAdvancedMode(bool advancedMode); - QString passwordAdditionalChars(); - void setPasswordAdditionalChars(const QString& chars); - QString passwordExcludedChars(); - void setPasswordExcludedChars(const QString& chars); - int passPhraseWordCount(); - void setPassPhraseWordCount(int wordCount); - QString passPhraseWordSeparator(); - void setPassPhraseWordSeparator(const QString& separator); - int generatorType(); - void setGeneratorType(int type); - bool passwordEveryGroup(); - void setPasswordEveryGroup(bool everyGroup); - bool passwordExcludeAlike(); - void setPasswordExcludeAlike(bool excludeAlike); - int passwordLength(); - void setPasswordLength(int length); - PasswordGenerator::CharClasses passwordCharClasses(); - PasswordGenerator::GeneratorFlags passwordGeneratorFlags(); - QJsonObject generatePassword(); void updateBinaryPaths(); QString replaceHomePath(QString location); QString replaceTildeHomePath(QString location); @@ -126,8 +81,6 @@ public: private: static BrowserSettings* m_instance; - PasswordGenerator m_passwordGenerator; - PassphraseGenerator m_passPhraseGenerator; NativeMessageInstaller m_nativeMessageInstaller; }; diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index acb93b630..78b240de9 100644 --- a/src/gui/PasswordGeneratorWidget.cpp +++ b/src/gui/PasswordGeneratorWidget.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 Felix Geyer - * Copyright (C) 2020 KeePassXC Team + * Copyright (C) 2021 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ #include "PasswordGeneratorWidget.h" #include "ui_PasswordGeneratorWidget.h" +#include #include #include #include @@ -109,6 +110,13 @@ PasswordGeneratorWidget::~PasswordGeneratorWidget() { } +void PasswordGeneratorWidget::closeEvent(QCloseEvent* event) +{ + // Emits closed signal when clicking X from title bar + emit closed(); + event->accept(); +} + PasswordGeneratorWidget* PasswordGeneratorWidget::popupGenerator(QWidget* parent) { auto pwGenerator = new PasswordGeneratorWidget(parent); diff --git a/src/gui/PasswordGeneratorWidget.h b/src/gui/PasswordGeneratorWidget.h index 832025d46..50de172ac 100644 --- a/src/gui/PasswordGeneratorWidget.h +++ b/src/gui/PasswordGeneratorWidget.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2013 Felix Geyer - * Copyright (C) 2017 KeePassXC Team + * Copyright (C) 2021 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -81,6 +81,7 @@ private slots: private: bool m_standalone = false; + void closeEvent(QCloseEvent* event); PasswordGenerator::CharClasses charClasses(); PasswordGenerator::GeneratorFlags generatorFlags();