diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 49beb1e9e..4aa2fe8e6 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -539,6 +539,14 @@ QString Entry::totp() const return {}; } +quint64 Entry::totpSecondsLeft() const +{ + if (hasTotp()) { + return Totp::secondsLeft(m_data.totpSettings); + } + return {}; +} + void Entry::setTotp(QSharedPointer settings) { beginUpdate(); diff --git a/src/core/Entry.h b/src/core/Entry.h index 88a89761a..2f0b5e718 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -109,6 +110,7 @@ public: QString notes() const; QString attribute(const QString& key) const; QString totp() const; + quint64 totpSecondsLeft() const; QString totpSettingsString() const; QSharedPointer totpSettings() const; int size() const; @@ -291,6 +293,8 @@ private: bool m_modifiedSinceBegin; QPointer m_group; bool m_updateTimeinfo; + + QTimer totptimer; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Entry::CloneFlags) diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp index 804a53143..5cbcd5708 100644 --- a/src/gui/Clipboard.cpp +++ b/src/gui/Clipboard.cpp @@ -84,6 +84,11 @@ void Clipboard::setText(const QString& text, bool clear) } } +int Clipboard::secondsElapsed() +{ + return m_secondsElapsed; +} + void Clipboard::clearCopiedText() { m_timer->stop(); diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h index c97d91881..c0a549147 100644 --- a/src/gui/Clipboard.h +++ b/src/gui/Clipboard.h @@ -37,6 +37,8 @@ public: static Clipboard* instance(); + int secondsElapsed(); + public slots: void clearCopiedText(); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index ada611d37..6644a3979 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -98,6 +98,7 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) , m_keepass1OpenWidget(new KeePass1OpenWidget(this)) , m_opVaultOpenWidget(new OpVaultOpenWidget(this)) , m_groupView(new GroupView(m_db.data(), m_mainSplitter)) + , m_totpTimer(new QTimer(this)) , m_saveAttempts(0) { Q_ASSERT(m_db); @@ -715,6 +716,16 @@ void DatabaseWidget::setClipboardTextAndMinimize(const QString& text) } } +void DatabaseWidget::pollToptOrStopAndDisconnect(Entry* e) +{ + auto clipboardTimeout = config()->get(Config::Security_ClearClipboardTimeout).toInt(); + if (clipboard()->secondsElapsed() < clipboardTimeout) { + setClipboardTextAndMinimize(e->totp()); + } + m_totpTimer->stop(); + disconnect(m_totpTimer); +} + #ifdef WITH_XC_SSHAGENT void DatabaseWidget::addToAgent() { @@ -1220,6 +1231,8 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod case EntryModel::Totp: if (entry->hasTotp()) { setClipboardTextAndMinimize(entry->totp()); + m_totpTimer->start(entry->totpSecondsLeft() * 1000); + connect(m_totpTimer, &QTimer::timeout, this, [=]() { this->pollToptOrStopAndDisconnect(entry); }); } else { setupTotp(); } diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index e56e65956..bce33e6e7 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -258,6 +258,7 @@ private: bool confirmDeleteEntries(QList entries, bool permanent); void performIconDownloads(const QList& entries, bool force = false); bool performSave(QString& errorMessage, const QString& fileName = {}); + void pollToptOrStopAndDisconnect(Entry* entry); QSharedPointer m_db; @@ -284,6 +285,8 @@ private: QScopedPointer m_newEntry; QPointer m_newParent; + QPointer m_totpTimer; + QUuid m_groupBeforeLock; QUuid m_entryBeforeLock; diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp index 1936cce75..bb98004a7 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -182,6 +182,13 @@ QString Totp::writeSettings(const QSharedPointer& settings, } } +quint64 Totp::secondsLeft(const QSharedPointer& settings) +{ + const Encoder& encoder = settings->encoder; + uint step = settings->custom ? settings->step : encoder.step; + return step - (qToBigEndian(static_cast(Clock::currentSecondsSinceEpoch())) % step); +} + QString Totp::generateTotp(const QSharedPointer& settings, const quint64 time) { Q_ASSERT(!settings.isNull()); diff --git a/src/totp/totp.h b/src/totp/totp.h index e21f55571..0bbe35a7e 100644 --- a/src/totp/totp.h +++ b/src/totp/totp.h @@ -86,6 +86,7 @@ namespace Totp const QString& username = {}, bool forceOtp = false); + quint64 secondsLeft(const QSharedPointer& settings); QString generateTotp(const QSharedPointer& settings, const quint64 time = 0ull); QList> supportedEncoders();