2011-07-06 18:15:52 -04:00
|
|
|
/*
|
|
|
|
* 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"
|
|
|
|
|
2013-10-03 09:18:16 -04:00
|
|
|
#include <QBuffer>
|
2016-07-31 08:22:00 -04:00
|
|
|
#include <QFile>
|
2013-10-03 09:18:16 -04:00
|
|
|
#include <QTest>
|
2011-07-06 18:15:52 -04:00
|
|
|
|
2016-01-28 17:07:04 -05:00
|
|
|
#include "config-keepassx-tests.h"
|
2015-07-20 15:32:07 -04:00
|
|
|
#include "FailDevice.h"
|
2011-07-06 18:15:52 -04:00
|
|
|
#include "core/Database.h"
|
2011-07-08 07:57:02 -04:00
|
|
|
#include "core/Group.h"
|
2011-07-06 18:15:52 -04:00
|
|
|
#include "core/Metadata.h"
|
|
|
|
#include "crypto/Crypto.h"
|
|
|
|
#include "format/KeePass2Reader.h"
|
2016-01-28 17:07:04 -05:00
|
|
|
#include "format/KeePass2Repair.h"
|
2011-07-06 18:15:52 -04:00
|
|
|
#include "format/KeePass2Writer.h"
|
2015-07-20 15:32:07 -04:00
|
|
|
#include "format/KeePass2XmlWriter.h"
|
2011-07-06 18:15:52 -04:00
|
|
|
#include "keys/PasswordKey.h"
|
|
|
|
|
2014-05-16 06:32:52 -04:00
|
|
|
QTEST_GUILESS_MAIN(TestKeePass2Writer)
|
|
|
|
|
2011-07-06 18:15:52 -04:00
|
|
|
void TestKeePass2Writer::initTestCase()
|
|
|
|
{
|
2014-06-15 05:17:40 -04:00
|
|
|
QVERIFY(Crypto::init());
|
2011-07-06 18:15:52 -04:00
|
|
|
|
|
|
|
CompositeKey key;
|
|
|
|
key.addKey(PasswordKey("test"));
|
|
|
|
|
|
|
|
m_dbOrg = new Database();
|
|
|
|
m_dbOrg->setKey(key);
|
|
|
|
m_dbOrg->metadata()->setName("TESTDB");
|
2011-07-09 15:54:01 -04:00
|
|
|
Group* group = m_dbOrg->rootGroup();
|
2011-07-06 18:15:52 -04:00
|
|
|
group->setUuid(Uuid::random());
|
2012-04-11 11:54:27 -04:00
|
|
|
group->setNotes("I'm a note!");
|
2011-07-06 18:15:52 -04:00
|
|
|
Entry* entry = new Entry();
|
2012-06-24 12:22:18 -04:00
|
|
|
entry->setPassword(QString::fromUtf8("\xc3\xa4\xa3\xb6\xc3\xbc\xe9\x9b\xbb\xe7\xb4\x85"));
|
2011-07-06 18:15:52 -04:00
|
|
|
entry->setUuid(Uuid::random());
|
2012-04-14 09:38:20 -04:00
|
|
|
entry->attributes()->set("test", "protectedTest", true);
|
|
|
|
QVERIFY(entry->attributes()->isProtected("test"));
|
2012-04-21 10:45:46 -04:00
|
|
|
entry->attachments()->set("myattach.txt", QByteArray("this is an attachment"));
|
|
|
|
entry->attachments()->set("aaa.txt", QByteArray("also an attachment"));
|
2011-07-08 07:57:02 -04:00
|
|
|
entry->setGroup(group);
|
2011-12-27 09:47:06 -05:00
|
|
|
Group* groupNew = new Group();
|
|
|
|
groupNew->setUuid(Uuid::random());
|
|
|
|
groupNew->setName("TESTGROUP");
|
2012-04-11 11:54:27 -04:00
|
|
|
groupNew->setNotes("I'm a sub group note!");
|
2011-12-27 09:47:06 -05:00
|
|
|
groupNew->setParent(group);
|
2011-07-06 18:15:52 -04:00
|
|
|
|
|
|
|
QBuffer buffer;
|
|
|
|
buffer.open(QBuffer::ReadWrite);
|
|
|
|
|
|
|
|
KeePass2Writer writer;
|
|
|
|
writer.writeDatabase(&buffer, m_dbOrg);
|
2013-06-30 08:43:02 -04:00
|
|
|
QVERIFY(!writer.hasError());
|
2011-07-06 18:15:52 -04:00
|
|
|
buffer.seek(0);
|
|
|
|
KeePass2Reader reader;
|
|
|
|
m_dbTest = reader.readDatabase(&buffer, key);
|
2012-01-06 14:03:13 -05:00
|
|
|
QVERIFY(!reader.hasError());
|
2011-07-06 18:15:52 -04:00
|
|
|
QVERIFY(m_dbTest);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestKeePass2Writer::testBasic()
|
|
|
|
{
|
|
|
|
QCOMPARE(m_dbTest->metadata()->name(), m_dbOrg->metadata()->name());
|
|
|
|
QVERIFY(m_dbTest->rootGroup());
|
2011-12-27 09:47:06 -05:00
|
|
|
QCOMPARE(m_dbTest->rootGroup()->children()[0]->name(), m_dbOrg->rootGroup()->children()[0]->name());
|
2012-04-11 11:54:27 -04:00
|
|
|
QCOMPARE(m_dbTest->rootGroup()->notes(), m_dbOrg->rootGroup()->notes());
|
|
|
|
QCOMPARE(m_dbTest->rootGroup()->children()[0]->notes(), m_dbOrg->rootGroup()->children()[0]->notes());
|
2011-07-06 18:15:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestKeePass2Writer::testProtectedAttributes()
|
|
|
|
{
|
|
|
|
QCOMPARE(m_dbTest->rootGroup()->entries().size(), 1);
|
|
|
|
Entry* entry = m_dbTest->rootGroup()->entries().at(0);
|
2012-04-14 09:38:20 -04:00
|
|
|
QCOMPARE(entry->attributes()->value("test"), QString("protectedTest"));
|
|
|
|
QCOMPARE(entry->attributes()->isProtected("test"), true);
|
2011-07-06 18:15:52 -04:00
|
|
|
}
|
|
|
|
|
2012-04-21 10:45:46 -04:00
|
|
|
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"));
|
|
|
|
}
|
|
|
|
|
2012-06-24 12:22:18 -04:00
|
|
|
void TestKeePass2Writer::testNonAsciiPasswords()
|
|
|
|
{
|
|
|
|
QCOMPARE(m_dbTest->rootGroup()->entries()[0]->password(), m_dbOrg->rootGroup()->entries()[0]->password());
|
|
|
|
}
|
|
|
|
|
2015-07-20 15:32:07 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-01-28 17:07:04 -05:00
|
|
|
void TestKeePass2Writer::testRepair()
|
|
|
|
{
|
|
|
|
QString brokenDbFilename = QString(KEEPASSX_TEST_DATA_DIR).append("/bug392.kdbx");
|
|
|
|
// master password = test
|
2016-02-01 18:41:16 -05:00
|
|
|
// entry username: testuser\x10\x20AC
|
2016-01-28 17:07:04 -05:00
|
|
|
// 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);
|
|
|
|
QCOMPARE(repair.repairDatabase(&file, key), KeePass2Repair::RepairSuccess);
|
|
|
|
Database* dbRepaired = repair.database();
|
|
|
|
QVERIFY(dbRepaired);
|
|
|
|
|
|
|
|
QCOMPARE(dbRepaired->rootGroup()->entries().size(), 1);
|
2016-02-01 18:57:28 -05:00
|
|
|
QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->username(), QString("testuser").append(QChar(0x20AC)));
|
2016-01-28 17:07:04 -05:00
|
|
|
QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->password(), QString("testpw"));
|
|
|
|
}
|
|
|
|
|
2012-04-22 17:09:52 -04:00
|
|
|
void TestKeePass2Writer::cleanupTestCase()
|
|
|
|
{
|
|
|
|
delete m_dbOrg;
|
|
|
|
delete m_dbTest;
|
|
|
|
}
|