2016-02-28 01:07:58 +01:00
|
|
|
#include "../io/cryptoexception.h"
|
|
|
|
#include "../io/entry.h"
|
2017-05-31 00:41:44 +02:00
|
|
|
#include "../io/passwordfile.h"
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
#include <c++utilities/tests/testutils.h>
|
|
|
|
|
|
|
|
#include <cppunit/TestFixture.h>
|
2017-05-31 00:41:44 +02:00
|
|
|
#include <cppunit/extensions/HelperMacros.h>
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Io;
|
2017-05-31 00:41:44 +02:00
|
|
|
using namespace TestUtilities::Literals;
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
using namespace CPPUNIT_NS;
|
|
|
|
|
2016-06-10 23:18:21 +02:00
|
|
|
/*!
|
|
|
|
* \brief The PasswordFileTests class tests the Io::PasswordFile class.
|
|
|
|
*/
|
2017-05-31 00:41:44 +02:00
|
|
|
class PasswordFileTests : public TestFixture {
|
2016-02-28 01:07:58 +01:00
|
|
|
CPPUNIT_TEST_SUITE(PasswordFileTests);
|
|
|
|
CPPUNIT_TEST(testReading);
|
2018-12-18 23:17:19 +01:00
|
|
|
CPPUNIT_TEST(testBasicWriting);
|
|
|
|
CPPUNIT_TEST(testExtendedWriting);
|
2016-02-28 01:07:58 +01:00
|
|
|
CPPUNIT_TEST_SUITE_END();
|
|
|
|
|
|
|
|
public:
|
2018-12-21 17:31:50 +01:00
|
|
|
void setUp() override;
|
|
|
|
void tearDown() override;
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
void testReading();
|
2018-12-18 23:17:19 +01:00
|
|
|
void testReading(const string &context, const string &testfile1path, const string &testfile1password, const string &testfile2,
|
|
|
|
const string &testfile2password, bool testfile2Mod, bool extendedHeaderMod);
|
|
|
|
void testBasicWriting();
|
|
|
|
void testExtendedWriting();
|
2016-02-28 01:07:58 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(PasswordFileTests);
|
|
|
|
|
|
|
|
void PasswordFileTests::setUp()
|
2017-05-31 00:41:44 +02:00
|
|
|
{
|
|
|
|
}
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
void PasswordFileTests::tearDown()
|
2017-05-31 00:41:44 +02:00
|
|
|
{
|
|
|
|
}
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Tests reading the testfiles testfile{1,2}.pwmgr.
|
|
|
|
*/
|
|
|
|
void PasswordFileTests::testReading()
|
|
|
|
{
|
2018-12-18 23:17:19 +01:00
|
|
|
testReading(
|
|
|
|
"read", TestUtilities::testFilePath("testfile1.pwmgr"), "123456", TestUtilities::testFilePath("testfile2.pwmgr"), string(), false, false);
|
2016-02-28 01:07:58 +01:00
|
|
|
}
|
|
|
|
|
2018-12-18 23:17:19 +01:00
|
|
|
void PasswordFileTests::testReading(const string &context, const string &testfile1path, const string &testfile1password, const string &testfile2,
|
|
|
|
const string &testfile2password, bool testfile2Mod, bool extendedHeaderMod)
|
2016-02-28 01:07:58 +01:00
|
|
|
{
|
|
|
|
PasswordFile file;
|
|
|
|
|
|
|
|
// open testfile 1 ...
|
|
|
|
file.setPath(testfile1path);
|
2018-12-18 23:17:19 +01:00
|
|
|
file.open(PasswordFileOpenFlags::ReadOnly);
|
2016-02-28 01:07:58 +01:00
|
|
|
|
2018-12-18 23:17:19 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(context, !testfile1password.empty(), file.isEncryptionUsed());
|
2016-02-28 01:07:58 +01:00
|
|
|
// attempt to decrypt using a wrong password
|
|
|
|
file.setPassword(testfile1password + "asdf");
|
2017-05-31 00:41:44 +02:00
|
|
|
if (!testfile1password.empty()) {
|
2016-02-28 01:07:58 +01:00
|
|
|
CPPUNIT_ASSERT_THROW(file.load(), CryptoException);
|
|
|
|
}
|
|
|
|
// attempt to decrypt using the correct password
|
|
|
|
file.setPassword(testfile1password);
|
|
|
|
file.load();
|
|
|
|
// test root entry
|
2018-06-09 18:35:26 +02:00
|
|
|
const NodeEntry *const rootEntry = file.rootEntry();
|
2017-02-06 18:38:02 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL("testfile1"s, rootEntry->label());
|
2017-05-31 00:41:44 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(4_st, rootEntry->children().size());
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
// test testaccount1
|
2017-02-06 18:38:02 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL("testaccount1"s, rootEntry->children()[0]->label());
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(EntryType::Account, rootEntry->children()[0]->type());
|
2017-02-06 18:38:02 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL("pin"s, static_cast<AccountEntry *>(rootEntry->children()[0])->fields().at(0).name());
|
|
|
|
CPPUNIT_ASSERT_EQUAL("123456"s, static_cast<AccountEntry *>(rootEntry->children()[0])->fields().at(0).value());
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(FieldType::Password, static_cast<AccountEntry *>(rootEntry->children()[0])->fields().at(0).type());
|
2017-05-31 00:41:44 +02:00
|
|
|
CPPUNIT_ASSERT(
|
|
|
|
static_cast<AccountEntry *>(rootEntry->children()[0])->fields().at(0).tiedAccount() == static_cast<AccountEntry *>(rootEntry->children()[0]));
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(FieldType::Normal, static_cast<AccountEntry *>(rootEntry->children()[0])->fields().at(1).type());
|
2016-02-28 01:07:58 +01:00
|
|
|
CPPUNIT_ASSERT_THROW(static_cast<AccountEntry *>(rootEntry->children()[0])->fields().at(2), out_of_range);
|
|
|
|
|
|
|
|
// test testaccount2
|
2017-02-06 18:38:02 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL("testaccount2"s, rootEntry->children()[1]->label());
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(EntryType::Account, rootEntry->children()[1]->type());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(0_st, static_cast<AccountEntry *>(rootEntry->children()[1])->fields().size());
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
// test testcategory1
|
2017-02-06 18:38:02 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL("testcategory1"s, rootEntry->children()[2]->label());
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(EntryType::Node, rootEntry->children()[2]->type());
|
|
|
|
const NodeEntry *const category = static_cast<NodeEntry *>(rootEntry->children()[2]);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(3_st, category->children().size());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(EntryType::Node, category->children()[2]->type());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(2_st, static_cast<NodeEntry *>(category->children()[2])->children().size());
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
// test testaccount3
|
2017-02-06 18:38:02 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL("testaccount3"s, rootEntry->children()[3]->label());
|
2016-02-28 01:07:58 +01:00
|
|
|
|
2018-12-18 23:17:19 +01:00
|
|
|
if (extendedHeaderMod) {
|
|
|
|
CPPUNIT_ASSERT_EQUAL("foo"s, file.extendedHeader());
|
|
|
|
} else {
|
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.extendedHeader());
|
|
|
|
}
|
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.encryptedExtendedHeader());
|
|
|
|
|
2016-02-28 01:07:58 +01:00
|
|
|
// open testfile 2
|
|
|
|
file.setPath(testfile2);
|
2018-12-18 23:17:19 +01:00
|
|
|
file.open(PasswordFileOpenFlags::ReadOnly);
|
2016-02-28 01:07:58 +01:00
|
|
|
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL(!testfile2password.empty(), file.isEncryptionUsed());
|
2016-02-28 01:07:58 +01:00
|
|
|
file.setPassword(testfile2password);
|
|
|
|
file.load();
|
2018-06-09 18:35:26 +02:00
|
|
|
const NodeEntry *const rootEntry2 = file.rootEntry();
|
2017-05-31 00:41:44 +02:00
|
|
|
if (testfile2Mod) {
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL("testfile2 - modified"s, rootEntry2->label());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(2_st, rootEntry2->children().size());
|
|
|
|
CPPUNIT_ASSERT_EQUAL("newAccount"s, rootEntry2->children()[1]->label());
|
2016-02-28 01:07:58 +01:00
|
|
|
} else {
|
2018-06-09 18:35:26 +02:00
|
|
|
CPPUNIT_ASSERT_EQUAL("testfile2"s, rootEntry2->label());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1_st, rootEntry2->children().size());
|
2016-02-28 01:07:58 +01:00
|
|
|
}
|
2018-12-18 23:17:19 +01:00
|
|
|
if (extendedHeaderMod) {
|
|
|
|
CPPUNIT_ASSERT_EQUAL("foo"s, file.extendedHeader());
|
|
|
|
CPPUNIT_ASSERT_EQUAL("bar"s, file.encryptedExtendedHeader());
|
|
|
|
} else {
|
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.extendedHeader());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.encryptedExtendedHeader());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Tests writing (and reading again) using basic features.
|
|
|
|
*/
|
|
|
|
void PasswordFileTests::testBasicWriting()
|
|
|
|
{
|
|
|
|
const string testfile1 = TestUtilities::workingCopyPath("testfile1.pwmgr");
|
|
|
|
const string testfile2 = TestUtilities::workingCopyPath("testfile2.pwmgr");
|
|
|
|
PasswordFile file;
|
|
|
|
|
|
|
|
// resave testfile 1
|
|
|
|
file.setPath(testfile1);
|
|
|
|
file.open();
|
|
|
|
file.setPassword("123456");
|
|
|
|
file.load();
|
|
|
|
file.doBackup();
|
|
|
|
file.save(PasswordFileSaveFlags::Compression);
|
|
|
|
|
|
|
|
// resave testfile 2
|
|
|
|
file.setPath(testfile2);
|
|
|
|
file.open();
|
|
|
|
file.load();
|
|
|
|
file.rootEntry()->setLabel("testfile2 - modified");
|
|
|
|
new AccountEntry("newAccount", file.rootEntry());
|
|
|
|
file.setPassword("654321");
|
|
|
|
file.doBackup();
|
|
|
|
file.save(PasswordFileSaveFlags::Encryption);
|
|
|
|
|
|
|
|
// check results using the reading test
|
|
|
|
testReading("basic writing", testfile1, string(), testfile2, "654321", true, false);
|
|
|
|
|
|
|
|
// check backup files
|
|
|
|
testReading("basic writing", testfile1 + ".backup", "123456", testfile2 + ".backup", string(), false, false);
|
2016-02-28 01:07:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2018-12-18 23:17:19 +01:00
|
|
|
* \brief Tests writing (and reading again) using extended features.
|
2016-02-28 01:07:58 +01:00
|
|
|
*/
|
2018-12-18 23:17:19 +01:00
|
|
|
void PasswordFileTests::testExtendedWriting()
|
2016-02-28 01:07:58 +01:00
|
|
|
{
|
2018-06-09 18:35:26 +02:00
|
|
|
const string testfile1 = TestUtilities::workingCopyPath("testfile1.pwmgr");
|
|
|
|
const string testfile2 = TestUtilities::workingCopyPath("testfile2.pwmgr");
|
2016-02-28 01:07:58 +01:00
|
|
|
PasswordFile file;
|
|
|
|
|
|
|
|
// resave testfile 1
|
|
|
|
file.setPath(testfile1);
|
2018-12-18 23:17:19 +01:00
|
|
|
file.open();
|
2016-02-28 01:07:58 +01:00
|
|
|
file.setPassword("123456");
|
|
|
|
file.load();
|
2018-12-18 23:17:19 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.extendedHeader());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.encryptedExtendedHeader());
|
2016-02-28 01:07:58 +01:00
|
|
|
file.doBackup();
|
2018-12-18 23:17:19 +01:00
|
|
|
file.extendedHeader() = "foo";
|
|
|
|
file.save(PasswordFileSaveFlags::Encryption | PasswordFileSaveFlags::PasswordHashing);
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
// resave testfile 2
|
|
|
|
file.setPath(testfile2);
|
2018-12-18 23:17:19 +01:00
|
|
|
file.open();
|
2016-02-28 01:07:58 +01:00
|
|
|
file.load();
|
2018-12-18 23:17:19 +01:00
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.extendedHeader());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(""s, file.encryptedExtendedHeader());
|
2016-02-28 01:07:58 +01:00
|
|
|
file.rootEntry()->setLabel("testfile2 - modified");
|
|
|
|
new AccountEntry("newAccount", file.rootEntry());
|
|
|
|
file.setPassword("654321");
|
2018-12-18 23:17:19 +01:00
|
|
|
file.extendedHeader() = "foo";
|
|
|
|
file.encryptedExtendedHeader() = "bar";
|
2016-02-28 01:07:58 +01:00
|
|
|
file.doBackup();
|
2018-12-18 23:17:19 +01:00
|
|
|
file.save(PasswordFileSaveFlags::Encryption | PasswordFileSaveFlags::PasswordHashing);
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
// check results using the reading test
|
2018-12-18 23:17:19 +01:00
|
|
|
testReading("extended writing", testfile1, "123456", testfile2, "654321", true, true);
|
2016-02-28 01:07:58 +01:00
|
|
|
|
|
|
|
// check backup files
|
2018-12-18 23:17:19 +01:00
|
|
|
testReading("extended writing", testfile1 + ".backup", "123456", testfile2 + ".backup", string(), false, false);
|
2016-02-28 01:07:58 +01:00
|
|
|
}
|