mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Adding --no-password option to CLI
I also added tests for the --key-file option, which was untested.
This commit is contained in:
parent
a58e3d5ee0
commit
13a9ac8f57
@ -50,6 +50,7 @@ int Add::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
|
|
||||||
QCommandLineOption username(QStringList() << "u"
|
QCommandLineOption username(QStringList() << "u"
|
||||||
<< "username",
|
<< "username",
|
||||||
@ -91,6 +92,7 @@ int Add::execute(const QStringList& arguments)
|
|||||||
const QString& entryPath = args.at(1);
|
const QString& entryPath = args.at(1);
|
||||||
|
|
||||||
auto db = Utils::unlockDatabase(databasePath,
|
auto db = Utils::unlockDatabase(databasePath,
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -49,6 +49,7 @@ int Clip::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
|
|
||||||
QCommandLineOption totp(QStringList() << "t"
|
QCommandLineOption totp(QStringList() << "t"
|
||||||
<< "totp",
|
<< "totp",
|
||||||
@ -67,6 +68,7 @@ int Clip::execute(const QStringList& arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto db = Utils::unlockDatabase(args.at(0),
|
auto db = Utils::unlockDatabase(args.at(0),
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -46,6 +46,10 @@ const QCommandLineOption Command::KeyFileOption = QCommandLineOption(QStringList
|
|||||||
QObject::tr("Key file of the database."),
|
QObject::tr("Key file of the database."),
|
||||||
QObject::tr("path"));
|
QObject::tr("path"));
|
||||||
|
|
||||||
|
const QCommandLineOption Command::NoPasswordOption =
|
||||||
|
QCommandLineOption(QStringList() << "no-password",
|
||||||
|
QObject::tr("Deactivate password key for the database."));
|
||||||
|
|
||||||
QMap<QString, Command*> commands;
|
QMap<QString, Command*> commands;
|
||||||
|
|
||||||
Command::~Command()
|
Command::~Command()
|
||||||
|
@ -40,6 +40,7 @@ public:
|
|||||||
|
|
||||||
static const QCommandLineOption QuietOption;
|
static const QCommandLineOption QuietOption;
|
||||||
static const QCommandLineOption KeyFileOption;
|
static const QCommandLineOption KeyFileOption;
|
||||||
|
static const QCommandLineOption NoPasswordOption;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSXC_COMMAND_H
|
#endif // KEEPASSXC_COMMAND_H
|
||||||
|
@ -49,6 +49,7 @@ int Edit::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
|
|
||||||
QCommandLineOption username(QStringList() << "u"
|
QCommandLineOption username(QStringList() << "u"
|
||||||
<< "username",
|
<< "username",
|
||||||
@ -95,6 +96,7 @@ int Edit::execute(const QStringList& arguments)
|
|||||||
const QString& entryPath = args.at(1);
|
const QString& entryPath = args.at(1);
|
||||||
|
|
||||||
auto db = Utils::unlockDatabase(databasePath,
|
auto db = Utils::unlockDatabase(databasePath,
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -51,6 +51,7 @@ int Extract::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("database", QObject::tr("Path of the database to extract."));
|
parser.addPositionalArgument("database", QObject::tr("Path of the database to extract."));
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.process(arguments);
|
parser.process(arguments);
|
||||||
|
|
||||||
@ -59,17 +60,19 @@ int Extract::execute(const QStringList& arguments)
|
|||||||
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli extract");
|
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli extract");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parser.isSet(Command::QuietOption)) {
|
|
||||||
outputTextStream << QObject::tr("Insert password to unlock %1: ").arg(args.at(0)) << flush;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto compositeKey = QSharedPointer<CompositeKey>::create();
|
auto compositeKey = QSharedPointer<CompositeKey>::create();
|
||||||
|
|
||||||
QString line = Utils::getPassword(parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT);
|
if (!parser.isSet(Command::NoPasswordOption)) {
|
||||||
auto passwordKey = QSharedPointer<PasswordKey>::create();
|
if (!parser.isSet(Command::QuietOption)) {
|
||||||
passwordKey->setPassword(line);
|
outputTextStream << QObject::tr("Insert password to unlock %1: ").arg(args.at(0)) << flush;
|
||||||
compositeKey->addKey(passwordKey);
|
}
|
||||||
|
|
||||||
|
QString line = Utils::getPassword(parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT);
|
||||||
|
auto passwordKey = QSharedPointer<PasswordKey>::create();
|
||||||
|
passwordKey->setPassword(line);
|
||||||
|
compositeKey->addKey(passwordKey);
|
||||||
|
}
|
||||||
|
|
||||||
QString keyFilePath = parser.value(Command::KeyFileOption);
|
QString keyFilePath = parser.value(Command::KeyFileOption);
|
||||||
if (!keyFilePath.isEmpty()) {
|
if (!keyFilePath.isEmpty()) {
|
||||||
|
@ -48,6 +48,7 @@ int List::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("group", QObject::tr("Path of the group to list. Default is /"), "[group]");
|
parser.addPositionalArgument("group", QObject::tr("Path of the group to list. Default is /"), "[group]");
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
|
|
||||||
QCommandLineOption recursiveOption(QStringList() << "R"
|
QCommandLineOption recursiveOption(QStringList() << "R"
|
||||||
<< "recursive",
|
<< "recursive",
|
||||||
@ -65,6 +66,7 @@ int List::execute(const QStringList& arguments)
|
|||||||
bool recursive = parser.isSet(recursiveOption);
|
bool recursive = parser.isSet(recursiveOption);
|
||||||
|
|
||||||
auto db = Utils::unlockDatabase(args.at(0),
|
auto db = Utils::unlockDatabase(args.at(0),
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -50,6 +50,7 @@ int Locate::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("term", QObject::tr("Search term."));
|
parser.addPositionalArgument("term", QObject::tr("Search term."));
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.process(arguments);
|
parser.process(arguments);
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ int Locate::execute(const QStringList& arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto db = Utils::unlockDatabase(args.at(0),
|
auto db = Utils::unlockDatabase(args.at(0),
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -52,6 +52,7 @@ int Merge::execute(const QStringList& arguments)
|
|||||||
QObject::tr("Use the same credentials for both database files."));
|
QObject::tr("Use the same credentials for both database files."));
|
||||||
parser.addOption(samePasswordOption);
|
parser.addOption(samePasswordOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
|
|
||||||
QCommandLineOption keyFileFromOption(QStringList() << "f"
|
QCommandLineOption keyFileFromOption(QStringList() << "f"
|
||||||
<< "key-file-from",
|
<< "key-file-from",
|
||||||
@ -59,6 +60,10 @@ int Merge::execute(const QStringList& arguments)
|
|||||||
QObject::tr("path"));
|
QObject::tr("path"));
|
||||||
parser.addOption(keyFileFromOption);
|
parser.addOption(keyFileFromOption);
|
||||||
|
|
||||||
|
QCommandLineOption noPasswordFromOption(QStringList() << "no-password-from",
|
||||||
|
QObject::tr("Deactivate password key for the database to merge from."));
|
||||||
|
parser.addOption(noPasswordFromOption);
|
||||||
|
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.process(arguments);
|
parser.process(arguments);
|
||||||
|
|
||||||
@ -69,6 +74,7 @@ int Merge::execute(const QStringList& arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto db1 = Utils::unlockDatabase(args.at(0),
|
auto db1 = Utils::unlockDatabase(args.at(0),
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
@ -79,6 +85,7 @@ int Merge::execute(const QStringList& arguments)
|
|||||||
QSharedPointer<Database> db2;
|
QSharedPointer<Database> db2;
|
||||||
if (!parser.isSet("same-credentials")) {
|
if (!parser.isSet("same-credentials")) {
|
||||||
db2 = Utils::unlockDatabase(args.at(1),
|
db2 = Utils::unlockDatabase(args.at(1),
|
||||||
|
!parser.isSet(noPasswordFromOption),
|
||||||
parser.value(keyFileFromOption),
|
parser.value(keyFileFromOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -51,6 +51,7 @@ int Remove::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
parser.addPositionalArgument("entry", QObject::tr("Path of the entry to remove."));
|
parser.addPositionalArgument("entry", QObject::tr("Path of the entry to remove."));
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.process(arguments);
|
parser.process(arguments);
|
||||||
@ -62,6 +63,7 @@ int Remove::execute(const QStringList& arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto db = Utils::unlockDatabase(args.at(0),
|
auto db = Utils::unlockDatabase(args.at(0),
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -48,6 +48,8 @@ int Show::execute(const QStringList& arguments)
|
|||||||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||||
parser.addOption(Command::QuietOption);
|
parser.addOption(Command::QuietOption);
|
||||||
parser.addOption(Command::KeyFileOption);
|
parser.addOption(Command::KeyFileOption);
|
||||||
|
parser.addOption(Command::NoPasswordOption);
|
||||||
|
|
||||||
QCommandLineOption totp(QStringList() << "t"
|
QCommandLineOption totp(QStringList() << "t"
|
||||||
<< "totp",
|
<< "totp",
|
||||||
QObject::tr("Show the entry's current TOTP."));
|
QObject::tr("Show the entry's current TOTP."));
|
||||||
@ -72,6 +74,7 @@ int Show::execute(const QStringList& arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto db = Utils::unlockDatabase(args.at(0),
|
auto db = Utils::unlockDatabase(args.at(0),
|
||||||
|
!parser.isSet(Command::NoPasswordOption),
|
||||||
parser.value(Command::KeyFileOption),
|
parser.value(Command::KeyFileOption),
|
||||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||||
Utils::STDERR);
|
Utils::STDERR);
|
||||||
|
@ -98,6 +98,7 @@ namespace Utils
|
|||||||
} // namespace Test
|
} // namespace Test
|
||||||
|
|
||||||
QSharedPointer<Database> unlockDatabase(const QString& databaseFilename,
|
QSharedPointer<Database> unlockDatabase(const QString& databaseFilename,
|
||||||
|
const bool isPasswordProtected,
|
||||||
const QString& keyFilename,
|
const QString& keyFilename,
|
||||||
FILE* outputDescriptor,
|
FILE* outputDescriptor,
|
||||||
FILE* errorDescriptor)
|
FILE* errorDescriptor)
|
||||||
@ -106,12 +107,13 @@ namespace Utils
|
|||||||
TextStream out(outputDescriptor);
|
TextStream out(outputDescriptor);
|
||||||
TextStream err(errorDescriptor);
|
TextStream err(errorDescriptor);
|
||||||
|
|
||||||
out << QObject::tr("Insert password to unlock %1: ").arg(databaseFilename) << flush;
|
if (isPasswordProtected) {
|
||||||
|
out << QObject::tr("Insert password to unlock %1: ").arg(databaseFilename) << flush;
|
||||||
QString line = Utils::getPassword(outputDescriptor);
|
QString line = Utils::getPassword(outputDescriptor);
|
||||||
auto passwordKey = QSharedPointer<PasswordKey>::create();
|
auto passwordKey = QSharedPointer<PasswordKey>::create();
|
||||||
passwordKey->setPassword(line);
|
passwordKey->setPassword(line);
|
||||||
compositeKey->addKey(passwordKey);
|
compositeKey->addKey(passwordKey);
|
||||||
|
}
|
||||||
|
|
||||||
if (!keyFilename.isEmpty()) {
|
if (!keyFilename.isEmpty()) {
|
||||||
auto fileKey = QSharedPointer<FileKey>::create();
|
auto fileKey = QSharedPointer<FileKey>::create();
|
||||||
|
@ -36,6 +36,7 @@ namespace Utils
|
|||||||
QString getPassword(FILE* outputDescriptor = STDOUT);
|
QString getPassword(FILE* outputDescriptor = STDOUT);
|
||||||
int clipText(const QString& text);
|
int clipText(const QString& text);
|
||||||
QSharedPointer<Database> unlockDatabase(const QString& databaseFilename,
|
QSharedPointer<Database> unlockDatabase(const QString& databaseFilename,
|
||||||
|
const bool isPasswordProtected = true,
|
||||||
const QString& keyFilename = {},
|
const QString& keyFilename = {},
|
||||||
FILE* outputDescriptor = STDOUT,
|
FILE* outputDescriptor = STDOUT,
|
||||||
FILE* errorDescriptor = STDERR);
|
FILE* errorDescriptor = STDERR);
|
||||||
|
@ -62,6 +62,9 @@ Displays debugging information.
|
|||||||
.IP "-k, --key-file <path>"
|
.IP "-k, --key-file <path>"
|
||||||
Specifies a path to a key file for unlocking the database. In a merge operation this option is used to specify the key file path for the first database.
|
Specifies a path to a key file for unlocking the database. In a merge operation this option is used to specify the key file path for the first database.
|
||||||
|
|
||||||
|
.IP "--no-password"
|
||||||
|
Deactivate password key for the database.
|
||||||
|
|
||||||
.IP "-q, --quiet <path>"
|
.IP "-q, --quiet <path>"
|
||||||
Silence password prompt and other secondary outputs.
|
Silence password prompt and other secondary outputs.
|
||||||
|
|
||||||
@ -77,6 +80,9 @@ Displays the program version.
|
|||||||
.IP "-f, --key-file-from <path>"
|
.IP "-f, --key-file-from <path>"
|
||||||
Path of the key file for the second database.
|
Path of the key file for the second database.
|
||||||
|
|
||||||
|
.IP "--no-password-from"
|
||||||
|
Deactivate password key for the database to merge from.
|
||||||
|
|
||||||
.IP "-s, --same-credentials"
|
.IP "-s, --same-credentials"
|
||||||
Use the same credentials for unlocking both database.
|
Use the same credentials for unlocking both database.
|
||||||
|
|
||||||
|
@ -70,11 +70,23 @@ void TestCli::initTestCase()
|
|||||||
QVERIFY(Tools::readAllFromDevice(&sourceDbFile, m_dbData));
|
QVERIFY(Tools::readAllFromDevice(&sourceDbFile, m_dbData));
|
||||||
sourceDbFile.close();
|
sourceDbFile.close();
|
||||||
|
|
||||||
// Load the NewDatabase.kdbx file into temporary storage
|
// Load the NewDatabase2.kdbx file into temporary storage
|
||||||
QFile sourceDbFile2(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase2.kdbx"));
|
QFile sourceDbFile2(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase2.kdbx"));
|
||||||
QVERIFY(sourceDbFile2.open(QIODevice::ReadOnly));
|
QVERIFY(sourceDbFile2.open(QIODevice::ReadOnly));
|
||||||
QVERIFY(Tools::readAllFromDevice(&sourceDbFile2, m_dbData2));
|
QVERIFY(Tools::readAllFromDevice(&sourceDbFile2, m_dbData2));
|
||||||
sourceDbFile2.close();
|
sourceDbFile2.close();
|
||||||
|
|
||||||
|
// Load the KeyFileProtected.kdbx file into temporary storage
|
||||||
|
QFile sourceDbFile3(QString(KEEPASSX_TEST_DATA_DIR).append("/KeyFileProtected.kdbx"));
|
||||||
|
QVERIFY(sourceDbFile3.open(QIODevice::ReadOnly));
|
||||||
|
QVERIFY(Tools::readAllFromDevice(&sourceDbFile3, m_keyFileProtectedDbData));
|
||||||
|
sourceDbFile3.close();
|
||||||
|
|
||||||
|
// Load the KeyFileProtectedNoPassword.kdbx file into temporary storage
|
||||||
|
QFile sourceDbFile4(QString(KEEPASSX_TEST_DATA_DIR).append("/KeyFileProtectedNoPassword.kdbx"));
|
||||||
|
QVERIFY(sourceDbFile4.open(QIODevice::ReadOnly));
|
||||||
|
QVERIFY(Tools::readAllFromDevice(&sourceDbFile4, m_keyFileProtectedNoPasswordDbData));
|
||||||
|
sourceDbFile4.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCli::init()
|
void TestCli::init()
|
||||||
@ -89,6 +101,16 @@ void TestCli::init()
|
|||||||
m_dbFile2->write(m_dbData2);
|
m_dbFile2->write(m_dbData2);
|
||||||
m_dbFile2->close();
|
m_dbFile2->close();
|
||||||
|
|
||||||
|
m_keyFileProtectedDbFile.reset(new TemporaryFile());
|
||||||
|
m_keyFileProtectedDbFile->open();
|
||||||
|
m_keyFileProtectedDbFile->write(m_keyFileProtectedDbData);
|
||||||
|
m_keyFileProtectedDbFile->close();
|
||||||
|
|
||||||
|
m_keyFileProtectedNoPasswordDbFile.reset(new TemporaryFile());
|
||||||
|
m_keyFileProtectedNoPasswordDbFile->open();
|
||||||
|
m_keyFileProtectedNoPasswordDbFile->write(m_keyFileProtectedNoPasswordDbData);
|
||||||
|
m_keyFileProtectedNoPasswordDbFile->close();
|
||||||
|
|
||||||
m_stdinFile.reset(new TemporaryFile());
|
m_stdinFile.reset(new TemporaryFile());
|
||||||
m_stdinFile->open();
|
m_stdinFile->open();
|
||||||
m_stdinHandle = fdopen(m_stdinFile->handle(), "r+");
|
m_stdinHandle = fdopen(m_stdinFile->handle(), "r+");
|
||||||
@ -131,7 +153,7 @@ void TestCli::cleanupTestCase()
|
|||||||
QSharedPointer<Database> TestCli::readTestDatabase() const
|
QSharedPointer<Database> TestCli::readTestDatabase() const
|
||||||
{
|
{
|
||||||
Utils::Test::setNextPassword("a");
|
Utils::Test::setNextPassword("a");
|
||||||
auto db = QSharedPointer<Database>(Utils::unlockDatabase(m_dbFile->fileName(), "", m_stdoutHandle));
|
auto db = QSharedPointer<Database>(Utils::unlockDatabase(m_dbFile->fileName(), true, "", m_stdoutHandle));
|
||||||
m_stdoutFile->seek(ftell(m_stdoutHandle)); // re-synchronize handles
|
m_stdoutFile->seek(ftell(m_stdoutHandle)); // re-synchronize handles
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
@ -320,7 +342,7 @@ void TestCli::testCreate()
|
|||||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
||||||
|
|
||||||
Utils::Test::setNextPassword("a");
|
Utils::Test::setNextPassword("a");
|
||||||
auto db = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename, "", Utils::DEVNULL));
|
auto db = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename, true, "", Utils::DEVNULL));
|
||||||
QVERIFY(db);
|
QVERIFY(db);
|
||||||
|
|
||||||
// Should refuse to create the database if it already exists.
|
// Should refuse to create the database if it already exists.
|
||||||
@ -349,7 +371,7 @@ void TestCli::testCreate()
|
|||||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
||||||
|
|
||||||
Utils::Test::setNextPassword("a");
|
Utils::Test::setNextPassword("a");
|
||||||
auto db2 = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename2, keyfilePath, Utils::DEVNULL));
|
auto db2 = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename2, true, keyfilePath, Utils::DEVNULL));
|
||||||
QVERIFY(db2);
|
QVERIFY(db2);
|
||||||
|
|
||||||
// Testing with existing keyfile
|
// Testing with existing keyfile
|
||||||
@ -366,7 +388,7 @@ void TestCli::testCreate()
|
|||||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
||||||
|
|
||||||
Utils::Test::setNextPassword("a");
|
Utils::Test::setNextPassword("a");
|
||||||
auto db3 = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename3, keyfilePath, Utils::DEVNULL));
|
auto db3 = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilename3, true, keyfilePath, Utils::DEVNULL));
|
||||||
QVERIFY(db3);
|
QVERIFY(db3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,6 +681,65 @@ void TestCli::testGenerate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestCli::testKeyFileOption()
|
||||||
|
{
|
||||||
|
List listCmd;
|
||||||
|
|
||||||
|
QString keyFilePath(QString(KEEPASSX_TEST_DATA_DIR).append("/KeyFileProtected.key"));
|
||||||
|
Utils::Test::setNextPassword("a");
|
||||||
|
listCmd.execute({"ls", "-k", keyFilePath, m_keyFileProtectedDbFile->fileName()});
|
||||||
|
m_stdoutFile->reset();
|
||||||
|
m_stdoutFile->readLine(); // skip password prompt
|
||||||
|
QCOMPARE(m_stdoutFile->readAll(), QByteArray("entry1\n"
|
||||||
|
"entry2\n"));
|
||||||
|
|
||||||
|
// Should raise an error with no key file.
|
||||||
|
qint64 pos = m_stdoutFile->pos();
|
||||||
|
qint64 posErr = m_stderrFile->pos();
|
||||||
|
Utils::Test::setNextPassword("a");
|
||||||
|
listCmd.execute({"ls", m_keyFileProtectedDbFile->fileName()});
|
||||||
|
m_stdoutFile->seek(pos);
|
||||||
|
m_stdoutFile->readLine(); // skip password prompt
|
||||||
|
m_stderrFile->seek(posErr);
|
||||||
|
QCOMPARE(m_stdoutFile->readAll(), QByteArray(""));
|
||||||
|
QCOMPARE(m_stderrFile->readAll(),
|
||||||
|
QByteArray("Error while reading the database: Wrong key or database file is corrupt. (HMAC mismatch)\n"));
|
||||||
|
|
||||||
|
// Should raise an error if key file path is invalid.
|
||||||
|
pos = m_stdoutFile->pos();
|
||||||
|
posErr = m_stderrFile->pos();
|
||||||
|
Utils::Test::setNextPassword("a");
|
||||||
|
listCmd.execute({"ls", "-k", "invalidpath", m_keyFileProtectedDbFile->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("Failed to load key file invalidpath"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestCli::testNoPasswordOption()
|
||||||
|
{
|
||||||
|
List listCmd;
|
||||||
|
|
||||||
|
QString keyFilePath(QString(KEEPASSX_TEST_DATA_DIR).append("/KeyFileProtectedNoPassword.key"));
|
||||||
|
listCmd.execute({"ls", "-k", keyFilePath, "--no-password", m_keyFileProtectedNoPasswordDbFile->fileName()});
|
||||||
|
m_stdoutFile->reset();
|
||||||
|
QCOMPARE(m_stdoutFile->readAll(), QByteArray("entry1\n"
|
||||||
|
"entry2\n"));
|
||||||
|
|
||||||
|
// Should raise an error with no key file.
|
||||||
|
qint64 pos = m_stdoutFile->pos();
|
||||||
|
qint64 posErr = m_stderrFile->pos();
|
||||||
|
listCmd.execute({"ls", "--no-password", m_keyFileProtectedNoPasswordDbFile->fileName()});
|
||||||
|
m_stdoutFile->seek(pos);
|
||||||
|
m_stdoutFile->readLine(); // skip password prompt
|
||||||
|
m_stderrFile->seek(posErr);
|
||||||
|
QCOMPARE(m_stdoutFile->readAll(), QByteArray(""));
|
||||||
|
QCOMPARE(m_stderrFile->readAll(),
|
||||||
|
QByteArray("Error while reading the database: Wrong key or database file is corrupt. (HMAC mismatch)\n"));
|
||||||
|
}
|
||||||
|
|
||||||
void TestCli::testList()
|
void TestCli::testList()
|
||||||
{
|
{
|
||||||
List listCmd;
|
List listCmd;
|
||||||
|
@ -51,6 +51,8 @@ private slots:
|
|||||||
void testExtract();
|
void testExtract();
|
||||||
void testGenerate_data();
|
void testGenerate_data();
|
||||||
void testGenerate();
|
void testGenerate();
|
||||||
|
void testKeyFileOption();
|
||||||
|
void testNoPasswordOption();
|
||||||
void testList();
|
void testList();
|
||||||
void testLocate();
|
void testLocate();
|
||||||
void testMerge();
|
void testMerge();
|
||||||
@ -61,8 +63,12 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
QByteArray m_dbData;
|
QByteArray m_dbData;
|
||||||
QByteArray m_dbData2;
|
QByteArray m_dbData2;
|
||||||
|
QByteArray m_keyFileProtectedDbData;
|
||||||
|
QByteArray m_keyFileProtectedNoPasswordDbData;
|
||||||
QScopedPointer<TemporaryFile> m_dbFile;
|
QScopedPointer<TemporaryFile> m_dbFile;
|
||||||
QScopedPointer<TemporaryFile> m_dbFile2;
|
QScopedPointer<TemporaryFile> m_dbFile2;
|
||||||
|
QScopedPointer<TemporaryFile> m_keyFileProtectedDbFile;
|
||||||
|
QScopedPointer<TemporaryFile> m_keyFileProtectedNoPasswordDbFile;
|
||||||
QScopedPointer<TemporaryFile> m_stdoutFile;
|
QScopedPointer<TemporaryFile> m_stdoutFile;
|
||||||
QScopedPointer<TemporaryFile> m_stderrFile;
|
QScopedPointer<TemporaryFile> m_stderrFile;
|
||||||
QScopedPointer<TemporaryFile> m_stdinFile;
|
QScopedPointer<TemporaryFile> m_stdinFile;
|
||||||
|
BIN
tests/data/KeyFileProtected.kdbx
Normal file
BIN
tests/data/KeyFileProtected.kdbx
Normal file
Binary file not shown.
BIN
tests/data/KeyFileProtected.key
Normal file
BIN
tests/data/KeyFileProtected.key
Normal file
Binary file not shown.
BIN
tests/data/KeyFileProtectedNoPassword.kdbx
Normal file
BIN
tests/data/KeyFileProtectedNoPassword.kdbx
Normal file
Binary file not shown.
BIN
tests/data/KeyFileProtectedNoPassword.key
Normal file
BIN
tests/data/KeyFileProtectedNoPassword.key
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user