Skip to content

Commit

Permalink
Adding more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
louib committed Sep 18, 2022
1 parent 2515124 commit 3f29b55
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 73 deletions.
4 changes: 4 additions & 0 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7891,6 +7891,10 @@ Kernel: %3 %4</source>
<source>Cannot remove file key: The database does not have a file key.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Found unexpected Key type %1</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QtIOCompressor</name>
Expand Down
89 changes: 34 additions & 55 deletions src/cli/DatabaseEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,84 +106,63 @@ QSharedPointer<CompositeKey> DatabaseEdit::getNewDatabaseKey(QSharedPointer<Data
{
auto& err = Utils::STDERR;
auto newDatabaseKey = QSharedPointer<CompositeKey>::create();
bool updateKeyFile = !newFileKeyPath.isEmpty();

if (removePassword) {
if (!database->key()->hasKey(PasswordKey::UUID)) {
err << QObject::tr("Cannot remove password: The database does not have a password.") << endl;
return {};
}
auto currentPasswordKey = database->key()->getKey(PasswordKey::UUID);
auto currentFileKey = database->key()->getKey(FileKey::UUID);
auto currentChallengeResponseKey = database->key()->getKey(ChallengeResponseKey::UUID);

if (removePassword && currentPasswordKey.isNull()) {
err << QObject::tr("Cannot remove password: The database does not have a password.") << endl;
return {};
}
if (removeKeyFile) {
if (!database->key()->hasKey(FileKey::UUID)) {
err << QObject::tr("Cannot remove file key: The database does not have a file key.") << endl;
return {};
}

if (removeKeyFile && currentFileKey.isNull()) {
err << QObject::tr("Cannot remove file key: The database does not have a file key.") << endl;
return {};
}

QSharedPointer<PasswordKey> newPasswordKey;
if (updatePassword) {
newPasswordKey = Utils::getConfirmedPassword();
QSharedPointer<PasswordKey> newPasswordKey = Utils::getConfirmedPassword();
if (newPasswordKey.isNull()) {
err << QObject::tr("Failed to set database password.") << endl;
return {};
}
newDatabaseKey->addKey(newPasswordKey);
} else if (!removePassword && !currentPasswordKey.isNull()) {
newDatabaseKey->addKey(currentPasswordKey);
}

QSharedPointer<FileKey> newFileKey;
if (!newFileKeyPath.isEmpty()) {
newFileKey = QSharedPointer<FileKey>::create();
if (updateKeyFile) {
QSharedPointer<FileKey> newFileKey = QSharedPointer<FileKey>::create();
QString errorMessage;
if (!Utils::loadFileKey(newFileKeyPath, newFileKey)) {
err << QObject::tr("Loading the new key file failed: %1").arg(errorMessage) << endl;
return {};
}
newDatabaseKey->addKey(newFileKey);
} else if (!removeKeyFile && !currentFileKey.isNull()) {
newDatabaseKey->addKey(currentFileKey);
}

for (const auto& key : database->key()->keys()) {
if (key->uuid() == PasswordKey::UUID) {
if (removePassword) {
continue;
}

if (!updatePassword) {
newDatabaseKey->addKey(key);
continue;
}

newDatabaseKey->addKey(newPasswordKey);
continue;
}

if (key->uuid() == FileKey::UUID) {
if (removeKeyFile) {
continue;
}

if (newFileKeyPath.isEmpty()) {
newDatabaseKey->addKey(key);
continue;
}

newDatabaseKey->addKey(newFileKey);
continue;
// This is a sanity check to make sure that this function is not used if
// new key types are introduced. Otherwise, those key types would be
// silently removed from the database.
for (const QSharedPointer<Key>& key : database->key()->keys()) {
if (key->uuid() != PasswordKey::UUID && key->uuid() != FileKey::UUID) {
err << QObject::tr("Found unexpected Key type %1").arg(key->uuid().toString()) << endl;
return {};
}

// Not sure that we should ever get here.
newDatabaseKey->addKey(key);
}

for (const auto& key : database->key()->challengeResponseKeys()) {
if (key->uuid() == ChallengeResponseKey::UUID) {
newDatabaseKey->addKey(key);
for (const QSharedPointer<ChallengeResponseKey>& key : database->key()->challengeResponseKeys()) {
if (key->uuid() != ChallengeResponseKey::UUID) {
err << QObject::tr("Found unexpected Key type %1").arg(key->uuid().toString()) << endl;
return {};
}
}

if (!newDatabaseKey->hasKey(PasswordKey::UUID) && updatePassword) {
newDatabaseKey->addKey(newPasswordKey);
}

if (!newDatabaseKey->hasKey(FileKey::UUID) && !newFileKeyPath.isEmpty()) {
newDatabaseKey->addKey(newFileKey);
if (!currentChallengeResponseKey.isNull()) {
newDatabaseKey->addKey(currentChallengeResponseKey);
}

if (newDatabaseKey->keys().isEmpty()) {
Expand Down
20 changes: 20 additions & 0 deletions src/keys/CompositeKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,26 @@ void CompositeKey::addKey(const QSharedPointer<Key>& key)
m_keys.append(key);
}

/**
* Get the \link Key with the specified ID.
*
* @param keyId the ID of the key to get.
*/
QSharedPointer<Key> CompositeKey::getKey(const QUuid keyId) const
{
for (const QSharedPointer<Key>& key : m_keys) {
if (key->uuid() == keyId) {
return key;
}
}
for (const QSharedPointer<ChallengeResponseKey>& key : m_challengeResponseKeys) {
if (key->uuid() == keyId) {
return key;
}
}
return {};
}

/**
* Test if a \link Key with the specified ID is
* in the composite key.
Expand Down
1 change: 1 addition & 0 deletions src/keys/CompositeKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class CompositeKey : public Key

void addKey(const QSharedPointer<Key>& key);
bool hasKey(const QUuid keyType) const;
QSharedPointer<Key> getKey(const QUuid keyType) const;
const QList<QSharedPointer<Key>>& keys() const;

void addChallengeResponseKey(const QSharedPointer<ChallengeResponseKey>& key);
Expand Down
71 changes: 53 additions & 18 deletions tests/TestCli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,25 +851,24 @@ void TestCli::testCreate()

void TestCli::testDatabaseEdit()
{
TemporaryFile keyFile;
keyFile.open();
keyFile.write(QString("keyFilePassword").toLatin1());
keyFile.close();
TemporaryFile firstKeyFile;
firstKeyFile.open();
firstKeyFile.write(QString("keyFilePassword").toLatin1());
firstKeyFile.close();

TemporaryFile newKeyFile;
newKeyFile.open();
newKeyFile.write(QString("newKeyFilePassword").toLatin1());
newKeyFile.close();
TemporaryFile secondKeyFile;
secondKeyFile.open();
secondKeyFile.write(QString("newKeyFilePassword").toLatin1());
secondKeyFile.close();

QScopedPointer<QTemporaryDir> testDir(new QTemporaryDir());

DatabaseCreate createCmd;
DatabaseEdit editCmd;
QVERIFY(!createCmd.name.isEmpty());
QVERIFY(createCmd.getDescriptionLine().contains(createCmd.name));
QVERIFY(!editCmd.name.isEmpty());
QVERIFY(editCmd.getDescriptionLine().contains(editCmd.name));

QString dbFilename;

dbFilename = testDir->path() + "/testDatabaseEdit.kdbx";

// Creating a database for testing
Expand All @@ -894,6 +893,10 @@ void TestCli::testDatabaseEdit()
m_stderr->readLine();
QCOMPARE(m_stderr->readAll(), QByteArray("Cannot use set-key-file and unset-key-file at the same time.\n"));

// Sanity check.
db = readDatabase(dbFilename, "a");
QVERIFY(!db.isNull());

setInput({"a", "b", "b"});
execCmd(editCmd, {"db-edit", dbFilename, "-p"});
QCOMPARE(m_stdout->readAll(), QByteArray("Successfully edited the database.\n"));
Expand All @@ -903,7 +906,7 @@ void TestCli::testDatabaseEdit()
QVERIFY(!db.isNull());

setInput("b");
execCmd(editCmd, {"db-edit", dbFilename, "--set-key-file", keyFile.fileName()});
execCmd(editCmd, {"db-edit", dbFilename, "--set-key-file", firstKeyFile.fileName()});
// Skipping the password prompt.
m_stderr->readLine();
QCOMPARE(m_stderr->readAll(), QByteArray(""));
Expand All @@ -912,25 +915,57 @@ void TestCli::testDatabaseEdit()
// Sanity check
db = readDatabase(dbFilename, "b");
QVERIFY(db.isNull());
db = readDatabase(dbFilename, "b", keyFile.fileName());
db = readDatabase(dbFilename, "b", firstKeyFile.fileName());
QVERIFY(!db.isNull());

setInput("b");
execCmd(editCmd, {"db-edit", dbFilename, "-k", keyFile.fileName(), "--set-key-file", newKeyFile.fileName()});
execCmd(editCmd,
{"db-edit", dbFilename, "-k", firstKeyFile.fileName(), "--set-key-file", secondKeyFile.fileName()});
QCOMPARE(m_stdout->readAll(), QByteArray("Successfully edited the database.\n"));

// Sanity check
db = readDatabase(dbFilename, "b", keyFile.fileName());
db = readDatabase(dbFilename, "b", firstKeyFile.fileName());
QVERIFY(db.isNull());
db = readDatabase(dbFilename, "b", newKeyFile.fileName());
db = readDatabase(dbFilename, "b", secondKeyFile.fileName());
QVERIFY(!db.isNull());

setInput("b");
execCmd(editCmd, {"db-edit", dbFilename, "-k", newKeyFile.fileName(), "--unset-key-file"});
execCmd(editCmd, {"db-edit", dbFilename, "-k", secondKeyFile.fileName(), "--unset-password"});
// Skipping the password prompt.
m_stderr->readLine();
QCOMPARE(m_stderr->readAll(), QByteArray(""));
QCOMPARE(m_stdout->readAll(), QByteArray("Successfully edited the database.\n"));

execCmd(editCmd,
{"db-edit",
dbFilename,
"--no-password",
"-k",
secondKeyFile.fileName(),
"--set-key-file",
firstKeyFile.fileName()});
// Skipping the password prompt.
m_stderr->readLine();
QCOMPARE(m_stderr->readAll(), QByteArray(""));
QCOMPARE(m_stdout->readAll(), QByteArray("Successfully edited the database.\n"));

setInput({"b", "b"});
execCmd(editCmd, {"db-edit", dbFilename, "-k", firstKeyFile.fileName(), "--no-password", "--set-password"});
// Skipping over the password setting prompts.
m_stderr->readLine();
m_stderr->readLine();
QCOMPARE(m_stderr->readAll(), QByteArray(""));
QCOMPARE(m_stdout->readAll(), QByteArray("Successfully edited the database.\n"));

setInput("b");
execCmd(editCmd, {"db-edit", dbFilename, "-k", firstKeyFile.fileName(), "--unset-key-file"});
// Skipping the password prompt.
m_stderr->readLine();
QCOMPARE(m_stderr->readAll(), QByteArray(""));
QCOMPARE(m_stdout->readAll(), QByteArray("Successfully edited the database.\n"));

// Sanity check
db = readDatabase(dbFilename, "b", keyFile.fileName());
db = readDatabase(dbFilename, "b", firstKeyFile.fileName());
QVERIFY(db.isNull());
db = readDatabase(dbFilename, "b");
QVERIFY(!db.isNull());
Expand Down

0 comments on commit 3f29b55

Please sign in to comment.