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
path: root/tests
diff options
context:
space:
mode:
authorlouib <L0U13@protonmail.com>2019-09-21 19:31:44 +0300
committerJonathan White <support@dmapps.us>2019-09-23 01:11:40 +0300
commit964478e78f94b00f79983f97480eb0183dae413f (patch)
treeb6a36544cf490627bb12f9a5a2c268b823bb2704 /tests
parent77fcde875e78fa44fc664b92e77db14f41b92c0b (diff)
CLI: Add Yubikey unlock support
Diffstat (limited to 'tests')
-rw-r--r--tests/TestCli.cpp114
-rw-r--r--tests/TestCli.h3
-rw-r--r--tests/TestYkChallengeResponseKey.cpp2
-rw-r--r--tests/data/YubiKeyProtectedPasswords.kdbxbin0 -> 1653 bytes
4 files changed, 97 insertions, 22 deletions
diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp
index d1ae3992d..d0fe75702 100644
--- a/tests/TestCli.cpp
+++ b/tests/TestCli.cpp
@@ -89,6 +89,11 @@ void TestCli::initTestCase()
QVERIFY(sourceDbFile4.open(QIODevice::ReadOnly));
QVERIFY(Tools::readAllFromDevice(&sourceDbFile4, m_keyFileProtectedNoPasswordDbData));
sourceDbFile4.close();
+
+ QFile sourceDbFileYubiKeyProtected(QString(KEEPASSX_TEST_DATA_DIR).append("/YubiKeyProtectedPasswords.kdbx"));
+ QVERIFY(sourceDbFileYubiKeyProtected.open(QIODevice::ReadOnly));
+ QVERIFY(Tools::readAllFromDevice(&sourceDbFileYubiKeyProtected, m_yubiKeyProtectedDbData));
+ sourceDbFileYubiKeyProtected.close();
}
void TestCli::init()
@@ -113,6 +118,11 @@ void TestCli::init()
m_keyFileProtectedNoPasswordDbFile->write(m_keyFileProtectedNoPasswordDbData);
m_keyFileProtectedNoPasswordDbFile->close();
+ m_yubiKeyProtectedDbFile.reset(new TemporaryFile());
+ m_yubiKeyProtectedDbFile->open();
+ m_yubiKeyProtectedDbFile->write(m_yubiKeyProtectedDbData);
+ m_yubiKeyProtectedDbFile->close();
+
m_stdinFile.reset(new TemporaryFile());
m_stdinFile->open();
m_stdinHandle = fdopen(m_stdinFile->handle(), "r+");
@@ -155,7 +165,7 @@ void TestCli::cleanupTestCase()
QSharedPointer<Database> TestCli::readTestDatabase() const
{
Utils::Test::setNextPassword("a");
- auto db = QSharedPointer<Database>(Utils::unlockDatabase(m_dbFile->fileName(), true, "", m_stdoutHandle));
+ auto db = QSharedPointer<Database>(Utils::unlockDatabase(m_dbFile->fileName(), true, "", "", m_stdoutHandle));
m_stdoutFile->seek(ftell(m_stdoutHandle)); // re-synchronize handles
return db;
}
@@ -226,14 +236,8 @@ void TestCli::testAdd()
Utils::Test::setNextPassword("a");
Utils::Test::setNextPassword("newpassword");
- addCmd.execute({"add",
- "-u",
- "newuser2",
- "--url",
- "https://example.net/",
- "-p",
- m_dbFile->fileName(),
- "/newuser-entry2"});
+ addCmd.execute(
+ {"add", "-u", "newuser2", "--url", "https://example.net/", "-p", m_dbFile->fileName(), "/newuser-entry2"});
db = readTestDatabase();
entry = db->rootGroup()->findEntryByPath("/newuser-entry2");
@@ -246,14 +250,7 @@ void TestCli::testAdd()
pos = m_stdoutFile->pos();
posErr = m_stderrFile->pos();
Utils::Test::setNextPassword("a");
- addCmd.execute({"add",
- "-u",
- "newuser3",
- "-g",
- "-L",
- "34",
- m_dbFile->fileName(),
- "/newuser-entry3"});
+ addCmd.execute({"add", "-u", "newuser3", "-g", "-L", "34", m_dbFile->fileName(), "/newuser-entry3"});
m_stdoutFile->seek(pos);
m_stderrFile->seek(posErr);
m_stdoutFile->readLine(); // skip password prompt
@@ -433,7 +430,7 @@ void TestCli::testCreate()
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
Utils::Test::setNextPassword("a");
- auto db = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename, true, "", Utils::DEVNULL));
+ auto db = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename, true, "", "", Utils::DEVNULL));
QVERIFY(db);
// Should refuse to create the database if it already exists.
@@ -462,7 +459,8 @@ void TestCli::testCreate()
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
Utils::Test::setNextPassword("a");
- auto db2 = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename2, true, keyfilePath, Utils::DEVNULL));
+ auto db2 =
+ QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename2, true, keyfilePath, "", Utils::DEVNULL));
QVERIFY(db2);
// Testing with existing keyfile
@@ -479,7 +477,8 @@ void TestCli::testCreate()
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
Utils::Test::setNextPassword("a");
- auto db3 = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename3, true, keyfilePath, Utils::DEVNULL));
+ auto db3 =
+ QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename3, true, keyfilePath, "", Utils::DEVNULL));
QVERIFY(db3);
}
@@ -1471,5 +1470,78 @@ void TestCli::testInvalidDbFiles()
m_stderrFile->seek(pos);
QCOMPARE(QString(m_stderrFile->readAll()),
QObject::tr("Failed to open database file %1: not readable").arg(path) + "\n");
-#endif // Q_OS_WIN
+#endif // Q_OS_WIN
+}
+
+/**
+ * Secret key for the YubiKey slot used by the unit test is
+ * 1c e3 0f d7 8d 20 dc fa 40 b5 0c 18 77 9a fb 0f 02 28 8d b7
+ * This secret should be configured at slot 2, and the slot
+ * should be configured as passive.
+ */
+void TestCli::testYubiKeyOption()
+{
+ if (!YubiKey::instance()->init()) {
+ QSKIP("Unable to connect to YubiKey");
+ }
+
+ QString errorMessage;
+ bool isBlocking = YubiKey::instance()->checkSlotIsBlocking(2, errorMessage);
+ if (isBlocking && errorMessage.isEmpty()) {
+ QSKIP("Skipping YubiKey in press mode.");
+ }
+
+ QByteArray challenge("CLITest");
+ QByteArray response;
+ YubiKey::instance()->challenge(2, false, challenge, response);
+ QByteArray expected("\xA2\x3B\x94\x00\xBE\x47\x9A\x30\xA9\xEB\x50\x9B\x85\x56\x5B\x6B\x30\x25\xB4\x8E", 20);
+ QVERIFY2(response == expected, "YubiKey Slot 2 is not configured with correct secret key.");
+
+ List listCmd;
+ Add addCmd;
+
+ Utils::Test::setNextPassword("a");
+ listCmd.execute({"ls", "-y", "2", m_yubiKeyProtectedDbFile->fileName()});
+ m_stdoutFile->reset();
+ m_stderrFile->reset();
+ m_stdoutFile->readLine(); // skip password prompt
+ QCOMPARE(m_stdoutFile->readAll(),
+ QByteArray("entry1\n"
+ "entry2\n"));
+
+ // Should raise an error with no yubikey slot.
+ qint64 pos = m_stdoutFile->pos();
+ qint64 posErr = m_stderrFile->pos();
+ Utils::Test::setNextPassword("a");
+ listCmd.execute({"ls", m_yubiKeyProtectedDbFile->fileName()});
+ m_stdoutFile->seek(pos);
+ m_stdoutFile->readLine(); // skip password prompt
+ m_stderrFile->seek(posErr);
+ QCOMPARE(m_stdoutFile->readAll(), QByteArray(""));
+ QCOMPARE(m_stderrFile->readLine(),
+ QByteArray("Error while reading the database: Invalid credentials were provided, please try again.\n"));
+ QCOMPARE(m_stderrFile->readLine(),
+ QByteArray("If this reoccurs, then your database file may be corrupt. (HMAC mismatch)\n"));
+
+ // Should raise an error if yubikey slot is not a string
+ pos = m_stdoutFile->pos();
+ posErr = m_stderrFile->pos();
+ Utils::Test::setNextPassword("a");
+ listCmd.execute({"ls", "-y", "invalidslot", m_yubiKeyProtectedDbFile->fileName()});
+ m_stdoutFile->seek(pos);
+ m_stdoutFile->readLine(); // skip password prompt
+ m_stderrFile->seek(posErr);
+ QCOMPARE(m_stdoutFile->readAll(), QByteArray(""));
+ QCOMPARE(m_stderrFile->readAll().split(':').at(0), QByteArray("Invalid YubiKey slot invalidslot\n"));
+
+ // Should raise an error if yubikey slot is invalid.
+ pos = m_stdoutFile->pos();
+ posErr = m_stderrFile->pos();
+ Utils::Test::setNextPassword("a");
+ listCmd.execute({"ls", "-y", "3", m_yubiKeyProtectedDbFile->fileName()});
+ m_stdoutFile->seek(pos);
+ m_stdoutFile->readLine(); // skip password prompt
+ m_stderrFile->seek(posErr);
+ QCOMPARE(m_stdoutFile->readAll(), QByteArray(""));
+ QCOMPARE(m_stderrFile->readAll().split(':').at(0), QByteArray("Invalid YubiKey slot 3\n"));
}
diff --git a/tests/TestCli.h b/tests/TestCli.h
index 09c55e0ed..c2d72effa 100644
--- a/tests/TestCli.h
+++ b/tests/TestCli.h
@@ -64,16 +64,19 @@ private slots:
void testRemoveQuiet();
void testShow();
void testInvalidDbFiles();
+ void testYubiKeyOption();
private:
QByteArray m_dbData;
QByteArray m_dbData2;
+ QByteArray m_yubiKeyProtectedDbData;
QByteArray m_keyFileProtectedDbData;
QByteArray m_keyFileProtectedNoPasswordDbData;
QScopedPointer<TemporaryFile> m_dbFile;
QScopedPointer<TemporaryFile> m_dbFile2;
QScopedPointer<TemporaryFile> m_keyFileProtectedDbFile;
QScopedPointer<TemporaryFile> m_keyFileProtectedNoPasswordDbFile;
+ QScopedPointer<TemporaryFile> m_yubiKeyProtectedDbFile;
QScopedPointer<TemporaryFile> m_stdoutFile;
QScopedPointer<TemporaryFile> m_stderrFile;
QScopedPointer<TemporaryFile> m_stdinFile;
diff --git a/tests/TestYkChallengeResponseKey.cpp b/tests/TestYkChallengeResponseKey.cpp
index 126d00315..0d6f9b5c3 100644
--- a/tests/TestYkChallengeResponseKey.cpp
+++ b/tests/TestYkChallengeResponseKey.cpp
@@ -74,7 +74,7 @@ void TestYubiKeyChalResp::keyIssueChallenge()
/* TODO Determine if it's reasonable to provide a fixed secret key for
* verification testing. Obviously simple technically, but annoying
* if devs need to re-program their yubikeys or have a spare test key
- * for unit tests to past.
+ * for unit tests to pass.
*
* Might be worth it for integrity verification though.
*/
diff --git a/tests/data/YubiKeyProtectedPasswords.kdbx b/tests/data/YubiKeyProtectedPasswords.kdbx
new file mode 100644
index 000000000..c6c6d1324
--- /dev/null
+++ b/tests/data/YubiKeyProtectedPasswords.kdbx
Binary files differ