mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Merge branch 'master' into develop
This commit is contained in:
parent
4e90cb5818
commit
61b85183f9
22
CHANGELOG.md
22
CHANGELOG.md
@ -1,5 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
## 2.6.4 (2021-01-31)
|
||||
|
||||
### Added
|
||||
|
||||
- Automatically adapt to light/dark system theme changes (Windows/macOS only) [#6034]
|
||||
|
||||
### Changed
|
||||
|
||||
- Show window title as tooltip on system tray [#5948]
|
||||
- Compress Snap release as LZO for faster initial startup [#5877]
|
||||
- Password generator: Set maximum selectable password length to 999 [#5937]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix crash on app close when using SSH agent [#5935]
|
||||
- Fix KDF selection showing wrong item when using Argon2id [#5923]
|
||||
- Automatically close About dialog on database lock if it is still open [#5947]
|
||||
- Linux: Fix automatic launch at system startup with AppImages [#5901]
|
||||
- Linux: Fix click-to-move on empty area activating when using menus [#5971]
|
||||
- Linux: Try multiple times to show tray icon if tray is not ready yet [#5948]
|
||||
- macOS: Fix KeePassXC blocking clean shutdown [#6002]
|
||||
|
||||
## 2.6.3 (2021-01-12)
|
||||
|
||||
### Added
|
||||
|
@ -288,6 +288,8 @@ image::database_security.png[]
|
||||
.Database credentials
|
||||
image::database_security_credentials.png[]
|
||||
|
||||
WARNING: Consider creating a backup of your YubiKey. Please refer to <<Creating a YubiKey backup>>
|
||||
|
||||
5. Encryption settings allows you to change the average time it takes to encrypt and decrypt the database. The longer time that is chosen, the harder it will be to brute force attack your database. *We recommend a setting of one second.*
|
||||
+
|
||||
.Database encryption
|
||||
@ -305,6 +307,23 @@ The following key derivation functions are supported:
|
||||
* AES-KDF (KDBX 4 and KDBX 3.1): This key derivation function is based on iterating AES. Users can change the number of iterations. The more iterations, the harder are dictionary and guessing attacks, but also database loading/saving takes more time (linearly). KDBX 3.1 only supports AES-KDF; any other key derivation function, like for instance Argon2, requires KDBX 4.
|
||||
|
||||
* Argon2 (KDBX 4 - recommended): KDBX 4, the Argon2 key derivation function can be used for transforming the composite master key (as protection against dictionary attacks). The main advantage of Argon2 over AES-KDF is that it provides a better resistance against GPU/ASIC attacks (due to being a memory-hard function). The number of iterations scales linearly with the required time. By increasing the memory parameter, GPU/ASIC attacks become harder (and the required time increases). The parallelism parameter can be used to specify how many threads should be used.
|
||||
|
||||
=== Creating a YubiKey backup
|
||||
It is advisable to have a backup replica YubiKey In case your main YubiKey gets damaged, lost, or stolen. The same HMAC key will need to be written to both keys. To do this you can either use the YubiKey Personalization Tool GUI or the ykpersonalize CLI tool. The steps for the CLI tool are shown:
|
||||
|
||||
1. Create a 20 byte HMAC key:
|
||||
+
|
||||
```
|
||||
dd status=none if=/dev/random bs=20 count=1 | xxd -p -c 40
|
||||
```
|
||||
|
||||
2. Write the HMAC key to slot 2 _(Set through the first switch. Out of the box the YubiKey OTP resides in slot 1)_:
|
||||
+
|
||||
```
|
||||
ykpersonalize -2 -a -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible -oallow-update
|
||||
```
|
||||
|
||||
You will be asked to enter the HMAC key you created earlier, copy/paste they key output in the first step. Repeat both steps for your second YubiKey. We recommend storing your HMAC key in a safe place (e.g., printed on paper) in case you need to recreate another key.
|
||||
// end::advanced[]
|
||||
|
||||
== Storing a Database File
|
||||
|
18
release-tool
18
release-tool
@ -44,6 +44,7 @@ ORIG_BRANCH=""
|
||||
ORIG_CWD="$(pwd)"
|
||||
MACOSX_DEPLOYMENT_TARGET=10.12
|
||||
GREP="grep"
|
||||
TIMESTAMP_SERVER="http://timestamp.sectigo.com"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# helper functions
|
||||
@ -114,6 +115,7 @@ Options:
|
||||
--appimage Build a Linux AppImage after compilation.
|
||||
If this option is set, --install-prefix has no effect
|
||||
--appsign Perform platform specific App Signing before packaging
|
||||
--timestamp Explicitly set the timestamp server to use for appsign (default: '${TIMESTAMP_SERVER}')
|
||||
-k, --key Specify the App Signing Key/Identity
|
||||
-c, --cmake-options Additional CMake options for compiling the sources
|
||||
--compiler Compiler to use (default: '${COMPILER}')
|
||||
@ -145,6 +147,8 @@ Options:
|
||||
-f, --files Files to sign (required)
|
||||
-k, --key, -i, --identity
|
||||
Signing Key or Apple Developer ID (required)
|
||||
--timestamp Explicitly set the timestamp server to use for appsign (default: '${TIMESTAMP_SERVER}')
|
||||
-u, --username Apple username for notarization (required on macOS)
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
elif [ "notarize" == "$cmd" ]; then
|
||||
@ -494,6 +498,10 @@ merge() {
|
||||
GPG_GIT_KEY="$2"
|
||||
shift ;;
|
||||
|
||||
--timestamp)
|
||||
TIMESTAMP_SERVER="$2"
|
||||
shift ;;
|
||||
|
||||
-r|--release-branch)
|
||||
SOURCE_BRANCH="$2"
|
||||
shift ;;
|
||||
@ -810,6 +818,10 @@ build() {
|
||||
--appsign)
|
||||
build_appsign=true ;;
|
||||
|
||||
--timestamp)
|
||||
TIMESTAMP_SERVER="$2"
|
||||
shift ;;
|
||||
|
||||
-k|--key)
|
||||
build_key="$2"
|
||||
shift ;;
|
||||
@ -1268,8 +1280,10 @@ appsign() {
|
||||
|
||||
# osslsigncode does not succeed at signing MSI files at this time...
|
||||
logInfo "Signing file '${f}' using Microsoft signtool..."
|
||||
if ! signtool sign -f "${key}" -p "${password}" -d "KeePassXC" -td sha256 \
|
||||
-fd sha256 -tr "http://timestamp.comodoca.com/authenticode" "${f}"; then
|
||||
signtool sign -f "${key}" -p "${password}" -d "KeePassXC" -td sha256 \
|
||||
-fd sha256 -tr "${TIMESTAMP_SERVER}" "${f}"
|
||||
|
||||
if [ 0 -ne $? ]; then
|
||||
exitError "Signing failed!"
|
||||
fi
|
||||
else
|
||||
|
@ -50,6 +50,23 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.6.4" date="2021-01-31">
|
||||
<description>
|
||||
<ul>
|
||||
<li>Automatically adapt to light/dark system theme changes (Windows/macOS only) [#6034]</li>
|
||||
<li>Show window title as tooltip on system tray [#5948]</li>
|
||||
<li>Compress Snap release as LZO for faster initial startup [#5877]</li>
|
||||
<li>Password generator: Set maximum selectable password length to 999 [#5937]</li>
|
||||
<li>Fix crash on app close when using SSH agent [#5935]</li>
|
||||
<li>Fix KDF selection showing wrong item when using Argon2id [#5923]</li>
|
||||
<li>Automatically close About dialog on database lock if it is still open [#5947]</li>
|
||||
<li>Linux: Fix automatic launch at system startup with AppImages [#5901]</li>
|
||||
<li>Linux: Fix click-to-move on empty area activating when using menus [#5971]</li>
|
||||
<li>Linux: Try multiple times to show tray icon if tray is not ready yet [#5948]</li>
|
||||
<li>macOS: Fix KeePassXC blocking clean shutdown [#6002]</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="2.6.3" date="2021-01-12">
|
||||
<description>
|
||||
<ul>
|
||||
|
@ -8,6 +8,7 @@ description: |
|
||||
published under the terms of the GNU General Public License.
|
||||
confinement: strict
|
||||
base: core18
|
||||
compression: lzo
|
||||
|
||||
plugs: # plugs for theming, font settings, cursor and to use gtk3 file chooser
|
||||
gtk-3-themes:
|
||||
|
@ -30,8 +30,7 @@
|
||||
* or associated data. KeePass uses the latest version of Argon2, v1.3.
|
||||
*/
|
||||
Argon2Kdf::Argon2Kdf(Type type)
|
||||
: Kdf::Kdf(KeePass2::KDF_ARGON2D)
|
||||
, m_type(type)
|
||||
: Kdf::Kdf(type == Type::Argon2d ? KeePass2::KDF_ARGON2D : KeePass2::KDF_ARGON2ID)
|
||||
, m_version(0x13)
|
||||
, m_memory(1 << 16)
|
||||
, m_parallelism(static_cast<quint32>(QThread::idealThreadCount()))
|
||||
@ -57,12 +56,7 @@ bool Argon2Kdf::setVersion(quint32 version)
|
||||
|
||||
Argon2Kdf::Type Argon2Kdf::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
void Argon2Kdf::setType(Type type)
|
||||
{
|
||||
m_type = type;
|
||||
return uuid() == KeePass2::KDF_ARGON2D ? Type::Argon2d : Type::Argon2id;
|
||||
}
|
||||
|
||||
quint64 Argon2Kdf::memory() const
|
||||
@ -144,11 +138,7 @@ bool Argon2Kdf::processParameters(const QVariantMap& p)
|
||||
QVariantMap Argon2Kdf::writeParameters()
|
||||
{
|
||||
QVariantMap p;
|
||||
if (type() == Type::Argon2d) {
|
||||
p.insert(KeePass2::KDFPARAM_UUID, KeePass2::KDF_ARGON2D.toRfc4122());
|
||||
} else {
|
||||
p.insert(KeePass2::KDFPARAM_UUID, KeePass2::KDF_ARGON2ID.toRfc4122());
|
||||
}
|
||||
p.insert(KeePass2::KDFPARAM_UUID, uuid().toRfc4122());
|
||||
p.insert(KeePass2::KDFPARAM_ARGON2_VERSION, version());
|
||||
p.insert(KeePass2::KDFPARAM_ARGON2_PARALLELISM, parallelism());
|
||||
p.insert(KeePass2::KDFPARAM_ARGON2_MEMORY, memory() * 1024);
|
||||
|
@ -39,7 +39,6 @@ public:
|
||||
quint32 version() const;
|
||||
bool setVersion(quint32 version);
|
||||
Type type() const;
|
||||
void setType(Type type);
|
||||
quint64 memory() const;
|
||||
bool setMemory(quint64 kibibytes);
|
||||
quint32 parallelism() const;
|
||||
@ -49,7 +48,6 @@ public:
|
||||
protected:
|
||||
int benchmarkImpl(int msec) const override;
|
||||
|
||||
Type m_type;
|
||||
quint32 m_version;
|
||||
quint64 m_memory;
|
||||
quint32 m_parallelism;
|
||||
|
@ -214,13 +214,6 @@ DatabaseWidget::DatabaseWidget(QSharedPointer<Database> db, QWidget* parent)
|
||||
m_EntrySearcher = new EntrySearcher(false);
|
||||
m_searchLimitGroup = config()->get(Config::SearchLimitGroup).toBool();
|
||||
|
||||
#ifdef WITH_XC_SSHAGENT
|
||||
if (sshAgent()->isEnabled()) {
|
||||
connect(this, SIGNAL(databaseLocked()), sshAgent(), SLOT(databaseLocked()));
|
||||
connect(this, SIGNAL(databaseUnlocked()), sshAgent(), SLOT(databaseUnlocked()));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_XC_KEESHARE
|
||||
// We need to reregister the database to allow exports
|
||||
// from a newly created database
|
||||
@ -1091,6 +1084,9 @@ void DatabaseWidget::loadDatabase(bool accepted)
|
||||
m_entryBeforeLock = QUuid();
|
||||
m_saveAttempts = 0;
|
||||
emit databaseUnlocked();
|
||||
#ifdef WITH_XC_SSHAGENT
|
||||
sshAgent()->databaseUnlocked(m_db);
|
||||
#endif
|
||||
if (config()->get(Config::MinimizeAfterUnlock).toBool()) {
|
||||
getMainWindow()->minimizeOrHide();
|
||||
}
|
||||
@ -1178,6 +1174,10 @@ void DatabaseWidget::unlockDatabase(bool accepted)
|
||||
processAutoOpen();
|
||||
emit databaseUnlocked();
|
||||
|
||||
#ifdef WITH_XC_SSHAGENT
|
||||
sshAgent()->databaseUnlocked(m_db);
|
||||
#endif
|
||||
|
||||
if (senderDialog && senderDialog->intent() == DatabaseOpenDialog::Intent::AutoType) {
|
||||
QList<QSharedPointer<Database>> dbList;
|
||||
dbList.append(m_db);
|
||||
@ -1599,6 +1599,10 @@ bool DatabaseWidget::lock()
|
||||
m_entryBeforeLock = currentEntry->uuid();
|
||||
}
|
||||
|
||||
#ifdef WITH_XC_SSHAGENT
|
||||
sshAgent()->databaseLocked(m_db);
|
||||
#endif
|
||||
|
||||
endSearch();
|
||||
clearAllWidgets();
|
||||
switchToOpenDatabase(m_db->filePath());
|
||||
|
@ -411,7 +411,6 @@ MainWindow::MainWindow()
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateWindowTitle()));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(databaseTabChanged(int)));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(setMenuActionState()));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateTrayIcon()));
|
||||
connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), SLOT(databaseStatusChanged(DatabaseWidget*)));
|
||||
connect(m_ui->tabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), SLOT(databaseStatusChanged(DatabaseWidget*)));
|
||||
connect(m_ui->tabWidget, SIGNAL(tabVisibilityChanged(bool)), SLOT(updateToolbarSeparatorVisibility()));
|
||||
@ -565,6 +564,9 @@ MainWindow::MainWindow()
|
||||
MessageWidget::Error);
|
||||
}
|
||||
|
||||
// Properly shutdown on logoff, restart, and shutdown
|
||||
connect(qApp, &QGuiApplication::commitDataRequest, this, [this] { m_appExitCalled = true; });
|
||||
|
||||
#if defined(KEEPASSXC_BUILD_TYPE_SNAPSHOT) || defined(KEEPASSXC_BUILD_TYPE_PRE_RELEASE)
|
||||
auto* hidePreRelWarn = new QAction(tr("Don't show again for this version"), m_ui->globalMessageWidget);
|
||||
m_ui->globalMessageWidget->addAction(hidePreRelWarn);
|
||||
@ -617,6 +619,9 @@ MainWindow::MainWindow()
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
#ifdef WITH_XC_SSHAGENT
|
||||
sshAgent()->removeAllIdentities();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -968,11 +973,20 @@ void MainWindow::updateWindowTitle()
|
||||
|
||||
setWindowTitle(windowTitle);
|
||||
setWindowModified(isModified);
|
||||
|
||||
updateTrayIcon();
|
||||
}
|
||||
|
||||
void MainWindow::showAboutDialog()
|
||||
{
|
||||
auto* aboutDialog = new AboutDialog(this);
|
||||
// Auto close the about dialog before attempting database locks
|
||||
if (m_ui->tabWidget->currentDatabaseWidget()) {
|
||||
connect(m_ui->tabWidget->currentDatabaseWidget(),
|
||||
&DatabaseWidget::databaseLockRequested,
|
||||
aboutDialog,
|
||||
&AboutDialog::close);
|
||||
}
|
||||
aboutDialog->open();
|
||||
}
|
||||
|
||||
@ -1208,8 +1222,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
||||
void MainWindow::changeEvent(QEvent* event)
|
||||
{
|
||||
if ((event->type() == QEvent::WindowStateChange) && isMinimized()) {
|
||||
if (isTrayIconEnabled() && m_trayIcon && m_trayIcon->isVisible()
|
||||
&& config()->get(Config::GUI_MinimizeToTray).toBool()) {
|
||||
if (isTrayIconEnabled() && config()->get(Config::GUI_MinimizeToTray).toBool()) {
|
||||
event->ignore();
|
||||
hide();
|
||||
}
|
||||
@ -1309,9 +1322,7 @@ bool MainWindow::saveLastDatabases()
|
||||
|
||||
void MainWindow::updateTrayIcon()
|
||||
{
|
||||
if (isTrayIconEnabled()) {
|
||||
QApplication::setQuitOnLastWindowClosed(false);
|
||||
|
||||
if (config()->get(Config::GUI_ShowTrayIcon).toBool()) {
|
||||
if (!m_trayIcon) {
|
||||
m_trayIcon = new QSystemTrayIcon(this);
|
||||
auto* menu = new QMenu(this);
|
||||
@ -1323,40 +1334,46 @@ void MainWindow::updateTrayIcon()
|
||||
menu->addAction(m_ui->actionLockDatabases);
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
QAction* actionQuit = new QAction(tr("Quit KeePassXC"), menu);
|
||||
menu->addAction(actionQuit);
|
||||
|
||||
auto actionQuit = new QAction(tr("Quit KeePassXC"), menu);
|
||||
connect(actionQuit, SIGNAL(triggered()), SLOT(appExit()));
|
||||
menu->addAction(actionQuit);
|
||||
#else
|
||||
menu->addAction(m_ui->actionQuit);
|
||||
|
||||
#endif
|
||||
m_trayIcon->setContextMenu(menu);
|
||||
|
||||
connect(m_trayIcon,
|
||||
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||
SLOT(trayIconTriggered(QSystemTrayIcon::ActivationReason)));
|
||||
connect(actionToggle, SIGNAL(triggered()), SLOT(toggleWindow()));
|
||||
|
||||
m_trayIcon->setContextMenu(menu);
|
||||
|
||||
m_trayIcon->setIcon(icons()->trayIcon());
|
||||
m_trayIcon->show();
|
||||
}
|
||||
|
||||
if (m_ui->tabWidget->count() == 0) {
|
||||
m_trayIcon->setIcon(icons()->trayIcon());
|
||||
} else if (m_ui->tabWidget->hasLockableDatabases()) {
|
||||
if (m_ui->tabWidget->hasLockableDatabases()) {
|
||||
m_trayIcon->setIcon(icons()->trayIconUnlocked());
|
||||
} else {
|
||||
m_trayIcon->setIcon(icons()->trayIconLocked());
|
||||
}
|
||||
} else {
|
||||
QApplication::setQuitOnLastWindowClosed(true);
|
||||
|
||||
m_trayIcon->setToolTip(windowTitle().replace("[*]", isWindowModified() ? "*" : ""));
|
||||
m_trayIcon->show();
|
||||
|
||||
if (!isTrayIconEnabled() || !QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
// Try to show tray icon after 5 seconds, try 5 times
|
||||
// This can happen if KeePassXC starts before the system tray is available
|
||||
static int trayIconAttempts = 0;
|
||||
if (trayIconAttempts < 5) {
|
||||
QTimer::singleShot(5000, this, &MainWindow::updateTrayIcon);
|
||||
++trayIconAttempts;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_trayIcon) {
|
||||
m_trayIcon->hide();
|
||||
delete m_trayIcon;
|
||||
}
|
||||
}
|
||||
|
||||
QApplication::setQuitOnLastWindowClosed(!isTrayIconEnabled());
|
||||
}
|
||||
|
||||
void MainWindow::obtainContextFocusLock()
|
||||
@ -1598,7 +1615,7 @@ void MainWindow::forgetTouchIDAfterInactivity()
|
||||
|
||||
bool MainWindow::isTrayIconEnabled() const
|
||||
{
|
||||
return config()->get(Config::GUI_ShowTrayIcon).toBool() && QSystemTrayIcon::isSystemTrayAvailable();
|
||||
return m_trayIcon && m_trayIcon->isVisible();
|
||||
}
|
||||
|
||||
void MainWindow::displayGlobalMessage(const QString& text,
|
||||
@ -1833,9 +1850,11 @@ bool MainWindowEventFilter::eventFilter(QObject* watched, QEvent* event)
|
||||
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
if (watched == mainWindow->m_ui->menubar) {
|
||||
auto* m = static_cast<QMouseEvent*>(event);
|
||||
if (!mainWindow->m_ui->menubar->actionAt(m->pos())) {
|
||||
mainWindow->windowHandle()->startSystemMove();
|
||||
// Continue processing events, so menus keep working.
|
||||
return false;
|
||||
}
|
||||
} else if (watched == mainWindow->m_ui->toolBar) {
|
||||
if (!mainWindow->m_ui->toolBar->isMovable() || mainWindow->m_ui->toolBar->cursor() != Qt::SizeAllCursor) {
|
||||
mainWindow->windowHandle()->startSystemMove();
|
||||
|
@ -259,6 +259,9 @@ QProgressBar::chunk {
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
|
@ -115,13 +115,18 @@ void NixUtils::setLaunchAtStartup(bool enable)
|
||||
qWarning("Failed to create autostart desktop file.");
|
||||
return;
|
||||
}
|
||||
|
||||
const QString appImagePath = QString::fromLocal8Bit(qgetenv("APPIMAGE"));
|
||||
const bool isAppImage = !appImagePath.isNull() && QFile::exists(appImagePath);
|
||||
const QString executeablePath = isAppImage ? appImagePath : QApplication::applicationFilePath();
|
||||
|
||||
QTextStream stream(&desktopFile);
|
||||
stream.setCodec("UTF-8");
|
||||
stream << QStringLiteral("[Desktop Entry]") << '\n'
|
||||
<< QStringLiteral("Name=") << QApplication::applicationDisplayName() << '\n'
|
||||
<< QStringLiteral("GenericName=") << tr("Password Manager") << '\n'
|
||||
<< QStringLiteral("Exec=") << QApplication::applicationFilePath() << '\n'
|
||||
<< QStringLiteral("TryExec=") << QApplication::applicationFilePath() << '\n'
|
||||
<< QStringLiteral("Exec=") << executeablePath << '\n'
|
||||
<< QStringLiteral("TryExec=") << executeablePath << '\n'
|
||||
<< QStringLiteral("Icon=") << QApplication::applicationName().toLower() << '\n'
|
||||
<< QStringLiteral("StartupWMClass=keepassxc") << '\n'
|
||||
<< QStringLiteral("StartupNotify=true") << '\n'
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include "SSHAgent.h"
|
||||
|
||||
#include "core/Config.h"
|
||||
#include "core/Database.h"
|
||||
#include "core/Group.h"
|
||||
#include "core/Metadata.h"
|
||||
#include "crypto/ssh/BinaryStream.h"
|
||||
#include "crypto/ssh/OpenSSHKey.h"
|
||||
#include "sshagent/KeeAgentSettings.h"
|
||||
@ -31,11 +34,6 @@
|
||||
|
||||
Q_GLOBAL_STATIC(SSHAgent, s_sshAgent);
|
||||
|
||||
SSHAgent::~SSHAgent()
|
||||
{
|
||||
removeAllIdentities();
|
||||
}
|
||||
|
||||
SSHAgent* SSHAgent::instance()
|
||||
{
|
||||
return s_sshAgent;
|
||||
@ -427,18 +425,15 @@ void SSHAgent::setAutoRemoveOnLock(const OpenSSHKey& key, bool autoRemove)
|
||||
}
|
||||
}
|
||||
|
||||
void SSHAgent::databaseLocked()
|
||||
void SSHAgent::databaseLocked(QSharedPointer<Database> db)
|
||||
{
|
||||
auto* widget = qobject_cast<DatabaseWidget*>(sender());
|
||||
if (!widget) {
|
||||
if (!db) {
|
||||
return;
|
||||
}
|
||||
|
||||
QUuid databaseUuid = widget->database()->uuid();
|
||||
|
||||
auto it = m_addedKeys.begin();
|
||||
while (it != m_addedKeys.end()) {
|
||||
if (it.value().first != databaseUuid) {
|
||||
if (it.value().first != db->uuid()) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
@ -452,16 +447,14 @@ void SSHAgent::databaseLocked()
|
||||
}
|
||||
}
|
||||
|
||||
void SSHAgent::databaseUnlocked()
|
||||
void SSHAgent::databaseUnlocked(QSharedPointer<Database> db)
|
||||
{
|
||||
auto* widget = qobject_cast<DatabaseWidget*>(sender());
|
||||
if (!widget) {
|
||||
if (!db || !isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Entry* e : widget->database()->rootGroup()->entriesRecursive()) {
|
||||
if (widget->database()->metadata()->recycleBinEnabled()
|
||||
&& e->group() == widget->database()->metadata()->recycleBin()) {
|
||||
for (Entry* e : db->rootGroup()->entriesRecursive()) {
|
||||
if (db->metadata()->recycleBinEnabled() && e->group() == db->metadata()->recycleBin()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -483,7 +476,7 @@ void SSHAgent::databaseUnlocked()
|
||||
|
||||
// Add key to agent; ignore errors if we have previously added the key
|
||||
bool known_key = m_addedKeys.contains(key);
|
||||
if (!addIdentity(key, settings, widget->database()->uuid()) && !known_key) {
|
||||
if (!addIdentity(key, settings, db->uuid()) && !known_key) {
|
||||
emit error(m_error);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <QtCore>
|
||||
|
||||
#include "crypto/ssh/OpenSSHKey.h"
|
||||
#include "gui/DatabaseWidget.h"
|
||||
#include "sshagent/KeeAgentSettings.h"
|
||||
|
||||
class SSHAgent : public QObject
|
||||
@ -32,7 +31,7 @@ class SSHAgent : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~SSHAgent() override;
|
||||
~SSHAgent() override = default;
|
||||
static SSHAgent* instance();
|
||||
|
||||
bool isEnabled() const;
|
||||
@ -59,8 +58,8 @@ signals:
|
||||
void enabledChanged(bool enabled);
|
||||
|
||||
public slots:
|
||||
void databaseLocked();
|
||||
void databaseUnlocked();
|
||||
void databaseLocked(QSharedPointer<Database> db);
|
||||
void databaseUnlocked(QSharedPointer<Database> db);
|
||||
|
||||
private:
|
||||
const quint8 SSH_AGENT_FAILURE = 5;
|
||||
|
Loading…
Reference in New Issue
Block a user