mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-01-27 14:57:09 -05:00
Cleanup and replumb back to functional state
This commit is contained in:
parent
9e2be34897
commit
b96b86bfa7
@ -4,9 +4,9 @@ if(WITH_XC_CRYPTO_SSH)
|
|||||||
set(crypto_ssh_SOURCES
|
set(crypto_ssh_SOURCES
|
||||||
bcrypt_pbkdf.cpp
|
bcrypt_pbkdf.cpp
|
||||||
blowfish.c
|
blowfish.c
|
||||||
ASN1Key.cpp
|
ASN1Key.cpp
|
||||||
BinaryStream.cpp
|
BinaryStream.cpp
|
||||||
OpenSSHKey.cpp
|
OpenSSHKey.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(crypto_ssh STATIC ${crypto_ssh_SOURCES})
|
add_library(crypto_ssh STATIC ${crypto_ssh_SOURCES})
|
||||||
|
@ -78,16 +78,17 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
|
|||||||
connect(this, SIGNAL(apply()), SLOT(saveSettings()));
|
connect(this, SIGNAL(apply()), SLOT(saveSettings()));
|
||||||
connect(this, SIGNAL(rejected()), SLOT(reject()));
|
connect(this, SIGNAL(rejected()), SLOT(reject()));
|
||||||
|
|
||||||
connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableAutoSaveOnExit(bool)));
|
// clang-format off
|
||||||
|
connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), SLOT(enableAutoSaveOnExit(bool)));
|
||||||
connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableSystray(bool)));
|
connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)), this, SLOT(enableSystray(bool)));
|
||||||
|
|
||||||
connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)), m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool)));
|
connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)),
|
||||||
connect(m_secUi->lockDatabaseIdleCheckBox,
|
m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool)));
|
||||||
SIGNAL(toggled(bool)),
|
connect(m_secUi->lockDatabaseIdleCheckBox, SIGNAL(toggled(bool)),
|
||||||
m_secUi->lockDatabaseIdleSpinBox,
|
m_secUi->lockDatabaseIdleSpinBox, SLOT(setEnabled(bool)));
|
||||||
SLOT(setEnabled(bool)));
|
connect(m_secUi->touchIDResetCheckBox, SIGNAL(toggled(bool)),
|
||||||
|
m_secUi->touchIDResetSpinBox, SLOT(setEnabled(bool)));
|
||||||
connect(m_secUi->touchIDResetCheckBox, SIGNAL(toggled(bool)), m_secUi->touchIDResetSpinBox, SLOT(setEnabled(bool)));
|
// clang-format on
|
||||||
|
|
||||||
#ifndef WITH_XC_NETWORKING
|
#ifndef WITH_XC_NETWORKING
|
||||||
m_secUi->privacy->setVisible(false);
|
m_secUi->privacy->setVisible(false);
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "gui/entry/EntryView.h"
|
#include "gui/entry/EntryView.h"
|
||||||
#include "gui/group/EditGroupWidget.h"
|
#include "gui/group/EditGroupWidget.h"
|
||||||
#include "gui/group/GroupView.h"
|
#include "gui/group/GroupView.h"
|
||||||
|
#include "keeshare/KeeShare.h"
|
||||||
#include "touchid/TouchID.h"
|
#include "touchid/TouchID.h"
|
||||||
|
|
||||||
#include "config-keepassx.h"
|
#include "config-keepassx.h"
|
||||||
@ -372,6 +373,9 @@ void DatabaseWidget::replaceDatabase(QSharedPointer<Database> db)
|
|||||||
connectDatabaseSignals();
|
connectDatabaseSignals();
|
||||||
m_groupView->changeDatabase(m_db);
|
m_groupView->changeDatabase(m_db);
|
||||||
processAutoOpen();
|
processAutoOpen();
|
||||||
|
#ifdef WITH_XC_KEESHARE
|
||||||
|
KeeShare::instance()->connectDatabase(m_db, oldDb);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseWidget::cloneEntry()
|
void DatabaseWidget::cloneEntry()
|
||||||
|
@ -161,12 +161,16 @@ MainWindow::MainWindow()
|
|||||||
#ifdef WITH_XC_KEESHARE
|
#ifdef WITH_XC_KEESHARE
|
||||||
KeeShare::init(this);
|
KeeShare::init(this);
|
||||||
m_ui->settingsWidget->addSettingsPage(new SettingsPageKeeShare(m_ui->tabWidget));
|
m_ui->settingsWidget->addSettingsPage(new SettingsPageKeeShare(m_ui->tabWidget));
|
||||||
|
connect(KeeShare::instance(), SIGNAL(sharingMessage(QString, MessageWidget::MessageType)),
|
||||||
|
SLOT(displayGlobalMessage(QString, MessageWidget::MessageType)));
|
||||||
#endif
|
#endif
|
||||||
setWindowIcon(filePath()->applicationIcon());
|
setWindowIcon(filePath()->applicationIcon());
|
||||||
m_ui->globalMessageWidget->setHidden(true);
|
m_ui->globalMessageWidget->setHidden(true);
|
||||||
|
// clang-format off
|
||||||
connect(m_ui->globalMessageWidget, &MessageWidget::linkActivated, &MessageWidget::openHttpUrl);
|
connect(m_ui->globalMessageWidget, &MessageWidget::linkActivated, &MessageWidget::openHttpUrl);
|
||||||
connect(m_ui->globalMessageWidget, SIGNAL(showAnimationStarted()), m_ui->globalMessageWidgetContainer, SLOT(show()));
|
connect(m_ui->globalMessageWidget, SIGNAL(showAnimationStarted()), m_ui->globalMessageWidgetContainer, SLOT(show()));
|
||||||
connect(m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), m_ui->globalMessageWidgetContainer, SLOT(hide()));
|
connect(m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), m_ui->globalMessageWidgetContainer, SLOT(hide()));
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
m_clearHistoryAction = new QAction(tr("Clear history"), m_ui->menuFile);
|
m_clearHistoryAction = new QAction(tr("Clear history"), m_ui->menuFile);
|
||||||
m_lastDatabasesActions = new QActionGroup(m_ui->menuRecentDatabases);
|
m_lastDatabasesActions = new QActionGroup(m_ui->menuRecentDatabases);
|
||||||
|
@ -63,6 +63,9 @@ EditGroupWidget::EditGroupWidget(QWidget* parent)
|
|||||||
|
|
||||||
addPage(tr("Group"), FilePath::instance()->icon("actions", "document-edit"), m_editGroupWidgetMain);
|
addPage(tr("Group"), FilePath::instance()->icon("actions", "document-edit"), m_editGroupWidgetMain);
|
||||||
addPage(tr("Icon"), FilePath::instance()->icon("apps", "preferences-desktop-icons"), m_editGroupWidgetIcons);
|
addPage(tr("Icon"), FilePath::instance()->icon("apps", "preferences-desktop-icons"), m_editGroupWidgetIcons);
|
||||||
|
#ifdef WITH_XC_KEESHARE
|
||||||
|
addEditPage(new EditGroupPageKeeShare(this));
|
||||||
|
#endif
|
||||||
addPage(tr("Properties"), FilePath::instance()->icon("actions", "document-properties"), m_editWidgetProperties);
|
addPage(tr("Properties"), FilePath::instance()->icon("actions", "document-properties"), m_editWidgetProperties);
|
||||||
|
|
||||||
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
|
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
|
||||||
@ -82,10 +85,6 @@ EditGroupWidget::EditGroupWidget(QWidget* parent)
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
connect(m_editGroupWidgetIcons, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage()));
|
connect(m_editGroupWidgetIcons, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage()));
|
||||||
|
|
||||||
#ifdef WITH_XC_KEESHARE
|
|
||||||
addEditPage(new EditGroupPageKeeShare(this));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EditGroupWidget::~EditGroupWidget()
|
EditGroupWidget::~EditGroupWidget()
|
||||||
|
@ -82,7 +82,6 @@ private:
|
|||||||
QPointer<EditWidgetProperties> m_editWidgetProperties;
|
QPointer<EditWidgetProperties> m_editWidgetProperties;
|
||||||
|
|
||||||
QScopedPointer<Group> m_temporaryGroup;
|
QScopedPointer<Group> m_temporaryGroup;
|
||||||
QPointer<Database> m_database;
|
|
||||||
QPointer<Group> m_group;
|
QPointer<Group> m_group;
|
||||||
QSharedPointer<Database> m_db;
|
QSharedPointer<Database> m_db;
|
||||||
|
|
||||||
|
@ -32,10 +32,10 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static const QString KeeShare_Reference("KeeShare/Reference");
|
static const QString KeeShare_Reference("KeeShare/Reference");
|
||||||
static const QString KeeShare_Own("KeeShare/Settings.own");
|
static const QString KeeShare_Own("KeeShare/Settings.own");
|
||||||
static const QString KeeShare_Foreign("KeeShare/Settings.foreign");
|
static const QString KeeShare_Foreign("KeeShare/Settings.foreign");
|
||||||
static const QString KeeShare_Active("KeeShare/Settings.active");
|
static const QString KeeShare_Active("KeeShare/Settings.active");
|
||||||
}
|
}
|
||||||
|
|
||||||
KeeShare* KeeShare::m_instance = nullptr;
|
KeeShare* KeeShare::m_instance = nullptr;
|
||||||
@ -49,6 +49,12 @@ KeeShare* KeeShare::instance()
|
|||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeeShare::KeeShare(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
connect(config(), SIGNAL(changed(QString)), SLOT(handleSettingsChanged(QString)));
|
||||||
|
}
|
||||||
|
|
||||||
void KeeShare::init(QObject* parent)
|
void KeeShare::init(QObject* parent)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_instance);
|
Q_ASSERT(!m_instance);
|
||||||
@ -162,61 +168,19 @@ QString KeeShare::indicatorSuffix(const Group* group, const QString& text)
|
|||||||
|
|
||||||
void KeeShare::connectDatabase(QSharedPointer<Database> newDb, QSharedPointer<Database> oldDb)
|
void KeeShare::connectDatabase(QSharedPointer<Database> newDb, QSharedPointer<Database> oldDb)
|
||||||
{
|
{
|
||||||
if (oldDb && m_observersByDatabase.contains(oldDb.data())) {
|
if (oldDb && m_observersByDatabase.contains(oldDb->uuid())) {
|
||||||
QPointer<ShareObserver> observer = m_observersByDatabase.take(oldDb.data());
|
QPointer<ShareObserver> observer = m_observersByDatabase.take(oldDb->uuid());
|
||||||
if (observer) {
|
if (observer) {
|
||||||
delete observer;
|
delete observer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newDb && !m_observersByDatabase.contains(newDb.data())) {
|
if (newDb && !m_observersByDatabase.contains(newDb->uuid())) {
|
||||||
QPointer<ShareObserver> observer(new ShareObserver(newDb, this));
|
QPointer<ShareObserver> observer(new ShareObserver(newDb, this));
|
||||||
m_observersByDatabase[newDb.data()] = observer;
|
m_observersByDatabase[newDb->uuid()] = observer;
|
||||||
connect(observer.data(),
|
connect(observer.data(),
|
||||||
SIGNAL(sharingMessage(QString, MessageWidget::MessageType)),
|
SIGNAL(sharingMessage(QString, MessageWidget::MessageType)),
|
||||||
this,
|
SIGNAL(sharingMessage(QString, MessageWidget::MessageType)));
|
||||||
SLOT(emitSharingMessage(QString, MessageWidget::MessageType)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeeShare::handleDatabaseOpened(QSharedPointer<Database> db)
|
|
||||||
{
|
|
||||||
QPointer<ShareObserver> observer = m_observersByDatabase.value(db.data());
|
|
||||||
if (observer) {
|
|
||||||
observer->handleDatabaseOpened();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeeShare::handleDatabaseSaved(QSharedPointer<Database> db)
|
|
||||||
{
|
|
||||||
QPointer<ShareObserver> observer = m_observersByDatabase.value(db.data());
|
|
||||||
if (observer) {
|
|
||||||
observer->handleDatabaseSaved();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeeShare::emitSharingMessage(const QString& message, KMessageWidget::MessageType type)
|
|
||||||
{
|
|
||||||
QObject* observer = sender();
|
|
||||||
auto db = m_databasesByObserver.value(observer);
|
|
||||||
if (db) {
|
|
||||||
emit sharingMessage(db, message, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeeShare::handleDatabaseDeleted(QObject* db)
|
|
||||||
{
|
|
||||||
auto observer = m_observersByDatabase.take(db);
|
|
||||||
if (observer) {
|
|
||||||
m_databasesByObserver.remove(observer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeeShare::handleObserverDeleted(QObject* observer)
|
|
||||||
{
|
|
||||||
auto database = m_databasesByObserver.take(observer);
|
|
||||||
if (database) {
|
|
||||||
m_observersByDatabase.remove(database.data());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,9 +190,3 @@ void KeeShare::handleSettingsChanged(const QString& key)
|
|||||||
emit activeChanged();
|
emit activeChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KeeShare::KeeShare(QObject* parent)
|
|
||||||
: QObject(parent)
|
|
||||||
{
|
|
||||||
connect(config(), SIGNAL(changed(QString)), this, SLOT(handleSettingsChanged(QString)));
|
|
||||||
}
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#define KEEPASSXC_KEESHARE_H
|
#define KEEPASSXC_KEESHARE_H
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QUuid>
|
||||||
|
|
||||||
#include "gui/MessageWidget.h"
|
#include "gui/MessageWidget.h"
|
||||||
#include "keeshare/KeeShareSettings.h"
|
#include "keeshare/KeeShareSettings.h"
|
||||||
@ -32,7 +32,7 @@ class QXmlStreamReader;
|
|||||||
|
|
||||||
class KeeShare : public QObject
|
class KeeShare : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static KeeShare* instance();
|
static KeeShare* instance();
|
||||||
static void init(QObject* parent);
|
static void init(QObject* parent);
|
||||||
@ -54,17 +54,12 @@ public:
|
|||||||
static QString referenceTypeLabel(const KeeShareSettings::Reference& reference);
|
static QString referenceTypeLabel(const KeeShareSettings::Reference& reference);
|
||||||
|
|
||||||
void connectDatabase(QSharedPointer<Database> newDb, QSharedPointer<Database> oldDb);
|
void connectDatabase(QSharedPointer<Database> newDb, QSharedPointer<Database> oldDb);
|
||||||
void handleDatabaseOpened(QSharedPointer<Database> db);
|
|
||||||
void handleDatabaseSaved(QSharedPointer<Database> db);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void activeChanged();
|
void activeChanged();
|
||||||
void sharingMessage(QSharedPointer<Database>, QString, MessageWidget::MessageType);
|
void sharingMessage(QString, MessageWidget::MessageType);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void emitSharingMessage(const QString&, MessageWidget::MessageType);
|
|
||||||
void handleDatabaseDeleted(QObject*);
|
|
||||||
void handleObserverDeleted(QObject*);
|
|
||||||
void handleSettingsChanged(const QString&);
|
void handleSettingsChanged(const QString&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -72,8 +67,7 @@ private:
|
|||||||
|
|
||||||
explicit KeeShare(QObject* parent);
|
explicit KeeShare(QObject* parent);
|
||||||
|
|
||||||
QMap<QObject*, QPointer<ShareObserver>> m_observersByDatabase;
|
QMap<QUuid, QPointer<ShareObserver>> m_observersByDatabase;
|
||||||
QMap<QObject*, QSharedPointer<Database>> m_databasesByObserver;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSXC_KEESHARE_H
|
#endif // KEEPASSXC_KEESHARE_H
|
||||||
|
@ -95,10 +95,6 @@ void SettingsWidgetKeeShare::saveSettings()
|
|||||||
// TODO HNH: This depends on the order of saving new data - a better model would be to
|
// TODO HNH: This depends on the order of saving new data - a better model would be to
|
||||||
// store changes to the settings in a temporary object and check on the final values
|
// store changes to the settings in a temporary object and check on the final values
|
||||||
// of this object (similar scheme to Entry) - this way we could validate the settings before save
|
// of this object (similar scheme to Entry) - this way we could validate the settings before save
|
||||||
if (active.in) {
|
|
||||||
emit settingsMessage(tr("Make sure to have a history size greater than 2 to prevent data loss when importing!"), MessageWidget::Warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeeShare::setOwn(m_own);
|
KeeShare::setOwn(m_own);
|
||||||
KeeShare::setForeign(m_foreign);
|
KeeShare::setForeign(m_foreign);
|
||||||
KeeShare::setActive(active);
|
KeeShare::setActive(active);
|
||||||
|
@ -48,84 +48,96 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
static const QString KeeShare_Signature("container.share.signature");
|
static const QString KeeShare_Signature("container.share.signature");
|
||||||
static const QString KeeShare_Container("container.share.kdbx");
|
static const QString KeeShare_Container("container.share.kdbx");
|
||||||
|
|
||||||
enum Trust
|
enum Trust
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Invalid,
|
Invalid,
|
||||||
Single,
|
Single,
|
||||||
Lasting,
|
Lasting,
|
||||||
Known,
|
Known,
|
||||||
Own
|
Own
|
||||||
};
|
};
|
||||||
|
|
||||||
QPair<Trust, KeeShareSettings::Certificate> check(QByteArray& data,
|
|
||||||
const KeeShareSettings::Reference& reference,
|
|
||||||
const KeeShareSettings::Certificate& ownCertificate,
|
|
||||||
const QList<KeeShareSettings::Certificate>& knownCertificates,
|
|
||||||
const KeeShareSettings::Sign& sign)
|
|
||||||
{
|
|
||||||
if (sign.signature.isEmpty()) {
|
|
||||||
QMessageBox warning;
|
|
||||||
warning.setIcon(QMessageBox::Warning);
|
|
||||||
warning.setWindowTitle(ShareObserver::tr("Untrustworthy container without signature"));
|
|
||||||
warning.setText(ShareObserver::tr("Do you want to import from unsigned container %1").arg(reference.path));
|
|
||||||
auto yes = warning.addButton(ShareObserver::tr("Import once"), QMessageBox::ButtonRole::YesRole);
|
|
||||||
auto no = warning.addButton(ShareObserver::tr("No"), QMessageBox::ButtonRole::NoRole);
|
|
||||||
warning.setDefaultButton(no);
|
|
||||||
warning.exec();
|
|
||||||
const auto trust = warning.clickedButton() == yes ? Single : None;
|
|
||||||
return qMakePair(trust, KeeShareSettings::Certificate());
|
|
||||||
}
|
|
||||||
auto key = sign.certificate.sshKey();
|
|
||||||
key.openKey(QString());
|
|
||||||
const Signature signer;
|
|
||||||
if (!signer.verify(data, sign.signature, key)) {
|
|
||||||
const QFileInfo info(reference.path);
|
|
||||||
qCritical("Invalid signature for sharing container %s.", qPrintable(info.absoluteFilePath()));
|
|
||||||
return qMakePair(Invalid, KeeShareSettings::Certificate());
|
|
||||||
}
|
|
||||||
if (ownCertificate.key == sign.certificate.key) {
|
|
||||||
return qMakePair(Own, ownCertificate);
|
|
||||||
}
|
|
||||||
for (const auto& certificate : knownCertificates) {
|
|
||||||
if (certificate.key == certificate.key && certificate.trusted) {
|
|
||||||
return qMakePair(Known, certificate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
QPair<Trust, KeeShareSettings::Certificate> check(QByteArray& data,
|
||||||
|
const KeeShareSettings::Reference& reference,
|
||||||
|
const KeeShareSettings::Certificate& ownCertificate,
|
||||||
|
const QList<KeeShareSettings::Certificate>& knownCertificates,
|
||||||
|
const KeeShareSettings::Sign& sign)
|
||||||
|
{
|
||||||
|
if (sign.signature.isEmpty()) {
|
||||||
QMessageBox warning;
|
QMessageBox warning;
|
||||||
warning.setIcon(QMessageBox::Question);
|
warning.setIcon(QMessageBox::Warning);
|
||||||
warning.setWindowTitle(ShareObserver::tr("Import from untrustworthy certificate for sharing container"));
|
warning.setWindowTitle(ShareObserver::tr("Untrustworthy container without signature"));
|
||||||
warning.setText(ShareObserver::tr("Do you want to trust %1 with the fingerprint of %2")
|
warning.setText(ShareObserver::tr("Do you want to import from unsigned container %1").arg(reference.path));
|
||||||
.arg(sign.certificate.signer)
|
auto yes = warning.addButton(ShareObserver::tr("Import once"), QMessageBox::ButtonRole::YesRole);
|
||||||
.arg(sign.certificate.fingerprint()));
|
|
||||||
auto yes = warning.addButton(ShareObserver::tr("Import and trust"), QMessageBox::ButtonRole::YesRole);
|
|
||||||
auto no = warning.addButton(ShareObserver::tr("No"), QMessageBox::ButtonRole::NoRole);
|
auto no = warning.addButton(ShareObserver::tr("No"), QMessageBox::ButtonRole::NoRole);
|
||||||
warning.setDefaultButton(no);
|
warning.setDefaultButton(no);
|
||||||
warning.exec();
|
warning.exec();
|
||||||
if (warning.clickedButton() != yes) {
|
const auto trust = warning.clickedButton() == yes ? Single : None;
|
||||||
qWarning("Prevented import due to untrusted certificate of %s", qPrintable(sign.certificate.signer));
|
return qMakePair(trust, KeeShareSettings::Certificate());
|
||||||
return qMakePair(None, sign.certificate);
|
|
||||||
}
|
|
||||||
return qMakePair(Lasting, sign.certificate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto key = sign.certificate.sshKey();
|
||||||
|
key.openKey(QString());
|
||||||
|
const Signature signer;
|
||||||
|
if (!signer.verify(data, sign.signature, key)) {
|
||||||
|
const QFileInfo info(reference.path);
|
||||||
|
qCritical("Invalid signature for sharing container %s.", qPrintable(info.absoluteFilePath()));
|
||||||
|
return qMakePair(Invalid, KeeShareSettings::Certificate());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ownCertificate.key == sign.certificate.key) {
|
||||||
|
return qMakePair(Own, ownCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& certificate : knownCertificates) {
|
||||||
|
if (certificate.key == certificate.key && certificate.trusted) {
|
||||||
|
return qMakePair(Known, certificate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox warning;
|
||||||
|
warning.setIcon(QMessageBox::Question);
|
||||||
|
warning.setWindowTitle(ShareObserver::tr("Import from untrustworthy certificate for sharing container"));
|
||||||
|
warning.setText(ShareObserver::tr("Do you want to trust %1 with the fingerprint of %2")
|
||||||
|
.arg(sign.certificate.signer)
|
||||||
|
.arg(sign.certificate.fingerprint()));
|
||||||
|
auto yes = warning.addButton(ShareObserver::tr("Import and trust"), QMessageBox::ButtonRole::YesRole);
|
||||||
|
auto no = warning.addButton(ShareObserver::tr("No"), QMessageBox::ButtonRole::NoRole);
|
||||||
|
warning.setDefaultButton(no);
|
||||||
|
warning.exec();
|
||||||
|
if (warning.clickedButton() != yes) {
|
||||||
|
qWarning("Prevented import due to untrusted certificate of %s", qPrintable(sign.certificate.signer));
|
||||||
|
return qMakePair(None, sign.certificate);
|
||||||
|
}
|
||||||
|
return qMakePair(Lasting, sign.certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // End Namespace
|
||||||
|
|
||||||
ShareObserver::ShareObserver(QSharedPointer<Database> db, QObject* parent)
|
ShareObserver::ShareObserver(QSharedPointer<Database> db, QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_db(std::move(db))
|
, m_db(std::move(db))
|
||||||
, m_fileWatcher(new BulkFileWatcher(this))
|
, m_fileWatcher(new BulkFileWatcher(this))
|
||||||
{
|
{
|
||||||
connect(KeeShare::instance(), SIGNAL(activeChanged()), this, SLOT(handleDatabaseChanged()));
|
connect(KeeShare::instance(), SIGNAL(activeChanged()), SLOT(handleDatabaseChanged()));
|
||||||
|
|
||||||
connect(m_db.data(), SIGNAL(modified()), this, SLOT(handleDatabaseChanged()));
|
connect(m_db.data(), SIGNAL(modified()), SLOT(handleDatabaseChanged()));
|
||||||
|
connect(m_db.data(), SIGNAL(databaseSaved()), SLOT(handleDatabaseSaved()));
|
||||||
|
|
||||||
connect(m_fileWatcher, SIGNAL(fileCreated(QString)), this, SLOT(handleFileCreated(QString)));
|
connect(m_fileWatcher, SIGNAL(fileCreated(QString)), SLOT(handleFileUpdated(QString)));
|
||||||
connect(m_fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(handleFileChanged(QString)));
|
connect(m_fileWatcher, SIGNAL(fileChanged(QString)), SLOT(handleFileUpdated(QString)));
|
||||||
connect(m_fileWatcher, SIGNAL(fileRemoved(QString)), this, SLOT(handleFileRemoved(QString)));
|
connect(m_fileWatcher, SIGNAL(fileRemoved(QString)), SLOT(handleFileUpdated(QString)));
|
||||||
|
|
||||||
|
const auto active = KeeShare::active();
|
||||||
|
if (!active.in && !active.out) {
|
||||||
|
deinitialize();
|
||||||
|
} else {
|
||||||
|
reinitialize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareObserver::~ShareObserver()
|
ShareObserver::~ShareObserver()
|
||||||
@ -147,6 +159,7 @@ void ShareObserver::reinitialize()
|
|||||||
KeeShareSettings::Reference oldReference;
|
KeeShareSettings::Reference oldReference;
|
||||||
KeeShareSettings::Reference newReference;
|
KeeShareSettings::Reference newReference;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto active = KeeShare::active();
|
const auto active = KeeShare::active();
|
||||||
QList<Update> updated;
|
QList<Update> updated;
|
||||||
QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
QList<Group*> groups = m_db->rootGroup()->groupsRecursive(true);
|
||||||
@ -155,6 +168,7 @@ void ShareObserver::reinitialize()
|
|||||||
if (couple.oldReference == couple.newReference) {
|
if (couple.oldReference == couple.newReference) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_groupToReference.remove(couple.group);
|
m_groupToReference.remove(couple.group);
|
||||||
m_referenceToGroup.remove(couple.oldReference);
|
m_referenceToGroup.remove(couple.oldReference);
|
||||||
m_shareToGroup.remove(couple.oldReference.path);
|
m_shareToGroup.remove(couple.oldReference.path);
|
||||||
@ -174,6 +188,7 @@ void ShareObserver::reinitialize()
|
|||||||
if (!update.oldReference.path.isEmpty()) {
|
if (!update.oldReference.path.isEmpty()) {
|
||||||
m_fileWatcher->removePath(update.oldReference.path);
|
m_fileWatcher->removePath(update.oldReference.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!update.newReference.path.isEmpty() && update.newReference.type != KeeShareSettings::Inactive) {
|
if (!update.newReference.path.isEmpty() && update.newReference.type != KeeShareSettings::Inactive) {
|
||||||
m_fileWatcher->addPath(update.newReference.path);
|
m_fileWatcher->addPath(update.newReference.path);
|
||||||
}
|
}
|
||||||
@ -196,6 +211,7 @@ void ShareObserver::reinitialize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyAbout(success, warning, error);
|
notifyAbout(success, warning, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,20 +245,8 @@ void ShareObserver::handleDatabaseChanged()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareObserver::handleFileUpdated(const QString& path, Change change)
|
void ShareObserver::handleFileUpdated(const QString& path)
|
||||||
{
|
{
|
||||||
switch (change) {
|
|
||||||
case Creation:
|
|
||||||
qDebug("File created %s", qPrintable(path));
|
|
||||||
break;
|
|
||||||
case Update:
|
|
||||||
qDebug("File changed %s", qPrintable(path));
|
|
||||||
break;
|
|
||||||
case Deletion:
|
|
||||||
qDebug("File deleted %s", qPrintable(path));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Result result = this->importFromReferenceContainer(path);
|
const Result result = this->importFromReferenceContainer(path);
|
||||||
if (!result.isValid()) {
|
if (!result.isValid()) {
|
||||||
return;
|
return;
|
||||||
@ -262,21 +266,6 @@ void ShareObserver::handleFileUpdated(const QString& path, Change change)
|
|||||||
notifyAbout(success, warning, error);
|
notifyAbout(success, warning, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareObserver::handleFileCreated(const QString& path)
|
|
||||||
{
|
|
||||||
handleFileUpdated(path, Creation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareObserver::handleFileChanged(const QString& path)
|
|
||||||
{
|
|
||||||
handleFileUpdated(path, Update);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShareObserver::handleFileRemoved(const QString& path)
|
|
||||||
{
|
|
||||||
handleFileUpdated(path, Deletion);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShareObserver::Result ShareObserver::importContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup)
|
ShareObserver::Result ShareObserver::importContainerInto(const KeeShareSettings::Reference& reference, Group* targetGroup)
|
||||||
{
|
{
|
||||||
const QFileInfo info(reference.path);
|
const QFileInfo info(reference.path);
|
||||||
@ -471,30 +460,11 @@ Database* ShareObserver::exportIntoContainer(const KeeShareSettings::Reference&
|
|||||||
return targetDb;
|
return targetDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSharedPointer<Database> ShareObserver::database() const
|
|
||||||
{
|
|
||||||
return m_db;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<Database> ShareObserver::database()
|
QSharedPointer<Database> ShareObserver::database()
|
||||||
{
|
{
|
||||||
return m_db;
|
return m_db;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShareObserver::handleDatabaseOpened()
|
|
||||||
{
|
|
||||||
if (!m_db) {
|
|
||||||
Q_ASSERT(m_db);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto active = KeeShare::active();
|
|
||||||
if (!active.in && !active.out) {
|
|
||||||
deinitialize();
|
|
||||||
} else {
|
|
||||||
reinitialize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<ShareObserver::Result> ShareObserver::exportIntoReferenceContainers()
|
QList<ShareObserver::Result> ShareObserver::exportIntoReferenceContainers()
|
||||||
{
|
{
|
||||||
QList<Result> results;
|
QList<Result> results;
|
||||||
|
@ -35,37 +35,23 @@ class Database;
|
|||||||
|
|
||||||
class ShareObserver : public QObject
|
class ShareObserver : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ShareObserver(QSharedPointer<Database> db, QObject* parent = nullptr);
|
explicit ShareObserver(QSharedPointer<Database> db, QObject* parent = nullptr);
|
||||||
~ShareObserver();
|
~ShareObserver();
|
||||||
|
|
||||||
void handleDatabaseSaved();
|
|
||||||
void handleDatabaseOpened();
|
|
||||||
|
|
||||||
const QSharedPointer<Database> database() const;
|
|
||||||
QSharedPointer<Database> database();
|
QSharedPointer<Database> database();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sharingMessage(QString, MessageWidget::MessageType);
|
void sharingMessage(QString, MessageWidget::MessageType);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void handleDatabaseChanged();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleFileCreated(const QString& path);
|
void handleDatabaseChanged();
|
||||||
void handleFileChanged(const QString& path);
|
void handleDatabaseSaved();
|
||||||
void handleFileRemoved(const QString& path);
|
void handleFileUpdated(const QString& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Change
|
|
||||||
{
|
|
||||||
Creation,
|
|
||||||
Update,
|
|
||||||
Deletion
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Result
|
struct Result
|
||||||
{
|
{
|
||||||
enum Type
|
enum Type
|
||||||
@ -97,7 +83,6 @@ private:
|
|||||||
QList<ShareObserver::Result> exportIntoReferenceContainers();
|
QList<ShareObserver::Result> exportIntoReferenceContainers();
|
||||||
void deinitialize();
|
void deinitialize();
|
||||||
void reinitialize();
|
void reinitialize();
|
||||||
void handleFileUpdated(const QString& path, Change change);
|
|
||||||
void notifyAbout(const QStringList& success, const QStringList& warning, const QStringList& error);
|
void notifyAbout(const QStringList& success, const QStringList& warning, const QStringList& error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -55,10 +55,10 @@ EditGroupWidgetKeeShare::EditGroupWidgetKeeShare(QWidget* parent)
|
|||||||
|
|
||||||
connect(KeeShare::instance(), SIGNAL(activeChanged()), SLOT(showSharingState()));
|
connect(KeeShare::instance(), SIGNAL(activeChanged()), SLOT(showSharingState()));
|
||||||
|
|
||||||
const auto types = QList<KeeShareSettings::Type>() << KeeShareSettings::Inactive
|
const auto types = QList<KeeShareSettings::Type>() << KeeShareSettings::Inactive
|
||||||
<< KeeShareSettings::ImportFrom
|
<< KeeShareSettings::ImportFrom
|
||||||
<< KeeShareSettings::ExportTo
|
<< KeeShareSettings::ExportTo
|
||||||
<< KeeShareSettings::SynchronizeWith;
|
<< KeeShareSettings::SynchronizeWith;
|
||||||
for (const auto& type : types) {
|
for (const auto& type : types) {
|
||||||
QString name;
|
QString name;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -121,7 +121,6 @@ void EditGroupWidgetKeeShare::update()
|
|||||||
m_ui->pathEdit->clear();
|
m_ui->pathEdit->clear();
|
||||||
m_ui->passwordGenerator->hide();
|
m_ui->passwordGenerator->hide();
|
||||||
m_ui->togglePasswordGeneratorButton->setChecked(false);
|
m_ui->togglePasswordGeneratorButton->setChecked(false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const auto reference = KeeShare::referenceOf(m_temporaryGroup);
|
const auto reference = KeeShare::referenceOf(m_temporaryGroup);
|
||||||
|
|
||||||
@ -179,14 +178,9 @@ void EditGroupWidgetKeeShare::selectPath()
|
|||||||
}
|
}
|
||||||
switch (reference.type) {
|
switch (reference.type) {
|
||||||
case KeeShareSettings::ImportFrom:
|
case KeeShareSettings::ImportFrom:
|
||||||
filename = fileDialog()->getFileName(this,
|
filename = fileDialog()->getFileName(
|
||||||
tr("Select import source"),
|
this, tr("Select import source"), defaultDirPath, filters, nullptr, QFileDialog::DontConfirmOverwrite,
|
||||||
defaultDirPath,
|
filetype, filename);
|
||||||
filters,
|
|
||||||
nullptr,
|
|
||||||
QFileDialog::DontConfirmOverwrite,
|
|
||||||
filetype,
|
|
||||||
filename);
|
|
||||||
break;
|
break;
|
||||||
case KeeShareSettings::ExportTo:
|
case KeeShareSettings::ExportTo:
|
||||||
filename = fileDialog()->getFileName(
|
filename = fileDialog()->getFileName(
|
||||||
@ -203,7 +197,7 @@ void EditGroupWidgetKeeShare::selectPath()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPath(filename);
|
m_ui->pathEdit->setText(filename);
|
||||||
config()->set("KeeShare/LastShareDir", QFileInfo(filename).absolutePath());
|
config()->set("KeeShare/LastShareDir", QFileInfo(filename).absolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,5 +9,5 @@ if(WITH_XC_SSHAGENT)
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_library(sshagent STATIC ${sshagent_SOURCES})
|
add_library(sshagent STATIC ${sshagent_SOURCES})
|
||||||
target_link_libraries(sshagent Qt5::Core Qt5::Widgets Qt5::Network ${GCRYPT_LIBRARIES} ${crypto_ssh_LIB})
|
target_link_libraries(sshagent Qt5::Core Qt5::Widgets Qt5::Network ${GCRYPT_LIBRARIES} ${crypto_ssh_LIB})
|
||||||
endif()
|
endif()
|
||||||
|
@ -99,7 +99,12 @@ set(TEST_LIBRARIES
|
|||||||
${GPGERROR_LIBRARIES}
|
${GPGERROR_LIBRARIES}
|
||||||
${ZLIB_LIBRARIES})
|
${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
set(testsupport_SOURCES TestGlobal.h modeltest.cpp FailDevice.cpp mock/MockClock.cpp util/TemporaryFile.cpp stub/TestRandom.cpp)
|
set(testsupport_SOURCES
|
||||||
|
modeltest.cpp
|
||||||
|
FailDevice.cpp
|
||||||
|
mock/MockClock.cpp
|
||||||
|
util/TemporaryFile.cpp
|
||||||
|
stub/TestRandom.cpp)
|
||||||
add_library(testsupport STATIC ${testsupport_SOURCES})
|
add_library(testsupport STATIC ${testsupport_SOURCES})
|
||||||
target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test)
|
target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user