Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan White <support@dmapps.us>2022-09-01 13:54:34 +0300
committerJonathan White <support@dmapps.us>2022-09-05 17:40:48 +0300
commit735b245a3be0716735101095a77aa38295e0a28e (patch)
tree8e5e9d54d11b5695d9b49112dd0d22b49ae9cb34
parentbd809ba90b25d9a0a7634353025efcd0e4c66880 (diff)
Fix OPVault import when there are multiple OTP fieldshotfix/opvault-totp
* Fix #8371 - store multiple OTP fields as `otp_#` instead of silently discarding them.
-rw-r--r--src/format/OpVaultReaderSections.cpp11
-rw-r--r--tests/TestOpVaultReader.cpp10
2 files changed, 20 insertions, 1 deletions
diff --git a/src/format/OpVaultReaderSections.cpp b/src/format/OpVaultReaderSections.cpp
index 610f997ec..661b9d6c3 100644
--- a/src/format/OpVaultReaderSections.cpp
+++ b/src/format/OpVaultReaderSections.cpp
@@ -84,7 +84,16 @@ void OpVaultReader::fillFromSectionField(Entry* entry, const QString& sectionNam
auto kind = field["k"].toString();
if (attrName.startsWith("TOTP_")) {
- if (attrValue.startsWith("otpauth://")) {
+ if (entry->hasTotp()) {
+ // Store multiple TOTP definitions as additional otp attributes
+ int i = 0;
+ QString name("otp");
+ auto attributes = entry->attributes()->keys();
+ while (attributes.contains(name)) {
+ name = QString("otp_%1").arg(++i);
+ }
+ entry->attributes()->set(name, attrValue);
+ } else if (attrValue.startsWith("otpauth://")) {
QUrlQuery query(attrValue);
// at least as of 1Password 7, they don't append the digits= and period= which totp.cpp requires
if (!query.hasQueryItem("digits")) {
diff --git a/tests/TestOpVaultReader.cpp b/tests/TestOpVaultReader.cpp
index aa95880a0..a5d05e9b0 100644
--- a/tests/TestOpVaultReader.cpp
+++ b/tests/TestOpVaultReader.cpp
@@ -24,6 +24,7 @@
#include "format/OpVaultReader.h"
#include "totp/totp.h"
+#include <QJsonObject>
#include <QList>
#include <QStringList>
#include <QTest>
@@ -110,6 +111,15 @@ void TestOpVaultReader::testReadIntoDatabase()
QCOMPARE(totpSettings->digits, static_cast<unsigned int>(8));
QCOMPARE(totpSettings->step, static_cast<unsigned int>(45));
+ // Add another OTP to this entry to confirm it doesn't overwrite the existing one
+ auto field = QJsonObject::fromVariantMap({{"n", "TOTP_SETTINGS"}, {"v", "otpauth://test.url?digits=6"}});
+ reader.fillFromSectionField(entry, "", field);
+ QVERIFY(entry->hasTotp());
+ totpSettings = entry->totpSettings();
+ QCOMPARE(totpSettings->digits, static_cast<unsigned int>(8));
+ QCOMPARE(totpSettings->step, static_cast<unsigned int>(45));
+ QVERIFY(entry->attributes()->contains("otp_1"));
+
// Confirm trashed entries are sent to the recycle bin
auto recycleBin = db->metadata()->recycleBin();
QVERIFY(recycleBin);