Properly save custom header data

Ensure adding custom data upgrades to KDBX4
Implement review feedback
This commit is contained in:
Janek Bevendorff
2018-02-18 21:01:22 +01:00
parent 114f00e1e8
commit 5410d78bbb
26 changed files with 189 additions and 174 deletions

View File

@@ -33,7 +33,6 @@ QTEST_GUILESS_MAIN(TestKdbx3)
void TestKdbx3::initTestCaseImpl()
{
}
Database* TestKdbx3::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)

View File

@@ -131,6 +131,7 @@ void TestKdbx4::testFormat400Upgrade()
{
QFETCH(Uuid, kdfUuid);
QFETCH(Uuid, cipherUuid);
QFETCH(bool, addCustomData);
QFETCH(quint32, expectedVersion);
QScopedPointer<Database> sourceDb(new Database());
@@ -147,6 +148,12 @@ void TestKdbx4::testFormat400Upgrade()
// upgrade to KDBX 4 by changing KDF and Cipher
sourceDb->changeKdf(KeePass2::uuidToKdf(kdfUuid));
sourceDb->setCipher(cipherUuid);
if (addCustomData) {
sourceDb->metadata()->customData()->set("CustomPublicData", "Hey look, I turned myself into a pickle!");
sourceDb->rootGroup()->customData()->set("CustomGroupData", "I just killed my family! I don't care who they were!");
}
KeePass2Writer writer;
writer.writeDatabase(&buffer, sourceDb.data());
if (writer.hasError()) {
@@ -165,26 +172,39 @@ void TestKdbx4::testFormat400Upgrade()
QCOMPARE(targetDb->metadata()->name(), sourceDb->metadata()->name());
QCOMPARE(reader.version(), expectedVersion);
QCOMPARE(targetDb->kdf()->uuid(), sourceDb->kdf()->uuid());
QCOMPARE(targetDb->cipher(), cipherUuid);
QCOMPARE(*targetDb->metadata()->customData(), *sourceDb->metadata()->customData());
QCOMPARE(*targetDb->rootGroup()->customData(), *sourceDb->rootGroup()->customData());
}
void TestKdbx4::testFormat400Upgrade_data()
{
QTest::addColumn<Uuid>("kdfUuid");
QTest::addColumn<Uuid>("cipherUuid");
QTest::addColumn<bool>("addCustomData");
QTest::addColumn<quint32>("expectedVersion");
auto constexpr kdbx3 = KeePass2::FILE_VERSION_3_1 & KeePass2::FILE_VERSION_CRITICAL_MASK;
auto constexpr kdbx4 = KeePass2::FILE_VERSION_4 & KeePass2::FILE_VERSION_CRITICAL_MASK;
QTest::newRow("Argon2 + AES") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES << kdbx4;
QTest::newRow("AES-KDF + AES") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES << kdbx4;
QTest::newRow("AES-KDF (legacy) + AES") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES << kdbx3;
QTest::newRow("Argon2 + ChaCha20") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_CHACHA20 << kdbx4;
QTest::newRow("AES-KDF + ChaCha20") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_CHACHA20 << kdbx4;
QTest::newRow("AES-KDF (legacy) + ChaCha20") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_CHACHA20 << kdbx3;
QTest::newRow("Argon2 + Twofish") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_TWOFISH << kdbx4;
QTest::newRow("AES-KDF + Twofish") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_TWOFISH << kdbx4;
QTest::newRow("AES-KDF (legacy) + Twofish") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_TWOFISH << kdbx3;
QTest::newRow("Argon2 + AES") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES << false << kdbx4;
QTest::newRow("AES-KDF + AES") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES << false << kdbx4;
QTest::newRow("AES-KDF (legacy) + AES") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES << false << kdbx3;
QTest::newRow("Argon2 + AES + CustomData") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES << true << kdbx4;
QTest::newRow("AES-KDF + AES + CustomData") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES << true << kdbx4;
QTest::newRow("AES-KDF (legacy) + AES + CustomData") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES << true << kdbx4;
QTest::newRow("Argon2 + ChaCha20") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_CHACHA20 << false << kdbx4;
QTest::newRow("AES-KDF + ChaCha20") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_CHACHA20 << false << kdbx4;
QTest::newRow("AES-KDF (legacy) + ChaCha20") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_CHACHA20 << false << kdbx3;
QTest::newRow("Argon2 + ChaCha20 + CustomData") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_CHACHA20 << true << kdbx4;
QTest::newRow("AES-KDF + ChaCha20 + CustomData") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_CHACHA20 << true << kdbx4;
QTest::newRow("AES-KDF (legacy) + ChaCha20 + CustomData") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_CHACHA20 << true << kdbx4;
QTest::newRow("Argon2 + Twofish") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_TWOFISH << false << kdbx4;
QTest::newRow("AES-KDF + Twofish") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_TWOFISH << false << kdbx4;
QTest::newRow("AES-KDF (legacy) + Twofish") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_TWOFISH << false << kdbx3;
QTest::newRow("Argon2 + Twofish + CustomData") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_TWOFISH << true << kdbx4;
QTest::newRow("AES-KDF + Twofish + CustomData") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_TWOFISH << true << kdbx4;
QTest::newRow("AES-KDF (legacy) + Twofish + CustomData") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_TWOFISH << true << kdbx4;
}

View File

@@ -124,15 +124,6 @@ void TestKeePass2Format::testXmlCustomIcons()
}
}
void TestKeePass2Format::testXmlCustomData()
{
QHash<QString, QString> customFields = m_xmlDb->metadata()->customFields();
QCOMPARE(customFields.size(), 2);
QCOMPARE(customFields.value("A Sample Test Key"), QString("valu"));
QCOMPARE(customFields.value("custom key"), QString("blub"));
}
void TestKeePass2Format::testXmlGroupRoot()
{
const Group* group = m_xmlDb->rootGroup();
@@ -155,7 +146,6 @@ void TestKeePass2Format::testXmlGroupRoot()
QCOMPARE(group->autoTypeEnabled(), Group::Inherit);
QCOMPARE(group->searchingEnabled(), Group::Inherit);
QCOMPARE(group->lastTopVisibleEntry()->uuid().toBase64(), QString("+wSUOv6qf0OzW8/ZHAs2sA=="));
QCOMPARE(group->children().size(), 3);
QVERIFY(m_xmlDb->metadata()->recycleBin() == m_xmlDb->rootGroup()->children().at(2));

View File

@@ -40,7 +40,6 @@ private slots:
*/
void testXmlMetadata();
void testXmlCustomIcons();
void testXmlCustomData();
void testXmlGroupRoot();
void testXmlGroup1();
void testXmlGroup2();

View File

@@ -40,31 +40,31 @@ void TestModified::testSignals()
CompositeKey compositeKey;
Database* db = new Database();
Group* root = db->rootGroup();
QSignalSpy spyModified(db, SIGNAL(modifiedImmediate()));
QScopedPointer<Database> db(new Database());
auto* root = db->rootGroup();
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
db->setKey(compositeKey);
QCOMPARE(spyModified.count(), ++spyCount);
Group* group1 = new Group();
auto* group1 = new Group();
group1->setParent(root);
QCOMPARE(spyModified.count(), ++spyCount);
Group* group2 = new Group();
auto* group2 = new Group();
group2->setParent(root);
QCOMPARE(spyModified.count(), ++spyCount);
group2->setParent(root, 0);
QCOMPARE(spyModified.count(), ++spyCount);
Entry* entry1 = new Entry();
auto* entry1 = new Entry();
entry1->setGroup(group1);
QCOMPARE(spyModified.count(), ++spyCount);
Database* db2 = new Database();
Group* root2 = db2->rootGroup();
QSignalSpy spyModified2(db2, SIGNAL(modifiedImmediate()));
QScopedPointer<Database> db2(new Database());
auto* root2 = db2->rootGroup();
QSignalSpy spyModified2(db2.data(), SIGNAL(modifiedImmediate()));
group1->setParent(root2);
QCOMPARE(spyModified.count(), ++spyCount);
@@ -74,7 +74,7 @@ void TestModified::testSignals()
QCOMPARE(spyModified.count(), spyCount);
QCOMPARE(spyModified2.count(), ++spyCount2);
Entry* entry2 = new Entry();
auto* entry2 = new Entry();
entry2->setGroup(group2);
QCOMPARE(spyModified.count(), ++spyCount);
QCOMPARE(spyModified2.count(), spyCount2);
@@ -87,11 +87,11 @@ void TestModified::testSignals()
QCOMPARE(spyModified.count(), spyCount);
QCOMPARE(spyModified2.count(), ++spyCount2);
Group* group3 = new Group();
auto* group3 = new Group();
group3->setParent(root);
QCOMPARE(spyModified.count(), ++spyCount);
Group* group4 = new Group();
auto* group4 = new Group();
group4->setParent(group3);
QCOMPARE(spyModified.count(), ++spyCount);
@@ -103,21 +103,18 @@ void TestModified::testSignals()
QCOMPARE(spyModified.count(), spyCount);
QCOMPARE(spyModified2.count(), spyCount2);
delete db;
delete db2;
}
void TestModified::testGroupSets()
{
int spyCount = 0;
Database* db = new Database();
Group* root = db->rootGroup();
QScopedPointer<Database> db(new Database());
auto* root = db->rootGroup();
Group* group = new Group();
auto* group = new Group();
group->setParent(root);
QSignalSpy spyModified(db, SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
root->setUuid(Uuid::random());
QCOMPARE(spyModified.count(), ++spyCount);
@@ -169,22 +166,20 @@ void TestModified::testGroupSets()
QCOMPARE(spyModified.count(), ++spyCount);
group->setIcon(group->iconUuid());
QCOMPARE(spyModified.count(), spyCount);
delete db;
}
void TestModified::testEntrySets()
{
int spyCount = 0;
Database* db = new Database();
Group* root = db->rootGroup();
QScopedPointer<Database> db(new Database());
auto* root = db->rootGroup();
Group* group = new Group();
auto* group = new Group();
group->setParent(root);
Entry* entry = new Entry();
auto* entry = new Entry();
entry->setGroup(group);
QSignalSpy spyModified(db, SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
entry->setUuid(Uuid::random());
QCOMPARE(spyModified.count(), ++spyCount);
@@ -284,8 +279,6 @@ void TestModified::testEntrySets()
QCOMPARE(spyModified.count(), ++spyCount);
entry->attributes()->set("test key2", entry->attributes()->value("test key2"), true);
QCOMPARE(spyModified.count(), spyCount);
delete db;
}
void TestModified::testHistoryItems()
@@ -313,7 +306,7 @@ void TestModified::testHistoryItems()
entry->setTitle("b");
entry->endUpdate();
QCOMPARE(entry->historyItems().size(), ++historyItemsSize);
Entry *historyEntry = entry->historyItems().at(historyItemsSize - 1);
auto *historyEntry = entry->historyItems().at(historyItemsSize - 1);
QCOMPARE(historyEntry->title(), QString("a"));
QCOMPARE(historyEntry->uuid(), entry->uuid());
QCOMPARE(historyEntry->tags(), entry->tags());
@@ -342,12 +335,11 @@ void TestModified::testHistoryItems()
QVERIFY(!entry->historyItems().at(historyItemsSize - 1)->attributes()->keys().contains("k"));
QScopedPointer<Database> db(new Database());
Group* root = db->rootGroup();
auto* root = db->rootGroup();
db->metadata()->setHistoryMaxItems(3);
db->metadata()->setHistoryMaxSize(-1);
Entry* historyEntry2;
Entry* entry2 = new Entry();
auto* entry2 = new Entry();
entry2->setGroup(root);
entry2->beginUpdate();
entry2->setTitle("1");
@@ -373,7 +365,7 @@ void TestModified::testHistoryItems()
entry2->endUpdate();
QCOMPARE(entry2->historyItems().size(), 1);
historyEntry2 = entry2->historyItems().at(0);
auto* historyEntry2 = entry2->historyItems().at(0);
QCOMPARE(historyEntry2->title(), QString("4"));
db->metadata()->setHistoryMaxItems(-1);
@@ -451,7 +443,6 @@ void TestModified::testHistoryMaxSize()
QScopedPointer<Database> db(new Database());
const QString key("test");
auto entry1 = new Entry();
entry1->setGroup(db->rootGroup());
QCOMPARE(entry1->historyItems().size(), 0);
@@ -584,15 +575,15 @@ void TestModified::testHistoryMaxSize()
void TestModified::testCustomData()
{
int spyCount = 0;
Database* db = new Database();
Group* root = db->rootGroup();
QScopedPointer<Database> db(new Database());
auto* root = db->rootGroup();
Group* group = new Group();
auto* group = new Group();
group->setParent(root);
Entry* entry = new Entry();
auto* entry = new Entry();
entry->setGroup(group);
QSignalSpy spyModified(db, SIGNAL(modifiedImmediate()));
QSignalSpy spyModified(db.data(), SIGNAL(modifiedImmediate()));
db->metadata()->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), ++spyCount);
@@ -608,6 +599,4 @@ void TestModified::testCustomData()
QCOMPARE(spyModified.count(), ++spyCount);
group->customData()->set("Key", "Value");
QCOMPARE(spyModified.count(), spyCount);
delete db;
}

View File

@@ -39,16 +39,6 @@
<Binary ID="0" Compressed="True">H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/InZ29+7t3//0wcHD/wfGx4SmCgAAAA==</Binary>
<Binary ID="1" Compressed="True">H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/IrLJdJafX8yLn377/wCfD1fOCwAAAA==</Binary>
</Binaries>
<CustomData>
<Item>
<Key>A Sample Test Key</Key>
<Value>valu</Value>
</Item>
<Item>
<Key>custom key</Key>
<Value>blub</Value>
</Item>
</CustomData>
</Meta>
<Root>
<Group>
@@ -479,4 +469,4 @@
</DeletedObject>
</DeletedObjects>
</Root>
</KeePassFile>
</KeePassFile>