keepassxc/tests/TestKeePass2Writer.cpp

169 lines
5.6 KiB
C++

/*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TestKeePass2Writer.h"
#include <QBuffer>
#include <QFile>
#include <QTest>
#include "config-keepassx-tests.h"
#include "FailDevice.h"
#include "core/Database.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "crypto/Crypto.h"
#include "format/KeePass2Reader.h"
#include "format/KeePass2Repair.h"
#include "format/KeePass2Writer.h"
#include "keys/PasswordKey.h"
QTEST_GUILESS_MAIN(TestKeePass2Writer)
void TestKeePass2Writer::initTestCase()
{
QVERIFY(Crypto::init());
CompositeKey key;
key.addKey(PasswordKey("test"));
m_dbOrg = new Database();
m_dbOrg->setKey(key);
m_dbOrg->metadata()->setName("TESTDB");
Group* group = m_dbOrg->rootGroup();
group->setUuid(Uuid::random());
group->setNotes("I'm a note!");
Entry* entry = new Entry();
entry->setPassword(QString::fromUtf8("\xc3\xa4\xa3\xb6\xc3\xbc\xe9\x9b\xbb\xe7\xb4\x85"));
entry->setUuid(Uuid::random());
entry->attributes()->set("test", "protectedTest", true);
QVERIFY(entry->attributes()->isProtected("test"));
entry->attachments()->set("myattach.txt", QByteArray("this is an attachment"));
entry->attachments()->set("aaa.txt", QByteArray("also an attachment"));
entry->setGroup(group);
Group* groupNew = new Group();
groupNew->setUuid(Uuid::random());
groupNew->setName("TESTGROUP");
groupNew->setNotes("I'm a sub group note!");
groupNew->setParent(group);
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
KeePass2Writer writer;
bool writeSuccess = writer.writeDatabase(&buffer, m_dbOrg);
QVERIFY(writeSuccess);
QVERIFY(!writer.hasError());
buffer.seek(0);
KeePass2Reader reader;
m_dbTest = reader.readDatabase(&buffer, key);
if (reader.hasError()) {
QFAIL(reader.errorString().toUtf8().constData());
}
QVERIFY(m_dbTest);
}
void TestKeePass2Writer::testBasic()
{
QCOMPARE(m_dbTest->metadata()->name(), m_dbOrg->metadata()->name());
QVERIFY(m_dbTest->rootGroup());
QCOMPARE(m_dbTest->rootGroup()->children()[0]->name(), m_dbOrg->rootGroup()->children()[0]->name());
QCOMPARE(m_dbTest->rootGroup()->notes(), m_dbOrg->rootGroup()->notes());
QCOMPARE(m_dbTest->rootGroup()->children()[0]->notes(), m_dbOrg->rootGroup()->children()[0]->notes());
}
void TestKeePass2Writer::testProtectedAttributes()
{
QCOMPARE(m_dbTest->rootGroup()->entries().size(), 1);
Entry* entry = m_dbTest->rootGroup()->entries().at(0);
QCOMPARE(entry->attributes()->value("test"), QString("protectedTest"));
QCOMPARE(entry->attributes()->isProtected("test"), true);
}
void TestKeePass2Writer::testAttachments()
{
Entry* entry = m_dbTest->rootGroup()->entries().at(0);
QCOMPARE(entry->attachments()->keys().size(), 2);
QCOMPARE(entry->attachments()->value("myattach.txt"), QByteArray("this is an attachment"));
QCOMPARE(entry->attachments()->value("aaa.txt"), QByteArray("also an attachment"));
}
void TestKeePass2Writer::testNonAsciiPasswords()
{
QCOMPARE(m_dbTest->rootGroup()->entries()[0]->password(), m_dbOrg->rootGroup()->entries()[0]->password());
}
void TestKeePass2Writer::testDeviceFailure()
{
CompositeKey key;
key.addKey(PasswordKey("test"));
Database* db = new Database();
db->setKey(key);
// Disable compression so we write a predictable number of bytes.
db->setCompressionAlgo(Database::CompressionNone);
Entry* entry = new Entry();
entry->setParent(db->rootGroup());
QByteArray attachment(4096, 'Z');
entry->attachments()->set("test", attachment);
FailDevice failDevice(512);
QVERIFY(failDevice.open(QIODevice::WriteOnly));
KeePass2Writer writer;
writer.writeDatabase(&failDevice, db);
QVERIFY(writer.hasError());
QCOMPARE(writer.errorString(), QString("FAILDEVICE"));
delete db;
}
void TestKeePass2Writer::testRepair()
{
QString brokenDbFilename = QString(KEEPASSX_TEST_DATA_DIR).append("/bug392.kdbx");
// master password = test
// entry username: testuser\x10\x20AC
// entry password: testpw
CompositeKey key;
key.addKey(PasswordKey("test"));
// test that we can't open the broken database
KeePass2Reader reader;
Database* dbBroken = reader.readDatabase(brokenDbFilename, key);
QVERIFY(!dbBroken);
QVERIFY(reader.hasError());
// test if we can repair the database
KeePass2Repair repair;
QFile file(brokenDbFilename);
file.open(QIODevice::ReadOnly);
auto result = repair.repairDatabase(&file, key);
QCOMPARE(result.first, KeePass2Repair::RepairSuccess);
Database* dbRepaired = result.second;
QVERIFY(dbRepaired);
QCOMPARE(dbRepaired->rootGroup()->entries().size(), 1);
QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->username(), QString("testuser").append(QChar(0x20AC)));
QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->password(), QString("testpw"));
delete dbRepaired;
}
void TestKeePass2Writer::cleanupTestCase()
{
delete m_dbOrg;
delete m_dbTest;
}