Merge pull request #1406 from keepassxreboot/feature/cli-passgen

Add diceware and passgen to the cli interface
This commit is contained in:
Janek Bevendorff 2018-02-07 20:26:15 +01:00 committed by GitHub
commit 13dc1e02ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 471 additions and 94 deletions

View File

@ -211,7 +211,7 @@ void BrowserSettings::setVivaldiSupport(bool enabled) {
bool BrowserSettings::passwordUseNumbers() bool BrowserSettings::passwordUseNumbers()
{ {
return config()->get("generator/Numbers", true).toBool(); return config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool();
} }
void BrowserSettings::setPasswordUseNumbers(bool useNumbers) void BrowserSettings::setPasswordUseNumbers(bool useNumbers)
@ -221,7 +221,7 @@ void BrowserSettings::setPasswordUseNumbers(bool useNumbers)
bool BrowserSettings::passwordUseLowercase() bool BrowserSettings::passwordUseLowercase()
{ {
return config()->get("generator/LowerCase", true).toBool(); return config()->get("generator/LowerCase", PasswordGenerator::DefaultLower).toBool();
} }
void BrowserSettings::setPasswordUseLowercase(bool useLowercase) void BrowserSettings::setPasswordUseLowercase(bool useLowercase)
@ -231,7 +231,7 @@ void BrowserSettings::setPasswordUseLowercase(bool useLowercase)
bool BrowserSettings::passwordUseUppercase() bool BrowserSettings::passwordUseUppercase()
{ {
return config()->get("generator/UpperCase", true).toBool(); return config()->get("generator/UpperCase", PasswordGenerator::DefaultUpper).toBool();
} }
void BrowserSettings::setPasswordUseUppercase(bool useUppercase) void BrowserSettings::setPasswordUseUppercase(bool useUppercase)
@ -241,7 +241,7 @@ void BrowserSettings::setPasswordUseUppercase(bool useUppercase)
bool BrowserSettings::passwordUseSpecial() bool BrowserSettings::passwordUseSpecial()
{ {
return config()->get("generator/SpecialChars", false).toBool(); return config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool();
} }
void BrowserSettings::setPasswordUseSpecial(bool useSpecial) void BrowserSettings::setPasswordUseSpecial(bool useSpecial)
@ -251,7 +251,7 @@ void BrowserSettings::setPasswordUseSpecial(bool useSpecial)
bool BrowserSettings::passwordUseEASCII() bool BrowserSettings::passwordUseEASCII()
{ {
return config()->get("generator/EASCII", false).toBool(); return config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool();
} }
void BrowserSettings::setPasswordUseEASCII(bool useEASCII) void BrowserSettings::setPasswordUseEASCII(bool useEASCII)
@ -261,7 +261,7 @@ void BrowserSettings::setPasswordUseEASCII(bool useEASCII)
int BrowserSettings::passPhraseWordCount() int BrowserSettings::passPhraseWordCount()
{ {
return config()->get("generator/WordCount", 6).toInt(); return config()->get("generator/WordCount", PassphraseGenerator::DefaultWordCount).toInt();
} }
void BrowserSettings::setPassPhraseWordCount(int wordCount) void BrowserSettings::setPassPhraseWordCount(int wordCount)
@ -271,7 +271,7 @@ void BrowserSettings::setPassPhraseWordCount(int wordCount)
QString BrowserSettings::passPhraseWordSeparator() QString BrowserSettings::passPhraseWordSeparator()
{ {
return config()->get("generator/WordSeparator", " ").toString(); return config()->get("generator/WordSeparator", PassphraseGenerator::DefaultSeparator).toString();
} }
void BrowserSettings::setPassPhraseWordSeparator(QString separator) void BrowserSettings::setPassPhraseWordSeparator(QString separator)
@ -291,7 +291,7 @@ void BrowserSettings::setGeneratorType(int type)
bool BrowserSettings::passwordEveryGroup() bool BrowserSettings::passwordEveryGroup()
{ {
return config()->get("generator/EnsureEvery", true).toBool(); return config()->get("generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool();
} }
void BrowserSettings::setPasswordEveryGroup(bool everyGroup) void BrowserSettings::setPasswordEveryGroup(bool everyGroup)
@ -301,7 +301,7 @@ void BrowserSettings::setPasswordEveryGroup(bool everyGroup)
bool BrowserSettings::passwordExcludeAlike() bool BrowserSettings::passwordExcludeAlike()
{ {
return config()->get("generator/ExcludeAlike", true).toBool(); return config()->get("generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool();
} }
void BrowserSettings::setPasswordExcludeAlike(bool excludeAlike) void BrowserSettings::setPasswordExcludeAlike(bool excludeAlike)
@ -311,7 +311,7 @@ void BrowserSettings::setPasswordExcludeAlike(bool excludeAlike)
int BrowserSettings::passwordLength() int BrowserSettings::passwordLength()
{ {
return config()->get("generator/Length", 20).toInt(); return config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt();
} }
void BrowserSettings::setPasswordLength(int length) void BrowserSettings::setPasswordLength(int length)

View File

@ -31,15 +31,15 @@
Add::Add() Add::Add()
{ {
this->name = QString("add"); name = QString("add");
this->description = QObject::tr("Add a new entry to a database."); description = QObject::tr("Add a new entry to a database.");
} }
Add::~Add() Add::~Add()
{ {
} }
int Add::execute(QStringList arguments) int Add::execute(const QStringList& arguments)
{ {
QTextStream inputTextStream(stdin, QIODevice::ReadOnly); QTextStream inputTextStream(stdin, QIODevice::ReadOnly);
@ -133,8 +133,8 @@ int Add::execute(QStringList arguments)
passwordGenerator.setLength(passwordLength.toInt()); passwordGenerator.setLength(passwordLength.toInt());
} }
passwordGenerator.setCharClasses(PasswordGenerator::LowerLetters | PasswordGenerator::UpperLetters | passwordGenerator.setCharClasses(PasswordGenerator::DefaultCharset);
PasswordGenerator::Numbers); passwordGenerator.setFlags(PasswordGenerator::DefaultFlags);
QString password = passwordGenerator.generatePassword(); QString password = passwordGenerator.generatePassword();
entry->setPassword(password); entry->setPassword(password);
} }

View File

@ -25,7 +25,7 @@ class Add : public Command
public: public:
Add(); Add();
~Add(); ~Add();
int execute(QStringList arguments); int execute(const QStringList& arguments);
}; };
#endif // KEEPASSXC_ADD_H #endif // KEEPASSXC_ADD_H

View File

@ -20,12 +20,16 @@ set(cli_SOURCES
Clip.h Clip.h
Command.cpp Command.cpp
Command.h Command.h
Diceware.cpp
Diceware.h
Edit.cpp Edit.cpp
Edit.h Edit.h
Estimate.cpp Estimate.cpp
Estimate.h Estimate.h
Extract.cpp Extract.cpp
Extract.h Extract.h
Generate.cpp
Generate.h
List.cpp List.cpp
List.h List.h
Locate.cpp Locate.cpp

View File

@ -32,15 +32,15 @@
Clip::Clip() Clip::Clip()
{ {
this->name = QString("clip"); name = QString("clip");
this->description = QObject::tr("Copy an entry's password to the clipboard."); description = QObject::tr("Copy an entry's password to the clipboard.");
} }
Clip::~Clip() Clip::~Clip()
{ {
} }
int Clip::execute(QStringList arguments) int Clip::execute(const QStringList& arguments)
{ {
QTextStream out(stdout); QTextStream out(stdout);

View File

@ -25,7 +25,7 @@ class Clip : public Command
public: public:
Clip(); Clip();
~Clip(); ~Clip();
int execute(QStringList arguments); int execute(const QStringList& arguments);
int clipEntry(Database* database, QString entryPath, QString timeout); int clipEntry(Database* database, QString entryPath, QString timeout);
}; };

View File

@ -24,9 +24,11 @@
#include "Add.h" #include "Add.h"
#include "Clip.h" #include "Clip.h"
#include "Diceware.h"
#include "Edit.h" #include "Edit.h"
#include "Estimate.h" #include "Estimate.h"
#include "Extract.h" #include "Extract.h"
#include "Generate.h"
#include "List.h" #include "List.h"
#include "Locate.h" #include "Locate.h"
#include "Merge.h" #include "Merge.h"
@ -39,7 +41,7 @@ Command::~Command()
{ {
} }
int Command::execute(QStringList) int Command::execute(const QStringList&)
{ {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -61,9 +63,11 @@ void populateCommands()
if (commands.isEmpty()) { if (commands.isEmpty()) {
commands.insert(QString("add"), new Add()); commands.insert(QString("add"), new Add());
commands.insert(QString("clip"), new Clip()); commands.insert(QString("clip"), new Clip());
commands.insert(QString("diceware"), new Diceware());
commands.insert(QString("edit"), new Edit()); commands.insert(QString("edit"), new Edit());
commands.insert(QString("estimate"), new Estimate()); commands.insert(QString("estimate"), new Estimate());
commands.insert(QString("extract"), new Extract()); commands.insert(QString("extract"), new Extract());
commands.insert(QString("generate"), new Generate());
commands.insert(QString("locate"), new Locate()); commands.insert(QString("locate"), new Locate());
commands.insert(QString("ls"), new List()); commands.insert(QString("ls"), new List());
commands.insert(QString("merge"), new Merge()); commands.insert(QString("merge"), new Merge());

View File

@ -29,7 +29,7 @@ class Command
{ {
public: public:
virtual ~Command(); virtual ~Command();
virtual int execute(QStringList arguments); virtual int execute(const QStringList& arguments);
QString name; QString name;
QString description; QString description;
QString getDescriptionLine(); QString getDescriptionLine();

86
src/cli/Diceware.cpp Normal file
View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <stdio.h>
#include "Diceware.h"
#include <QCommandLineParser>
#include <QTextStream>
#include "core/PassphraseGenerator.h"
Diceware::Diceware()
{
name = QString("diceware");
description = QObject::tr("Generate a new random diceware passphrase.");
}
Diceware::~Diceware()
{
}
int Diceware::execute(const QStringList& arguments)
{
QTextStream inputTextStream(stdin, QIODevice::ReadOnly);
QTextStream outputTextStream(stdout, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(this->description);
QCommandLineOption words(QStringList() << "W" << "words",
QObject::tr("Word count for the diceware passphrase."),
QObject::tr("count"));
parser.addOption(words);
QCommandLineOption wordlistFile(QStringList() << "w"
<< "word-list",
QObject::tr("Wordlist for the diceware generator.\n[Default: EFF English]"),
QObject::tr("path"));
parser.addOption(wordlistFile);
parser.process(arguments);
const QStringList args = parser.positionalArguments();
if (!args.isEmpty()) {
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
return EXIT_FAILURE;
}
PassphraseGenerator dicewareGenerator;
if (parser.value(words).isEmpty()) {
dicewareGenerator.setWordCount(PassphraseGenerator::DefaultWordCount);
} else {
int wordcount = parser.value(words).toInt();
dicewareGenerator.setWordCount(wordcount);
}
if (!parser.value(wordlistFile).isEmpty()) {
dicewareGenerator.setWordList(parser.value(wordlistFile));
} else {
dicewareGenerator.setDefaultWordList();
}
if (!dicewareGenerator.isValid()) {
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli diceware");
return EXIT_FAILURE;
}
QString password = dicewareGenerator.generatePassphrase();
outputTextStream << password << endl;
return EXIT_SUCCESS;
}

31
src/cli/Diceware.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSXC_DICEWARE_H
#define KEEPASSXC_DICEWARE_H
#include "Command.h"
class Diceware : public Command
{
public:
Diceware();
~Diceware();
int execute(const QStringList& arguments);
};
#endif // KEEPASSXC_DICEWARE_H

View File

@ -31,15 +31,15 @@
Edit::Edit() Edit::Edit()
{ {
this->name = QString("edit"); name = QString("edit");
this->description = QObject::tr("Edit an entry."); description = QObject::tr("Edit an entry.");
} }
Edit::~Edit() Edit::~Edit()
{ {
} }
int Edit::execute(QStringList arguments) int Edit::execute(const QStringList& arguments)
{ {
QTextStream inputTextStream(stdin, QIODevice::ReadOnly); QTextStream inputTextStream(stdin, QIODevice::ReadOnly);
@ -149,8 +149,8 @@ int Edit::execute(QStringList arguments)
passwordGenerator.setLength(passwordLength.toInt()); passwordGenerator.setLength(passwordLength.toInt());
} }
passwordGenerator.setCharClasses(PasswordGenerator::LowerLetters | PasswordGenerator::UpperLetters | passwordGenerator.setCharClasses(PasswordGenerator::DefaultCharset);
PasswordGenerator::Numbers); passwordGenerator.setFlags(PasswordGenerator::DefaultFlags);
QString password = passwordGenerator.generatePassword(); QString password = passwordGenerator.generatePassword();
entry->setPassword(password); entry->setPassword(password);
} }

View File

@ -25,7 +25,7 @@ class Edit : public Command
public: public:
Edit(); Edit();
~Edit(); ~Edit();
int execute(QStringList arguments); int execute(const QStringList& arguments);
}; };
#endif // KEEPASSXC_EDIT_H #endif // KEEPASSXC_EDIT_H

View File

@ -34,8 +34,8 @@
Estimate::Estimate() Estimate::Estimate()
{ {
this->name = QString("estimate"); name = QString("estimate");
this->description = QObject::tr("Estimate the entropy of a password."); description = QObject::tr("Estimate the entropy of a password.");
} }
Estimate::~Estimate() Estimate::~Estimate()
@ -138,7 +138,7 @@ static void estimate(const char* pwd, bool advanced)
} }
} }
int Estimate::execute(QStringList arguments) int Estimate::execute(const QStringList& arguments)
{ {
QTextStream inputTextStream(stdin, QIODevice::ReadOnly); QTextStream inputTextStream(stdin, QIODevice::ReadOnly);
QTextStream outputTextStream(stdout, QIODevice::WriteOnly); QTextStream outputTextStream(stdout, QIODevice::WriteOnly);

View File

@ -25,7 +25,7 @@ class Estimate : public Command
public: public:
Estimate(); Estimate();
~Estimate(); ~Estimate();
int execute(QStringList arguments); int execute(const QStringList& arguments);
}; };
#endif // KEEPASSXC_ESTIMATE_H #endif // KEEPASSXC_ESTIMATE_H

View File

@ -33,15 +33,15 @@
Extract::Extract() Extract::Extract()
{ {
this->name = QString("extract"); name = QString("extract");
this->description = QObject::tr("Extract and print the content of a database."); description = QObject::tr("Extract and print the content of a database.");
} }
Extract::~Extract() Extract::~Extract()
{ {
} }
int Extract::execute(QStringList arguments) int Extract::execute(const QStringList& arguments)
{ {
QTextStream out(stdout); QTextStream out(stdout);
QTextStream errorTextStream(stderr); QTextStream errorTextStream(stderr);

View File

@ -25,7 +25,7 @@ class Extract : public Command
public: public:
Extract(); Extract();
~Extract(); ~Extract();
int execute(QStringList arguments); int execute(const QStringList& arguments);
}; };
#endif // KEEPASSXC_EXTRACT_H #endif // KEEPASSXC_EXTRACT_H

111
src/cli/Generate.cpp Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <stdio.h>
#include "Generate.h"
#include <QCommandLineParser>
#include <QTextStream>
#include "core/PasswordGenerator.h"
Generate::Generate()
{
name = QString("generate");
description = QObject::tr("Generate a new random password.");
}
Generate::~Generate()
{
}
int Generate::execute(const QStringList& arguments)
{
QTextStream inputTextStream(stdin, QIODevice::ReadOnly);
QTextStream outputTextStream(stdout, QIODevice::WriteOnly);
QCommandLineParser parser;
parser.setApplicationDescription(this->description);
QCommandLineOption len(QStringList() << "L" << "length",
QObject::tr("Length of the generated password."),
QObject::tr("length"));
parser.addOption(len);
QCommandLineOption lower(QStringList() << "l",
QObject::tr("Use lowercase characters in the generated password."));
parser.addOption(lower);
QCommandLineOption upper(QStringList() << "u",
QObject::tr("Use uppercase characters in the generated password."));
parser.addOption(upper);
QCommandLineOption numeric(QStringList() << "n",
QObject::tr("Use numbers in the generated password."));
parser.addOption(numeric);
QCommandLineOption special(QStringList() << "s",
QObject::tr("Use special characters in the generated password."));
parser.addOption(special);
QCommandLineOption extended(QStringList() << "e",
QObject::tr("Use extended ASCII in the generated password."));
parser.addOption(extended);
parser.process(arguments);
const QStringList args = parser.positionalArguments();
if (!args.isEmpty()) {
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli generate");
return EXIT_FAILURE;
}
PasswordGenerator passwordGenerator;
if (parser.value(len).isEmpty()) {
passwordGenerator.setLength(PasswordGenerator::DefaultLength);
} else {
int length = parser.value(len).toInt();
passwordGenerator.setLength(length);
}
PasswordGenerator::CharClasses classes = 0x0;
if (parser.isSet(lower)) {
classes |= PasswordGenerator::LowerLetters;
}
if (parser.isSet(upper)) {
classes |= PasswordGenerator::UpperLetters;
}
if (parser.isSet(numeric)) {
classes |= PasswordGenerator::Numbers;
}
if (parser.isSet(special)) {
classes |= PasswordGenerator::SpecialCharacters;
}
if (parser.isSet(extended)) {
classes |= PasswordGenerator::EASCII;
}
passwordGenerator.setCharClasses(classes);
passwordGenerator.setFlags(PasswordGenerator::DefaultFlags);
if (!passwordGenerator.isValid()) {
outputTextStream << parser.helpText().replace("keepassxc-cli", "keepassxc-cli generate");
return EXIT_FAILURE;
}
QString password = passwordGenerator.generatePassword();
outputTextStream << password << endl;
return EXIT_SUCCESS;
}

31
src/cli/Generate.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSXC_GENERATE_H
#define KEEPASSXC_GENERATE_H
#include "Command.h"
class Generate : public Command
{
public:
Generate();
~Generate();
int execute(const QStringList& arguments);
};
#endif // KEEPASSXC_GENERATE_H

View File

@ -29,15 +29,15 @@
List::List() List::List()
{ {
this->name = QString("ls"); name = QString("ls");
this->description = QObject::tr("List database entries."); description = QObject::tr("List database entries.");
} }
List::~List() List::~List()
{ {
} }
int List::execute(QStringList arguments) int List::execute(const QStringList& arguments)
{ {
QTextStream out(stdout); QTextStream out(stdout);

View File

@ -25,7 +25,7 @@ class List : public Command
public: public:
List(); List();
~List(); ~List();
int execute(QStringList arguments); int execute(const QStringList& arguments);
int listGroup(Database* database, QString groupPath = QString("")); int listGroup(Database* database, QString groupPath = QString(""));
}; };

View File

@ -31,15 +31,15 @@
Locate::Locate() Locate::Locate()
{ {
this->name = QString("locate"); name = QString("locate");
this->description = QObject::tr("Find entries quickly."); description = QObject::tr("Find entries quickly.");
} }
Locate::~Locate() Locate::~Locate()
{ {
} }
int Locate::execute(QStringList arguments) int Locate::execute(const QStringList& arguments)
{ {
QTextStream out(stdout); QTextStream out(stdout);

View File

@ -25,7 +25,7 @@ class Locate : public Command
public: public:
Locate(); Locate();
~Locate(); ~Locate();
int execute(QStringList arguments); int execute(const QStringList& arguments);
int locateEntry(Database* database, QString searchTerm); int locateEntry(Database* database, QString searchTerm);
}; };

View File

@ -26,15 +26,15 @@
Merge::Merge() Merge::Merge()
{ {
this->name = QString("merge"); name = QString("merge");
this->description = QObject::tr("Merge two databases."); description = QObject::tr("Merge two databases.");
} }
Merge::~Merge() Merge::~Merge()
{ {
} }
int Merge::execute(QStringList arguments) int Merge::execute(const QStringList& arguments)
{ {
QTextStream out(stdout); QTextStream out(stdout);

View File

@ -25,7 +25,7 @@ class Merge : public Command
public: public:
Merge(); Merge();
~Merge(); ~Merge();
int execute(QStringList arguments); int execute(const QStringList& arguments);
}; };
#endif // KEEPASSXC_MERGE_H #endif // KEEPASSXC_MERGE_H

View File

@ -34,15 +34,15 @@
Remove::Remove() Remove::Remove()
{ {
this->name = QString("rm"); name = QString("rm");
this->description = QString("Remove an entry from the database."); description = QString("Remove an entry from the database.");
} }
Remove::~Remove() Remove::~Remove()
{ {
} }
int Remove::execute(QStringList arguments) int Remove::execute(const QStringList& arguments)
{ {
QTextStream outputTextStream(stdout, QIODevice::WriteOnly); QTextStream outputTextStream(stdout, QIODevice::WriteOnly);

View File

@ -27,7 +27,7 @@ class Remove : public Command
public: public:
Remove(); Remove();
~Remove(); ~Remove();
int execute(QStringList arguments); int execute(const QStringList& arguments);
int removeEntry(Database* database, QString databasePath, QString entryPath); int removeEntry(Database* database, QString databasePath, QString entryPath);
}; };

View File

@ -29,15 +29,15 @@
Show::Show() Show::Show()
{ {
this->name = QString("show"); name = QString("show");
this->description = QObject::tr("Show an entry's information."); description = QObject::tr("Show an entry's information.");
} }
Show::~Show() Show::~Show()
{ {
} }
int Show::execute(QStringList arguments) int Show::execute(const QStringList& arguments)
{ {
QTextStream out(stdout); QTextStream out(stdout);

View File

@ -25,7 +25,7 @@ class Show : public Command
public: public:
Show(); Show();
~Show(); ~Show();
int execute(QStringList arguments); int execute(const QStringList& arguments);
int showEntry(Database* database, QStringList attributes, QString entryPath); int showEntry(Database* database, QStringList attributes, QString entryPath);
}; };

View File

@ -76,7 +76,7 @@ QString Utils::getPassword()
* A valid and running event loop is needed to use the global QClipboard, * A valid and running event loop is needed to use the global QClipboard,
* so we need to use this from the CLI. * so we need to use this from the CLI.
*/ */
int Utils::clipText(QString text) int Utils::clipText(const QString& text)
{ {
QString programName = ""; QString programName = "";

View File

@ -25,7 +25,7 @@ class Utils
public: public:
static void setStdinEcho(bool enable); static void setStdinEcho(bool enable);
static QString getPassword(); static QString getPassword();
static int clipText(QString text); static int clipText(const QString& text);
}; };
#endif // KEEPASSXC_UTILS_H #endif // KEEPASSXC_UTILS_H

View File

@ -1,4 +1,4 @@
.TH KEEPASSXC-CLI 1 "Aug 22, 2017" .TH KEEPASSXC-CLI 1 "Jan 19, 2018"
.SH NAME .SH NAME
keepassxc-cli \- command line interface for the \fBKeePassXC\fP password manager. keepassxc-cli \- command line interface for the \fBKeePassXC\fP password manager.
@ -19,6 +19,9 @@ Adds a new entry to a database. A password can be generated (\fI-g\fP option), o
.IP "clip [options] <database> <entry> [timeout]" .IP "clip [options] <database> <entry> [timeout]"
Copies the password of a database entry to the clipboard. If multiple entries with the same name exist in different groups, only the password for the first one is going to be copied. For copying the password of an entry in a specific group, the group path to the entry should be specified as well, instead of just the name. Optionally, a timeout in seconds can be specified to automatically clear the clipboard. Copies the password of a database entry to the clipboard. If multiple entries with the same name exist in different groups, only the password for the first one is going to be copied. For copying the password of an entry in a specific group, the group path to the entry should be specified as well, instead of just the name. Optionally, a timeout in seconds can be specified to automatically clear the clipboard.
.IP "diceware [options]"
Generate a random diceware passphrase.
.IP "edit [options] <database> <entry>" .IP "edit [options] <database> <entry>"
Edits a database entry. A password can be generated (\fI-g\fP option), or a prompt can be displayed to input the password (\fI-p\fP option). Edits a database entry. A password can be generated (\fI-g\fP option), or a prompt can be displayed to input the password (\fI-p\fP option).
@ -28,6 +31,9 @@ Estimates the entropy of a password. The password to estimate can be provided as
.IP "extract [options] <database>" .IP "extract [options] <database>"
Extracts and prints the contents of a database to standard output in XML format. Extracts and prints the contents of a database to standard output in XML format.
.IP "generate [options]"
Generate a random password.
.IP "locate [options] <database> <term>" .IP "locate [options] <database> <term>"
Locates all the entries that match a specific search term in a database. Locates all the entries that match a specific search term in a database.
@ -104,6 +110,39 @@ with each attribute shown one-per-line in the given order. If no attributes are
specified, a summary of the default attributes is given. specified, a summary of the default attributes is given.
.SS "Diceware options"
.IP "-W, --words <count>"
Desired number of words for the generated passphrase. [Default: 7]
.IP "-w, --word-list <path>"
Path of the wordlist for the diceware generator. The wordlist must have > 1000 words,
otherwise the program will fail. If the wordlist has < 4000 words a warning will
be printed to STDERR.
.SS "Generate options"
.IP "-L, --length <length>"
Desired length for the generated password. [Default: 16]
.IP "-l"
Use lowercase characters for the generated password. [Default: Enabled]
.IP "-u"
Use uppercase characters for the generated password. [Default: Enabled]
.IP "-n"
Use numbers characters for the generated password. [Default: Enabled]
.IP "-s"
Use special characters for the generated password. [Default: Disabled]
.IP "-e"
Use extended ASCII characters for the generated password. [Default: Disabled]
.SH REPORTING BUGS .SH REPORTING BUGS
Bugs and feature requests can be reported on GitHub at https://github.com/keepassxreboot/keepassxc/issues. Bugs and feature requests can be reported on GitHub at https://github.com/keepassxreboot/keepassxc/issues.

View File

@ -91,6 +91,11 @@ QString FilePath::pluginPath(const QString& name)
return QString(); return QString();
} }
QString FilePath::wordlistPath(const QString& name)
{
return m_instance->dataPath("wordlists/" + name);
}
QIcon FilePath::applicationIcon() QIcon FilePath::applicationIcon()
{ {
bool darkIcon = useDarkIcon(); bool darkIcon = useDarkIcon();

View File

@ -27,6 +27,7 @@ class FilePath
public: public:
QString dataPath(const QString& name); QString dataPath(const QString& name);
QString pluginPath(const QString& name); QString pluginPath(const QString& name);
QString wordlistPath(const QString& name);
QIcon applicationIcon(); QIcon applicationIcon();
QIcon trayIconLocked(); QIcon trayIconLocked();
QIcon trayIconUnlocked(); QIcon trayIconUnlocked();

View File

@ -24,9 +24,12 @@
#include "crypto/Random.h" #include "crypto/Random.h"
#include "core/FilePath.h" #include "core/FilePath.h"
const QString PassphraseGenerator::DefaultSeparator = " ";
const QString PassphraseGenerator::DefaultWordList = "eff_large.wordlist";
PassphraseGenerator::PassphraseGenerator() PassphraseGenerator::PassphraseGenerator()
: m_wordCount(0) : m_wordCount(0)
, m_separator(' ') , m_separator(PassphraseGenerator::DefaultSeparator)
{ {
} }
@ -48,7 +51,7 @@ void PassphraseGenerator::setWordCount(int wordCount)
m_wordCount = wordCount; m_wordCount = wordCount;
} else { } else {
// safe default if something goes wrong // safe default if something goes wrong
m_wordCount = 7; m_wordCount = DefaultWordCount;
} }
} }
@ -76,7 +79,7 @@ void PassphraseGenerator::setWordList(QString path)
void PassphraseGenerator::setDefaultWordList() void PassphraseGenerator::setDefaultWordList()
{ {
const QString path = filePath()->dataPath("wordlists/eff_large.wordlist"); const QString path = filePath()->wordlistPath(PassphraseGenerator::DefaultWordList);
setWordList(path); setWordList(path);
} }

View File

@ -36,6 +36,10 @@ public:
QString generatePassphrase() const; QString generatePassphrase() const;
static const int DefaultWordCount = 7;
static const QString DefaultSeparator;
static const QString DefaultWordList;
private: private:
int m_wordCount; int m_wordCount;
QString m_separator; QString m_separator;

View File

@ -35,11 +35,19 @@ double PasswordGenerator::calculateEntropy(QString password)
void PasswordGenerator::setLength(int length) void PasswordGenerator::setLength(int length)
{ {
if (length <= 0) {
m_length = DefaultLength;
return;
}
m_length = length; m_length = length;
} }
void PasswordGenerator::setCharClasses(const CharClasses& classes) void PasswordGenerator::setCharClasses(const CharClasses& classes)
{ {
if (classes == 0) {
m_classes = DefaultCharset;
return;
}
m_classes = classes; m_classes = classes;
} }

View File

@ -34,14 +34,16 @@ public:
UpperLetters = 0x2, UpperLetters = 0x2,
Numbers = 0x4, Numbers = 0x4,
SpecialCharacters = 0x8, SpecialCharacters = 0x8,
EASCII = 0x10 EASCII = 0x10,
DefaultCharset = LowerLetters | UpperLetters | Numbers
}; };
Q_DECLARE_FLAGS(CharClasses, CharClass) Q_DECLARE_FLAGS(CharClasses, CharClass)
enum GeneratorFlag enum GeneratorFlag
{ {
ExcludeLookAlike = 0x1, ExcludeLookAlike = 0x1,
CharFromEveryGroup = 0x2 CharFromEveryGroup = 0x2,
DefaultFlags = ExcludeLookAlike | CharFromEveryGroup
}; };
Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag) Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag)
@ -59,6 +61,13 @@ public:
int getbits() const; int getbits() const;
static const int DefaultLength = 16; static const int DefaultLength = 16;
static constexpr bool DefaultLower = (DefaultCharset & LowerLetters) != 0;
static constexpr bool DefaultUpper = (DefaultCharset & UpperLetters) != 0;
static constexpr bool DefaultNumbers = (DefaultCharset & Numbers) != 0;
static constexpr bool DefaultSpecial = (DefaultCharset & SpecialCharacters) != 0;
static constexpr bool DefaultEASCII = (DefaultCharset & EASCII) != 0;
static constexpr bool DefaultLookAlike = (DefaultFlags & ExcludeLookAlike) != 0;
static constexpr bool DefaultFromEveryGroup = (DefaultFlags & CharFromEveryGroup) != 0;
private: private:
QVector<PasswordGroup> passwordGroups() const; QVector<PasswordGroup> passwordGroups() const;

View File

@ -68,9 +68,9 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
} }
// set default separator to Space // set default separator to Space
m_ui->editWordSeparator->setText(" "); m_ui->editWordSeparator->setText(PassphraseGenerator::DefaultSeparator);
QDir path(filePath()->dataPath("wordlists/")); QDir path(filePath()->wordlistPath(""));
QStringList files = path.entryList(QDir::Files); QStringList files = path.entryList(QDir::Files);
m_ui->comboBoxWordList->addItems(files); m_ui->comboBoxWordList->addItems(files);
if (files.size() > 1) { if (files.size() > 1) {
@ -93,19 +93,19 @@ PasswordGeneratorWidget::~PasswordGeneratorWidget()
void PasswordGeneratorWidget::loadSettings() void PasswordGeneratorWidget::loadSettings()
{ {
// Password config // Password config
m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", true).toBool()); m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", PasswordGenerator::DefaultLower).toBool());
m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", true).toBool()); m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", PasswordGenerator::DefaultUpper).toBool());
m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", true).toBool()); m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool());
m_ui->checkBoxSpecialChars->setChecked(config()->get("generator/SpecialChars", false).toBool()); m_ui->checkBoxSpecialChars->setChecked(config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool());
m_ui->checkBoxExtASCII->setChecked(config()->get("generator/EASCII", false).toBool()); m_ui->checkBoxExtASCII->setChecked(config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool());
m_ui->checkBoxExcludeAlike->setChecked(config()->get("generator/ExcludeAlike", true).toBool()); m_ui->checkBoxExcludeAlike->setChecked(config()->get("generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool());
m_ui->checkBoxEnsureEvery->setChecked(config()->get("generator/EnsureEvery", true).toBool()); m_ui->checkBoxEnsureEvery->setChecked(config()->get("generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool());
m_ui->spinBoxLength->setValue(config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt()); m_ui->spinBoxLength->setValue(config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt());
// Diceware config // Diceware config
m_ui->spinBoxWordCount->setValue(config()->get("generator/WordCount", 6).toInt()); m_ui->spinBoxWordCount->setValue(config()->get("generator/WordCount", PassphraseGenerator::DefaultWordCount).toInt());
m_ui->editWordSeparator->setText(config()->get("generator/WordSeparator", " ").toString()); m_ui->editWordSeparator->setText(config()->get("generator/WordSeparator", PassphraseGenerator::DefaultSeparator).toString());
m_ui->comboBoxWordList->setCurrentText(config()->get("generator/WordList", "eff_large.wordlist").toString()); m_ui->comboBoxWordList->setCurrentText(config()->get("generator/WordList", PassphraseGenerator::DefaultWordList).toString());
// Password or diceware? // Password or diceware?
m_ui->tabWidget->setCurrentIndex(config()->get("generator/Type", 0).toInt()); m_ui->tabWidget->setCurrentIndex(config()->get("generator/Type", 0).toInt());
@ -394,7 +394,7 @@ void PasswordGeneratorWidget::updateGenerator()
m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value()); m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value());
if (!m_ui->comboBoxWordList->currentText().isEmpty()) { if (!m_ui->comboBoxWordList->currentText().isEmpty()) {
QString path = filePath()->dataPath("wordlists/" + m_ui->comboBoxWordList->currentText()); QString path = filePath()->wordlistPath(m_ui->comboBoxWordList->currentText());
m_dicewareGenerator->setWordList(path); m_dicewareGenerator->setWordList(path);
} }
m_dicewareGenerator->setWordSeparator(m_ui->editWordSeparator->text()); m_dicewareGenerator->setWordSeparator(m_ui->editWordSeparator->text());

View File

@ -48,13 +48,14 @@ HttpPasswordGeneratorWidget::~HttpPasswordGeneratorWidget()
void HttpPasswordGeneratorWidget::loadSettings() void HttpPasswordGeneratorWidget::loadSettings()
{ {
m_ui->checkBoxLower->setChecked(config()->get("Http/generator/LowerCase", true).toBool()); m_ui->checkBoxLower->setChecked(config()->get("Http/generator/LowerCase", PasswordGenerator::DefaultLower).toBool());
m_ui->checkBoxUpper->setChecked(config()->get("Http/generator/UpperCase", true).toBool()); m_ui->checkBoxUpper->setChecked(config()->get("Http/generator/UpperCase", PasswordGenerator::DefaultUpper).toBool());
m_ui->checkBoxNumbers->setChecked(config()->get("Http/generator/Numbers", true).toBool()); m_ui->checkBoxNumbers->setChecked(config()->get("Http/generator/Numbers", PasswordGenerator::DefaultNumbers).toBool());
m_ui->checkBoxSpecialChars->setChecked(config()->get("Http/generator/SpecialChars", false).toBool()); m_ui->checkBoxSpecialChars->setChecked(config()->get("Http/generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool());
m_ui->checkBoxSpecialChars->setChecked(config()->get("Http/generator/EASCII", PasswordGenerator::DefaultEASCII).toBool());
m_ui->checkBoxExcludeAlike->setChecked(config()->get("Http/generator/ExcludeAlike", true).toBool()); m_ui->checkBoxExcludeAlike->setChecked(config()->get("Http/generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool());
m_ui->checkBoxEnsureEvery->setChecked(config()->get("Http/generator/EnsureEvery", true).toBool()); m_ui->checkBoxEnsureEvery->setChecked(config()->get("Http/generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool());
m_ui->spinBoxLength->setValue(config()->get("Http/generator/Length", PasswordGenerator::DefaultLength).toInt()); m_ui->spinBoxLength->setValue(config()->get("Http/generator/Length", PasswordGenerator::DefaultLength).toInt());
} }
@ -65,6 +66,7 @@ void HttpPasswordGeneratorWidget::saveSettings()
config()->set("Http/generator/UpperCase", m_ui->checkBoxUpper->isChecked()); config()->set("Http/generator/UpperCase", m_ui->checkBoxUpper->isChecked());
config()->set("Http/generator/Numbers", m_ui->checkBoxNumbers->isChecked()); config()->set("Http/generator/Numbers", m_ui->checkBoxNumbers->isChecked());
config()->set("Http/generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked()); config()->set("Http/generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked());
config()->set("Http/generator/EASCII", m_ui->checkBoxExtASCII->isChecked());
config()->set("Http/generator/ExcludeAlike", m_ui->checkBoxExcludeAlike->isChecked()); config()->set("Http/generator/ExcludeAlike", m_ui->checkBoxExcludeAlike->isChecked());
config()->set("Http/generator/EnsureEvery", m_ui->checkBoxEnsureEvery->isChecked()); config()->set("Http/generator/EnsureEvery", m_ui->checkBoxEnsureEvery->isChecked());
@ -120,6 +122,10 @@ PasswordGenerator::CharClasses HttpPasswordGeneratorWidget::charClasses()
classes |= PasswordGenerator::SpecialCharacters; classes |= PasswordGenerator::SpecialCharacters;
} }
if (m_ui->checkBoxExtASCII->isChecked()) {
classes |= PasswordGenerator::EASCII;
}
return classes; return classes;
} }

View File

@ -142,6 +142,22 @@
</attribute> </attribute>
</widget> </widget>
</item> </item>
<item>
<widget class="QToolButton" name="checkBoxExtASCII">
<property name="toolTip">
<string>Extended ASCII</string>
</property>
<property name="text">
<string>Extended ASCII</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">optionButtons</string>
</attribute>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">

View File

@ -145,7 +145,7 @@ void HttpSettings::setHttpPort(int port)
bool HttpSettings::passwordUseNumbers() bool HttpSettings::passwordUseNumbers()
{ {
return config()->get("Http/generator/Numbers", true).toBool(); return config()->get("Http/generator/Numbers", PasswordGenerator::DefaultNumbers).toBool();
} }
void HttpSettings::setPasswordUseNumbers(bool useNumbers) void HttpSettings::setPasswordUseNumbers(bool useNumbers)
@ -155,7 +155,7 @@ void HttpSettings::setPasswordUseNumbers(bool useNumbers)
bool HttpSettings::passwordUseLowercase() bool HttpSettings::passwordUseLowercase()
{ {
return config()->get("Http/generator/LowerCase", true).toBool(); return config()->get("Http/generator/LowerCase", PasswordGenerator::DefaultLower).toBool();
} }
void HttpSettings::setPasswordUseLowercase(bool useLowercase) void HttpSettings::setPasswordUseLowercase(bool useLowercase)
@ -165,7 +165,7 @@ void HttpSettings::setPasswordUseLowercase(bool useLowercase)
bool HttpSettings::passwordUseUppercase() bool HttpSettings::passwordUseUppercase()
{ {
return config()->get("Http/generator/UpperCase", true).toBool(); return config()->get("Http/generator/UpperCase", PasswordGenerator::DefaultUpper).toBool();
} }
void HttpSettings::setPasswordUseUppercase(bool useUppercase) void HttpSettings::setPasswordUseUppercase(bool useUppercase)
@ -175,7 +175,7 @@ void HttpSettings::setPasswordUseUppercase(bool useUppercase)
bool HttpSettings::passwordUseSpecial() bool HttpSettings::passwordUseSpecial()
{ {
return config()->get("Http/generator/SpecialChars", false).toBool(); return config()->get("Http/generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool();
} }
void HttpSettings::setPasswordUseSpecial(bool useSpecial) void HttpSettings::setPasswordUseSpecial(bool useSpecial)
@ -183,9 +183,19 @@ void HttpSettings::setPasswordUseSpecial(bool useSpecial)
config()->set("Http/generator/SpecialChars", useSpecial); config()->set("Http/generator/SpecialChars", useSpecial);
} }
bool HttpSettings::passwordUseEASCII()
{
return config()->get("Http/generator/EASCII", PasswordGenerator::DefaultEASCII).toBool();
}
void HttpSettings::setPasswordUseEASCII(bool useExtended)
{
config()->set("Http/generator/EASCII", useExtended);
}
bool HttpSettings::passwordEveryGroup() bool HttpSettings::passwordEveryGroup()
{ {
return config()->get("Http/generator/EnsureEvery", true).toBool(); return config()->get("Http/generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool();
} }
void HttpSettings::setPasswordEveryGroup(bool everyGroup) void HttpSettings::setPasswordEveryGroup(bool everyGroup)
@ -195,7 +205,7 @@ void HttpSettings::setPasswordEveryGroup(bool everyGroup)
bool HttpSettings::passwordExcludeAlike() bool HttpSettings::passwordExcludeAlike()
{ {
return config()->get("Http/generator/ExcludeAlike", true).toBool(); return config()->get("Http/generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool();
} }
void HttpSettings::setPasswordExcludeAlike(bool excludeAlike) void HttpSettings::setPasswordExcludeAlike(bool excludeAlike)
@ -205,7 +215,7 @@ void HttpSettings::setPasswordExcludeAlike(bool excludeAlike)
int HttpSettings::passwordLength() int HttpSettings::passwordLength()
{ {
return config()->get("Http/generator/Length", 20).toInt(); return config()->get("Http/generator/Length", PasswordGenerator::DefaultLength).toInt();
} }
void HttpSettings::setPasswordLength(int length) void HttpSettings::setPasswordLength(int length)
@ -217,14 +227,21 @@ void HttpSettings::setPasswordLength(int length)
PasswordGenerator::CharClasses HttpSettings::passwordCharClasses() PasswordGenerator::CharClasses HttpSettings::passwordCharClasses()
{ {
PasswordGenerator::CharClasses classes; PasswordGenerator::CharClasses classes;
if (passwordUseLowercase()) if (passwordUseLowercase()) {
classes |= PasswordGenerator::LowerLetters; classes |= PasswordGenerator::LowerLetters;
if (passwordUseUppercase()) }
if (passwordUseUppercase()) {
classes |= PasswordGenerator::UpperLetters; classes |= PasswordGenerator::UpperLetters;
if (passwordUseNumbers()) }
if (passwordUseNumbers()) {
classes |= PasswordGenerator::Numbers; classes |= PasswordGenerator::Numbers;
if (passwordUseSpecial()) }
if (passwordUseSpecial()) {
classes |= PasswordGenerator::SpecialCharacters; classes |= PasswordGenerator::SpecialCharacters;
}
if (passwordUseEASCII()) {
classes |= PasswordGenerator::EASCII;
}
return classes; return classes;
} }

View File

@ -58,6 +58,8 @@ public:
static void setPasswordUseUppercase(bool useUppercase); static void setPasswordUseUppercase(bool useUppercase);
static bool passwordUseSpecial(); static bool passwordUseSpecial();
static void setPasswordUseSpecial(bool useSpecial); static void setPasswordUseSpecial(bool useSpecial);
static bool passwordUseEASCII();
static void setPasswordUseEASCII(bool useExtended);
static bool passwordEveryGroup(); static bool passwordEveryGroup();
static void setPasswordEveryGroup(bool everyGroup); static void setPasswordEveryGroup(bool everyGroup);
static bool passwordExcludeAlike(); static bool passwordExcludeAlike();