mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-08-09 23:12:23 -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
20 changed files with 146 additions and 20 deletions
|
@ -50,6 +50,7 @@ int Add::execute(const QStringList& arguments)
|
|||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
|
||||
QCommandLineOption username(QStringList() << "u"
|
||||
<< "username",
|
||||
|
@ -91,6 +92,7 @@ int Add::execute(const QStringList& arguments)
|
|||
const QString& entryPath = args.at(1);
|
||||
|
||||
auto db = Utils::unlockDatabase(databasePath,
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -49,6 +49,7 @@ int Clip::execute(const QStringList& arguments)
|
|||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
|
||||
QCommandLineOption totp(QStringList() << "t"
|
||||
<< "totp",
|
||||
|
@ -67,6 +68,7 @@ int Clip::execute(const QStringList& arguments)
|
|||
}
|
||||
|
||||
auto db = Utils::unlockDatabase(args.at(0),
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -46,6 +46,10 @@ const QCommandLineOption Command::KeyFileOption = QCommandLineOption(QStringList
|
|||
QObject::tr("Key file of the database."),
|
||||
QObject::tr("path"));
|
||||
|
||||
const QCommandLineOption Command::NoPasswordOption =
|
||||
QCommandLineOption(QStringList() << "no-password",
|
||||
QObject::tr("Deactivate password key for the database."));
|
||||
|
||||
QMap<QString, Command*> commands;
|
||||
|
||||
Command::~Command()
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
|
||||
static const QCommandLineOption QuietOption;
|
||||
static const QCommandLineOption KeyFileOption;
|
||||
static const QCommandLineOption NoPasswordOption;
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_COMMAND_H
|
||||
|
|
|
@ -49,6 +49,7 @@ int Edit::execute(const QStringList& arguments)
|
|||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
|
||||
QCommandLineOption username(QStringList() << "u"
|
||||
<< "username",
|
||||
|
@ -95,6 +96,7 @@ int Edit::execute(const QStringList& arguments)
|
|||
const QString& entryPath = args.at(1);
|
||||
|
||||
auto db = Utils::unlockDatabase(databasePath,
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -51,6 +51,7 @@ int Extract::execute(const QStringList& arguments)
|
|||
parser.addPositionalArgument("database", QObject::tr("Path of the database to extract."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
parser.addHelpOption();
|
||||
parser.process(arguments);
|
||||
|
||||
|
@ -59,17 +60,19 @@ int Extract::execute(const QStringList& arguments)
|
|||
errorTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli extract");
|
||||
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();
|
||||
|
||||
QString line = Utils::getPassword(parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT);
|
||||
auto passwordKey = QSharedPointer<PasswordKey>::create();
|
||||
passwordKey->setPassword(line);
|
||||
compositeKey->addKey(passwordKey);
|
||||
if (!parser.isSet(Command::NoPasswordOption)) {
|
||||
if (!parser.isSet(Command::QuietOption)) {
|
||||
outputTextStream << QObject::tr("Insert password to unlock %1: ").arg(args.at(0)) << flush;
|
||||
}
|
||||
|
||||
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);
|
||||
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.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
|
||||
QCommandLineOption recursiveOption(QStringList() << "R"
|
||||
<< "recursive",
|
||||
|
@ -65,6 +66,7 @@ int List::execute(const QStringList& arguments)
|
|||
bool recursive = parser.isSet(recursiveOption);
|
||||
|
||||
auto db = Utils::unlockDatabase(args.at(0),
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -50,6 +50,7 @@ int Locate::execute(const QStringList& arguments)
|
|||
parser.addPositionalArgument("term", QObject::tr("Search term."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
parser.addHelpOption();
|
||||
parser.process(arguments);
|
||||
|
||||
|
@ -60,6 +61,7 @@ int Locate::execute(const QStringList& arguments)
|
|||
}
|
||||
|
||||
auto db = Utils::unlockDatabase(args.at(0),
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -52,6 +52,7 @@ int Merge::execute(const QStringList& arguments)
|
|||
QObject::tr("Use the same credentials for both database files."));
|
||||
parser.addOption(samePasswordOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
|
||||
QCommandLineOption keyFileFromOption(QStringList() << "f"
|
||||
<< "key-file-from",
|
||||
|
@ -59,6 +60,10 @@ int Merge::execute(const QStringList& arguments)
|
|||
QObject::tr("path"));
|
||||
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.process(arguments);
|
||||
|
||||
|
@ -69,6 +74,7 @@ int Merge::execute(const QStringList& arguments)
|
|||
}
|
||||
|
||||
auto db1 = Utils::unlockDatabase(args.at(0),
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
@ -79,6 +85,7 @@ int Merge::execute(const QStringList& arguments)
|
|||
QSharedPointer<Database> db2;
|
||||
if (!parser.isSet("same-credentials")) {
|
||||
db2 = Utils::unlockDatabase(args.at(1),
|
||||
!parser.isSet(noPasswordFromOption),
|
||||
parser.value(keyFileFromOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -51,6 +51,7 @@ int Remove::execute(const QStringList& arguments)
|
|||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
parser.addPositionalArgument("entry", QObject::tr("Path of the entry to remove."));
|
||||
parser.addHelpOption();
|
||||
parser.process(arguments);
|
||||
|
@ -62,6 +63,7 @@ int Remove::execute(const QStringList& arguments)
|
|||
}
|
||||
|
||||
auto db = Utils::unlockDatabase(args.at(0),
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -48,6 +48,8 @@ int Show::execute(const QStringList& arguments)
|
|||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addOption(Command::NoPasswordOption);
|
||||
|
||||
QCommandLineOption totp(QStringList() << "t"
|
||||
<< "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),
|
||||
!parser.isSet(Command::NoPasswordOption),
|
||||
parser.value(Command::KeyFileOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
|
|
|
@ -98,6 +98,7 @@ namespace Utils
|
|||
} // namespace Test
|
||||
|
||||
QSharedPointer<Database> unlockDatabase(const QString& databaseFilename,
|
||||
const bool isPasswordProtected,
|
||||
const QString& keyFilename,
|
||||
FILE* outputDescriptor,
|
||||
FILE* errorDescriptor)
|
||||
|
@ -106,12 +107,13 @@ namespace Utils
|
|||
TextStream out(outputDescriptor);
|
||||
TextStream err(errorDescriptor);
|
||||
|
||||
out << QObject::tr("Insert password to unlock %1: ").arg(databaseFilename) << flush;
|
||||
|
||||
QString line = Utils::getPassword(outputDescriptor);
|
||||
auto passwordKey = QSharedPointer<PasswordKey>::create();
|
||||
passwordKey->setPassword(line);
|
||||
compositeKey->addKey(passwordKey);
|
||||
if (isPasswordProtected) {
|
||||
out << QObject::tr("Insert password to unlock %1: ").arg(databaseFilename) << flush;
|
||||
QString line = Utils::getPassword(outputDescriptor);
|
||||
auto passwordKey = QSharedPointer<PasswordKey>::create();
|
||||
passwordKey->setPassword(line);
|
||||
compositeKey->addKey(passwordKey);
|
||||
}
|
||||
|
||||
if (!keyFilename.isEmpty()) {
|
||||
auto fileKey = QSharedPointer<FileKey>::create();
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace Utils
|
|||
QString getPassword(FILE* outputDescriptor = STDOUT);
|
||||
int clipText(const QString& text);
|
||||
QSharedPointer<Database> unlockDatabase(const QString& databaseFilename,
|
||||
const bool isPasswordProtected = true,
|
||||
const QString& keyFilename = {},
|
||||
FILE* outputDescriptor = STDOUT,
|
||||
FILE* errorDescriptor = STDERR);
|
||||
|
|
|
@ -62,6 +62,9 @@ Displays debugging information.
|
|||
.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.
|
||||
|
||||
.IP "--no-password"
|
||||
Deactivate password key for the database.
|
||||
|
||||
.IP "-q, --quiet <path>"
|
||||
Silence password prompt and other secondary outputs.
|
||||
|
||||
|
@ -77,6 +80,9 @@ Displays the program version.
|
|||
.IP "-f, --key-file-from <path>"
|
||||
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"
|
||||
Use the same credentials for unlocking both database.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue