Skip to content

Commit

Permalink
CLI: Cleanup create options (keepassxreboot#4313)
Browse files Browse the repository at this point in the history
* Add ability to create database with an empty password
* Add password repeat check
* Standardize process between `db-create` and `import` commands
* Improve db-create tests with new password repeat

Co-authored-by: Jonathan White <[email protected]>
  • Loading branch information
louib and droidmonkey authored Mar 19, 2020
1 parent b045160 commit e6c2c7e
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 54 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

### Changed
- Renamed CLI create command to db-create [#4231]
- Added --set-password option for CLI db-create command
- Added --set-key-file option for CLI db-create command (replacing --key-file option)

## 2.5.3 (2020-01-19)

Expand Down
8 changes: 7 additions & 1 deletion share/docs/man/keepassxc-cli.1
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Copies an attribute or the current TOTP (if the \fI-t\fP option is specified) of
In interactive mode, closes the currently opened database (see \fIopen\fP).

.IP "\fBdb-create\fP [options] <database>"
Creates a new database with a key file and/or password. The key file will be created if the file that is referred to does not exist. If both the key file and password are empty, no database will be created.
Creates a new database with a password and/or a key file. The key file will be created if the file that is referred to does not exist. If both the key file and password are empty, no database will be created.

.IP "\fBdb-info\fP [options] <database>"
Show a database's information.
Expand Down Expand Up @@ -185,6 +185,12 @@ Will report an error if no TOTP is configured for the entry.

.SS "Create options"

.IP "\fB-k\fP, \fB--set-key-file\fP <path>"
Set the key file for the database.

.IP "\fB-p\fP, \fB--set-password\fP"
Set a password for the database.

.IP "\fB-t\fP, \fB--decryption-time\fP <time>"
Target decryption time in MS for the database.

Expand Down
37 changes: 27 additions & 10 deletions src/cli/Create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,24 @@ const QCommandLineOption Create::DecryptionTimeOption =
QObject::tr("Target decryption time in MS for the database."),
QObject::tr("time"));

const QCommandLineOption Create::SetKeyFileOption =
QCommandLineOption(QStringList() << "k"
<< "set-key-file",
QObject::tr("Set the key file for the database."),
QObject::tr("path"));

const QCommandLineOption Create::SetPasswordOption =
QCommandLineOption(QStringList() << "p"
<< "set-password",
QObject::tr("Set a password for the database."));

Create::Create()
{
name = QString("db-create");
description = QObject::tr("Create a new database.");
positionalArguments.append({QString("database"), QObject::tr("Path of the database."), QString("")});
options.append(Command::KeyFileOption);
options.append(Create::SetKeyFileOption);
options.append(Create::SetPasswordOption);
options.append(Create::DecryptionTimeOption);
}

Expand Down Expand Up @@ -97,21 +109,26 @@ int Create::execute(const QStringList& arguments)

auto key = QSharedPointer<CompositeKey>::create();

auto password = Utils::getPasswordFromStdin();
if (!password.isNull()) {
key->addKey(password);
if (parser->isSet(Create::SetPasswordOption)) {
auto passwordKey = Utils::getPasswordFromStdin();
if (passwordKey.isNull()) {
err << QObject::tr("Failed to set database password.") << endl;
return EXIT_FAILURE;
}
key->addKey(passwordKey);
}

QSharedPointer<FileKey> fileKey;
if (parser->isSet(Command::KeyFileOption)) {
if (!loadFileKey(parser->value(Command::KeyFileOption), fileKey)) {
if (parser->isSet(Create::SetKeyFileOption)) {
QSharedPointer<FileKey> fileKey;

if (!loadFileKey(parser->value(Create::SetKeyFileOption), fileKey)) {
err << QObject::tr("Loading the key file failed") << endl;
return EXIT_FAILURE;
}
}

if (!fileKey.isNull()) {
key->addKey(fileKey);
if (!fileKey.isNull()) {
key->addKey(fileKey);
}
}

if (key->isEmpty()) {
Expand Down
2 changes: 2 additions & 0 deletions src/cli/Create.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class Create : public Command
Create();
int execute(const QStringList& arguments) override;

static const QCommandLineOption SetKeyFileOption;
static const QCommandLineOption SetPasswordOption;
static const QCommandLineOption DecryptionTimeOption;

private:
Expand Down
8 changes: 5 additions & 3 deletions src/cli/Import.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,12 @@ int Import::execute(const QStringList& arguments)

auto key = QSharedPointer<CompositeKey>::create();

auto password = Utils::getPasswordFromStdin();
if (!password.isNull()) {
key->addKey(password);
auto passwordKey = Utils::getPasswordFromStdin();
if (passwordKey.isNull()) {
errorTextStream << QObject::tr("Failed to set database password.") << endl;
return EXIT_FAILURE;
}
key->addKey(passwordKey);

if (key->isEmpty()) {
errorTextStream << QObject::tr("No key is set. Aborting database creation.") << endl;
Expand Down
32 changes: 28 additions & 4 deletions src/cli/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,12 @@ namespace Utils
*
* @param password password to return next
*/
void setNextPassword(const QString& password)
void setNextPassword(const QString& password, bool repeat)
{
nextPasswords.append(password);
if (repeat) {
nextPasswords.append(password);
}
}
} // namespace Test

Expand Down Expand Up @@ -232,10 +235,31 @@ namespace Utils

out << QObject::tr("Enter password to encrypt database (optional): ");
out.flush();
QString password = Utils::getPassword();
auto password = Utils::getPassword();

if (password.isEmpty()) {
out << QObject::tr("Do you want to create a database with an empty password? [y/N]: ");
out.flush();
TextStream ts(STDIN, QIODevice::ReadOnly);
if (!ts.device()->isSequential()) {
// This is required for testing on macOS
ts.seek(0);
}
auto ans = ts.readLine();
if (ans.toLower().startsWith("y")) {
passwordKey = QSharedPointer<PasswordKey>::create("");
}
out << endl;
} else {
out << QObject::tr("Repeat password: ");
out.flush();
auto repeat = Utils::getPassword();

if (!password.isEmpty()) {
passwordKey = QSharedPointer<PasswordKey>(new PasswordKey(password));
if (password == repeat) {
passwordKey = QSharedPointer<PasswordKey>::create(password);
} else {
out << QObject::tr("Error: Passwords do not match.") << endl;
}
}

return passwordKey;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ namespace Utils

namespace Test
{
void setNextPassword(const QString& password);
void setNextPassword(const QString& password, bool repeat = false);
}
}; // namespace Utils

Expand Down
Loading

0 comments on commit e6c2c7e

Please sign in to comment.