copy TOTP again if it expires before clipboard erasure

Would solve/help with the underlying problem in issue #4461
This commit is contained in:
Xavier Valls 2021-04-26 20:18:43 +02:00
parent fd0bdaae80
commit a59de91d92
8 changed files with 43 additions and 0 deletions

View File

@ -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<Totp::Settings> settings)
{
beginUpdate();

View File

@ -24,6 +24,7 @@
#include <QPixmap>
#include <QPointer>
#include <QSet>
#include <QTimer>
#include <QUrl>
#include <QUuid>
@ -109,6 +110,7 @@ public:
QString notes() const;
QString attribute(const QString& key) const;
QString totp() const;
quint64 totpSecondsLeft() const;
QString totpSettingsString() const;
QSharedPointer<Totp::Settings> totpSettings() const;
int size() const;
@ -291,6 +293,8 @@ private:
bool m_modifiedSinceBegin;
QPointer<Group> m_group;
bool m_updateTimeinfo;
QTimer totptimer;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Entry::CloneFlags)

View File

@ -84,6 +84,11 @@ void Clipboard::setText(const QString& text, bool clear)
}
}
int Clipboard::secondsElapsed()
{
return m_secondsElapsed;
}
void Clipboard::clearCopiedText()
{
m_timer->stop();

View File

@ -37,6 +37,8 @@ public:
static Clipboard* instance();
int secondsElapsed();
public slots:
void clearCopiedText();

View File

@ -98,6 +98,7 @@ DatabaseWidget::DatabaseWidget(QSharedPointer<Database> 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();
}

View File

@ -258,6 +258,7 @@ private:
bool confirmDeleteEntries(QList<Entry*> entries, bool permanent);
void performIconDownloads(const QList<Entry*>& entries, bool force = false);
bool performSave(QString& errorMessage, const QString& fileName = {});
void pollToptOrStopAndDisconnect(Entry* entry);
QSharedPointer<Database> m_db;
@ -284,6 +285,8 @@ private:
QScopedPointer<Entry> m_newEntry;
QPointer<Group> m_newParent;
QPointer<QTimer> m_totpTimer;
QUuid m_groupBeforeLock;
QUuid m_entryBeforeLock;

View File

@ -182,6 +182,13 @@ QString Totp::writeSettings(const QSharedPointer<Totp::Settings>& settings,
}
}
quint64 Totp::secondsLeft(const QSharedPointer<Totp::Settings>& settings)
{
const Encoder& encoder = settings->encoder;
uint step = settings->custom ? settings->step : encoder.step;
return step - (qToBigEndian(static_cast<quint64>(Clock::currentSecondsSinceEpoch())) % step);
}
QString Totp::generateTotp(const QSharedPointer<Totp::Settings>& settings, const quint64 time)
{
Q_ASSERT(!settings.isNull());

View File

@ -86,6 +86,7 @@ namespace Totp
const QString& username = {},
bool forceOtp = false);
quint64 secondsLeft(const QSharedPointer<Totp::Settings>& settings);
QString generateTotp(const QSharedPointer<Totp::Settings>& settings, const quint64 time = 0ull);
QList<QPair<QString, QString>> supportedEncoders();