Launch KeePassXC password generator popup from the extension

* Closes #6473
This commit is contained in:
varjolintu 2021-10-17 09:53:25 +03:00 committed by Jonathan White
parent 2a9d92faeb
commit dd41f093e6
8 changed files with 66 additions and 341 deletions

View File

@ -23,6 +23,7 @@
#include "config-keepassx.h"
#include "core/Global.h"
#include "core/Tools.h"
#include "gui/PasswordGeneratorWidget.h"
#include <QJsonArray>
#include <QJsonDocument>
@ -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)

View File

@ -25,7 +25,7 @@ class QJsonObject;
class BrowserAction
{
public:
explicit BrowserAction() = default;
explicit BrowserAction();
~BrowserAction() = default;
QJsonObject processClientMessage(const QJsonObject& json);

View File

@ -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();

View File

@ -21,6 +21,7 @@
#define BROWSERSERVICE_H
#include "core/Entry.h"
#include "gui/PasswordGeneratorWidget.h"
typedef QPair<QString, QString> StringPair;
typedef QList<StringPair> 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<Database> 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<DatabaseWidget> m_currentDatabaseWidget;
QScopedPointer<PasswordGeneratorWidget> m_passwordGenerator;
Q_DISABLE_COPY(BrowserService);

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
*
* 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();

View File

@ -1,7 +1,7 @@
/*
* Copyright (C) 2013 Francois Ferrand
* Copyright (C) 2017 Sami Vänttinen <sami.vanttinen@protonmail.com>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
*
* 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;
};

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
* Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
*
* 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 <QCloseEvent>
#include <QDir>
#include <QShortcut>
#include <QTimer>
@ -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);

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
*
* 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();