Merge pull request #1414 from keepassxreboot/feature/1360-fix-totp-crash

Fix multiple TOTP issues, resolves #1360
This commit is contained in:
Janek Bevendorff 2018-01-23 00:40:12 +01:00 committed by GitHub
commit 83f1a53d32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 47 deletions

View File

@ -45,6 +45,7 @@ Entry::Entry()
m_data.totpStep = Totp::defaultStep; m_data.totpStep = Totp::defaultStep;
m_data.totpDigits = Totp::defaultDigits; m_data.totpDigits = Totp::defaultDigits;
connect(m_attributes, SIGNAL(modified()), SLOT(updateTotp()));
connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified())); connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified()));
connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged())); connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged()));
connect(m_attachments, SIGNAL(modified()), this, SIGNAL(modified())); connect(m_attachments, SIGNAL(modified()), this, SIGNAL(modified()));
@ -343,9 +344,8 @@ QString Entry::totp() const
QString output = Totp::generateTotp(seed.toLatin1(), time, m_data.totpDigits, m_data.totpStep); QString output = Totp::generateTotp(seed.toLatin1(), time, m_data.totpDigits, m_data.totpStep);
return QString(output); return QString(output);
} else {
return QString("");
} }
return {};
} }
void Entry::setTotp(const QString& seed, quint8& step, quint8& digits) void Entry::setTotp(const QString& seed, quint8& step, quint8& digits)
@ -388,23 +388,6 @@ QString Entry::totpSeed() const
secret = m_attributes->value("TOTP Seed"); secret = m_attributes->value("TOTP Seed");
} }
m_data.totpDigits = Totp::defaultDigits;
m_data.totpStep = Totp::defaultStep;
if (m_attributes->hasKey("TOTP Settings")) {
// this regex must be kept in sync with the set of allowed short names Totp::shortNameToEncoder
QRegularExpression rx(QString("(\\d+);((?:\\d+)|S)"));
QRegularExpressionMatch m = rx.match(m_attributes->value("TOTP Settings"));
if (m.hasMatch()) {
m_data.totpStep = m.captured(1).toUInt();
if (Totp::shortNameToEncoder.contains(m.captured(2))) {
m_data.totpDigits = Totp::shortNameToEncoder[m.captured(2)];
} else {
m_data.totpDigits = m.captured(2).toUInt();
}
}
}
return Totp::parseOtpString(secret, m_data.totpDigits, m_data.totpStep); return Totp::parseOtpString(secret, m_data.totpDigits, m_data.totpStep);
} }
@ -722,6 +705,33 @@ void Entry::updateModifiedSinceBegin()
m_modifiedSinceBegin = true; m_modifiedSinceBegin = true;
} }
/**
* Update TOTP data whenever entry attributes have changed.
*/
void Entry::updateTotp()
{
m_data.totpDigits = Totp::defaultDigits;
m_data.totpStep = Totp::defaultStep;
if (!m_attributes->hasKey("TOTP Settings")) {
return;
}
// this regex must be kept in sync with the set of allowed short names Totp::shortNameToEncoder
QRegularExpression rx(QString("(\\d+);((?:\\d+)|S)"));
QRegularExpressionMatch m = rx.match(m_attributes->value("TOTP Settings"));
if (!m.hasMatch()) {
return;
}
m_data.totpStep = static_cast<quint8>(m.captured(1).toUInt());
if (Totp::shortNameToEncoder.contains(m.captured(2))) {
m_data.totpDigits = Totp::shortNameToEncoder[m.captured(2)];
} else {
m_data.totpDigits = static_cast<quint8>(m.captured(2).toUInt());
}
}
QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const QString Entry::resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const
{ {
if (maxDepth <= 0) { if (maxDepth <= 0) {

View File

@ -210,6 +210,7 @@ private slots:
void emitDataChanged(); void emitDataChanged();
void updateTimeinfo(); void updateTimeinfo();
void updateModifiedSinceBegin(); void updateModifiedSinceBegin();
void updateTotp();
private: private:
QString resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const; QString resolveMultiplePlaceholdersRecursive(const QString& str, int maxDepth) const;

View File

@ -20,16 +20,12 @@
#include "ui_DetailsWidget.h" #include "ui_DetailsWidget.h"
#include <QDebug> #include <QDebug>
#include <QTimer>
#include <QDir> #include <QDir>
#include <QDesktopServices> #include <QDesktopServices>
#include <QTemporaryFile>
#include "core/Config.h" #include "core/Config.h"
#include "core/FilePath.h" #include "core/FilePath.h"
#include "core/TimeInfo.h"
#include "gui/Clipboard.h" #include "gui/Clipboard.h"
#include "gui/DatabaseWidget.h"
#include "entry/EntryAttachmentsModel.h" #include "entry/EntryAttachmentsModel.h"
DetailsWidget::DetailsWidget(QWidget* parent) DetailsWidget::DetailsWidget(QWidget* parent)
@ -70,6 +66,9 @@ DetailsWidget::DetailsWidget(QWidget* parent)
DetailsWidget::~DetailsWidget() DetailsWidget::~DetailsWidget()
{ {
if (m_timer) {
delete m_timer;
}
} }
void DetailsWidget::getSelectedEntry(Entry* selectedEntry) void DetailsWidget::getSelectedEntry(Entry* selectedEntry)
@ -154,13 +153,13 @@ void DetailsWidget::getSelectedEntry(Entry* selectedEntry)
if (m_currentEntry->hasTotp()) { if (m_currentEntry->hasTotp()) {
m_step = m_currentEntry->totpStep(); m_step = m_currentEntry->totpStep();
if (nullptr != m_timer) { if (m_timer) {
m_timer->stop(); delete m_timer;
} }
m_timer = new QTimer(this); m_timer = new QTimer(selectedEntry);
connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTotp())); connect(m_timer, SIGNAL(timeout()), this, SLOT(updateTotp()));
updateTotp(); updateTotp();
m_timer->start(m_step * 10); m_timer->start(m_step * 1000);
m_ui->totpButton->show(); m_ui->totpButton->show();
} }
@ -288,7 +287,7 @@ void DetailsWidget::updateTotp()
QString firstHalf = totpCode.left(totpCode.size() / 2); QString firstHalf = totpCode.left(totpCode.size() / 2);
QString secondHalf = totpCode.mid(totpCode.size() / 2); QString secondHalf = totpCode.mid(totpCode.size() / 2);
m_ui->totpLabel->setText(firstHalf + " " + secondHalf); m_ui->totpLabel->setText(firstHalf + " " + secondHalf);
} else if (nullptr != m_timer) { } else if (m_timer) {
m_timer->stop(); m_timer->stop();
} }
} }

View File

@ -20,6 +20,7 @@
#include "gui/DatabaseWidget.h" #include "gui/DatabaseWidget.h"
#include <QWidget> #include <QWidget>
#include <QTimer>
namespace Ui { namespace Ui {
class DetailsWidget; class DetailsWidget;
@ -67,7 +68,7 @@ private:
Entry* m_currentEntry; Entry* m_currentEntry;
Group* m_currentGroup; Group* m_currentGroup;
quint8 m_step; quint8 m_step;
QTimer* m_timer; QPointer<QTimer> m_timer = nullptr;
QWidget* m_attributesTabWidget; QWidget* m_attributesTabWidget;
QWidget* m_attachmentsTabWidget; QWidget* m_attachmentsTabWidget;
QWidget* m_autotypeTabWidget; QWidget* m_autotypeTabWidget;

View File

@ -20,33 +20,24 @@
#include "ui_TotpDialog.h" #include "ui_TotpDialog.h"
#include "core/Config.h" #include "core/Config.h"
#include "core/Entry.h"
#include "gui/DatabaseWidget.h"
#include "gui/Clipboard.h" #include "gui/Clipboard.h"
#include <QTimer>
#include <QDateTime>
#include <QPushButton>
TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry) TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry)
: QDialog(parent) : QDialog(parent)
, m_ui(new Ui::TotpDialog()) , m_ui(new Ui::TotpDialog())
, m_totpUpdateTimer(new QTimer(entry))
, m_entry(entry)
{ {
m_entry = entry;
m_parent = parent;
m_step = m_entry->totpStep();
m_ui->setupUi(this); m_ui->setupUi(this);
m_step = m_entry->totpStep();
uCounter = resetCounter(); uCounter = resetCounter();
updateProgressBar(); updateProgressBar();
QTimer* timer = new QTimer(this); connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateProgressBar()));
connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); connect(m_totpUpdateTimer, SIGNAL(timeout()), this, SLOT(updateSeconds()));
connect(timer, SIGNAL(timeout()), this, SLOT(updateSeconds())); m_totpUpdateTimer->start(m_step * 10);
timer->start(m_step * 10);
updateTotp(); updateTotp();
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
@ -61,7 +52,7 @@ void TotpDialog::copyToClipboard()
{ {
clipboard()->setText(m_entry->totp()); clipboard()->setText(m_entry->totp());
if (config()->get("MinimizeOnCopy").toBool()) { if (config()->get("MinimizeOnCopy").toBool()) {
m_parent->window()->showMinimized(); qobject_cast<DatabaseWidget*>(parent())->window()->showMinimized();
} }
} }
@ -101,4 +92,7 @@ double TotpDialog::resetCounter()
TotpDialog::~TotpDialog() TotpDialog::~TotpDialog()
{ {
if (m_totpUpdateTimer) {
delete m_totpUpdateTimer;
}
} }

View File

@ -21,6 +21,8 @@
#include <QDialog> #include <QDialog>
#include <QScopedPointer> #include <QScopedPointer>
#include <QTimer>
#include <totp/totp.h>
#include "core/Entry.h" #include "core/Entry.h"
#include "core/Database.h" #include "core/Database.h"
#include "gui/DatabaseWidget.h" #include "gui/DatabaseWidget.h"
@ -39,8 +41,9 @@ public:
private: private:
double uCounter; double uCounter;
quint8 m_step; quint8 m_step = Totp::defaultStep;
QScopedPointer<Ui::TotpDialog> m_ui; QScopedPointer<Ui::TotpDialog> m_ui;
QPointer<QTimer> m_totpUpdateTimer;
private Q_SLOTS: private Q_SLOTS:
void updateTotp(); void updateTotp();
@ -51,7 +54,6 @@ private Q_SLOTS:
protected: protected:
Entry* m_entry; Entry* m_entry;
DatabaseWidget* m_parent;
}; };
#endif // KEEPASSX_TOTPDIALOG_H #endif // KEEPASSX_TOTPDIALOG_H