diff --git a/src/browser/BrowserSettings.cpp b/src/browser/BrowserSettings.cpp index 2df7fc1c5..ecaf8e23e 100755 --- a/src/browser/BrowserSettings.cpp +++ b/src/browser/BrowserSettings.cpp @@ -211,7 +211,7 @@ void BrowserSettings::setVivaldiSupport(bool enabled) { bool BrowserSettings::passwordUseNumbers() { - return config()->get("generator/Numbers", true).toBool(); + return config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool(); } void BrowserSettings::setPasswordUseNumbers(bool useNumbers) @@ -221,7 +221,7 @@ void BrowserSettings::setPasswordUseNumbers(bool useNumbers) bool BrowserSettings::passwordUseLowercase() { - return config()->get("generator/LowerCase", true).toBool(); + return config()->get("generator/LowerCase", PasswordGenerator::DefaultLower).toBool(); } void BrowserSettings::setPasswordUseLowercase(bool useLowercase) @@ -231,7 +231,7 @@ void BrowserSettings::setPasswordUseLowercase(bool useLowercase) bool BrowserSettings::passwordUseUppercase() { - return config()->get("generator/UpperCase", true).toBool(); + return config()->get("generator/UpperCase", PasswordGenerator::DefaultUpper).toBool(); } void BrowserSettings::setPasswordUseUppercase(bool useUppercase) @@ -241,7 +241,7 @@ void BrowserSettings::setPasswordUseUppercase(bool useUppercase) bool BrowserSettings::passwordUseSpecial() { - return config()->get("generator/SpecialChars", false).toBool(); + return config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool(); } void BrowserSettings::setPasswordUseSpecial(bool useSpecial) @@ -251,7 +251,7 @@ void BrowserSettings::setPasswordUseSpecial(bool useSpecial) bool BrowserSettings::passwordUseEASCII() { - return config()->get("generator/EASCII", false).toBool(); + return config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool(); } void BrowserSettings::setPasswordUseEASCII(bool useEASCII) @@ -261,7 +261,7 @@ void BrowserSettings::setPasswordUseEASCII(bool useEASCII) int BrowserSettings::passPhraseWordCount() { - return config()->get("generator/WordCount", 6).toInt(); + return config()->get("generator/WordCount", PassphraseGenerator::DefaultWordCount).toInt(); } void BrowserSettings::setPassPhraseWordCount(int wordCount) @@ -271,7 +271,7 @@ void BrowserSettings::setPassPhraseWordCount(int wordCount) QString BrowserSettings::passPhraseWordSeparator() { - return config()->get("generator/WordSeparator", " ").toString(); + return config()->get("generator/WordSeparator", PassphraseGenerator::DefaultSeparator).toString(); } void BrowserSettings::setPassPhraseWordSeparator(QString separator) @@ -291,7 +291,7 @@ void BrowserSettings::setGeneratorType(int type) bool BrowserSettings::passwordEveryGroup() { - return config()->get("generator/EnsureEvery", true).toBool(); + return config()->get("generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool(); } void BrowserSettings::setPasswordEveryGroup(bool everyGroup) @@ -301,7 +301,7 @@ void BrowserSettings::setPasswordEveryGroup(bool everyGroup) bool BrowserSettings::passwordExcludeAlike() { - return config()->get("generator/ExcludeAlike", true).toBool(); + return config()->get("generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool(); } void BrowserSettings::setPasswordExcludeAlike(bool excludeAlike) @@ -311,7 +311,7 @@ void BrowserSettings::setPasswordExcludeAlike(bool excludeAlike) int BrowserSettings::passwordLength() { - return config()->get("generator/Length", 20).toInt(); + return config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt(); } void BrowserSettings::setPasswordLength(int length) diff --git a/src/cli/Add.cpp b/src/cli/Add.cpp index 13023b5bb..5c97299b8 100644 --- a/src/cli/Add.cpp +++ b/src/cli/Add.cpp @@ -31,15 +31,15 @@ Add::Add() { - this->name = QString("add"); - this->description = QObject::tr("Add a new entry to a database."); + name = QString("add"); + description = QObject::tr("Add a new entry to a database."); } Add::~Add() { } -int Add::execute(QStringList arguments) +int Add::execute(const QStringList& arguments) { QTextStream inputTextStream(stdin, QIODevice::ReadOnly); @@ -133,8 +133,8 @@ int Add::execute(QStringList arguments) passwordGenerator.setLength(passwordLength.toInt()); } - passwordGenerator.setCharClasses(PasswordGenerator::LowerLetters | PasswordGenerator::UpperLetters | - PasswordGenerator::Numbers); + passwordGenerator.setCharClasses(PasswordGenerator::DefaultCharset); + passwordGenerator.setFlags(PasswordGenerator::DefaultFlags); QString password = passwordGenerator.generatePassword(); entry->setPassword(password); } diff --git a/src/cli/Add.h b/src/cli/Add.h index 14356c418..5769249c9 100644 --- a/src/cli/Add.h +++ b/src/cli/Add.h @@ -25,7 +25,7 @@ class Add : public Command public: Add(); ~Add(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); }; #endif // KEEPASSXC_ADD_H diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 225ce47dc..a5126f999 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -20,12 +20,16 @@ set(cli_SOURCES Clip.h Command.cpp Command.h + Diceware.cpp + Diceware.h Edit.cpp Edit.h Estimate.cpp Estimate.h Extract.cpp Extract.h + Generate.cpp + Generate.h List.cpp List.h Locate.cpp diff --git a/src/cli/Clip.cpp b/src/cli/Clip.cpp index 6b458a673..886f8ecc7 100644 --- a/src/cli/Clip.cpp +++ b/src/cli/Clip.cpp @@ -32,15 +32,15 @@ Clip::Clip() { - this->name = QString("clip"); - this->description = QObject::tr("Copy an entry's password to the clipboard."); + name = QString("clip"); + description = QObject::tr("Copy an entry's password to the clipboard."); } Clip::~Clip() { } -int Clip::execute(QStringList arguments) +int Clip::execute(const QStringList& arguments) { QTextStream out(stdout); diff --git a/src/cli/Clip.h b/src/cli/Clip.h index a9e24faee..e94231236 100644 --- a/src/cli/Clip.h +++ b/src/cli/Clip.h @@ -25,7 +25,7 @@ class Clip : public Command public: Clip(); ~Clip(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); int clipEntry(Database* database, QString entryPath, QString timeout); }; diff --git a/src/cli/Command.cpp b/src/cli/Command.cpp index 6ec07b7af..ef6948888 100644 --- a/src/cli/Command.cpp +++ b/src/cli/Command.cpp @@ -24,9 +24,11 @@ #include "Add.h" #include "Clip.h" +#include "Diceware.h" #include "Edit.h" #include "Estimate.h" #include "Extract.h" +#include "Generate.h" #include "List.h" #include "Locate.h" #include "Merge.h" @@ -39,7 +41,7 @@ Command::~Command() { } -int Command::execute(QStringList) +int Command::execute(const QStringList&) { return EXIT_FAILURE; } @@ -61,9 +63,11 @@ void populateCommands() if (commands.isEmpty()) { commands.insert(QString("add"), new Add()); commands.insert(QString("clip"), new Clip()); + commands.insert(QString("diceware"), new Diceware()); commands.insert(QString("edit"), new Edit()); commands.insert(QString("estimate"), new Estimate()); commands.insert(QString("extract"), new Extract()); + commands.insert(QString("generate"), new Generate()); commands.insert(QString("locate"), new Locate()); commands.insert(QString("ls"), new List()); commands.insert(QString("merge"), new Merge()); diff --git a/src/cli/Command.h b/src/cli/Command.h index b751c4a8e..2ebdd77b9 100644 --- a/src/cli/Command.h +++ b/src/cli/Command.h @@ -29,7 +29,7 @@ class Command { public: virtual ~Command(); - virtual int execute(QStringList arguments); + virtual int execute(const QStringList& arguments); QString name; QString description; QString getDescriptionLine(); diff --git a/src/cli/Diceware.cpp b/src/cli/Diceware.cpp new file mode 100644 index 000000000..c71b57d7e --- /dev/null +++ b/src/cli/Diceware.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * 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 . + */ + +#include +#include + +#include "Diceware.h" + +#include +#include + +#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; +} diff --git a/src/cli/Diceware.h b/src/cli/Diceware.h new file mode 100644 index 000000000..61fe724ca --- /dev/null +++ b/src/cli/Diceware.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * 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 . + */ + +#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 diff --git a/src/cli/Edit.cpp b/src/cli/Edit.cpp index 25d2fd456..967ddd8ed 100644 --- a/src/cli/Edit.cpp +++ b/src/cli/Edit.cpp @@ -31,15 +31,15 @@ Edit::Edit() { - this->name = QString("edit"); - this->description = QObject::tr("Edit an entry."); + name = QString("edit"); + description = QObject::tr("Edit an entry."); } Edit::~Edit() { } -int Edit::execute(QStringList arguments) +int Edit::execute(const QStringList& arguments) { QTextStream inputTextStream(stdin, QIODevice::ReadOnly); @@ -149,8 +149,8 @@ int Edit::execute(QStringList arguments) passwordGenerator.setLength(passwordLength.toInt()); } - passwordGenerator.setCharClasses(PasswordGenerator::LowerLetters | PasswordGenerator::UpperLetters | - PasswordGenerator::Numbers); + passwordGenerator.setCharClasses(PasswordGenerator::DefaultCharset); + passwordGenerator.setFlags(PasswordGenerator::DefaultFlags); QString password = passwordGenerator.generatePassword(); entry->setPassword(password); } diff --git a/src/cli/Edit.h b/src/cli/Edit.h index e52069ff0..2c413bea0 100644 --- a/src/cli/Edit.h +++ b/src/cli/Edit.h @@ -25,7 +25,7 @@ class Edit : public Command public: Edit(); ~Edit(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); }; #endif // KEEPASSXC_EDIT_H diff --git a/src/cli/Estimate.cpp b/src/cli/Estimate.cpp index 80226a27e..9a2ab0b0f 100644 --- a/src/cli/Estimate.cpp +++ b/src/cli/Estimate.cpp @@ -34,8 +34,8 @@ Estimate::Estimate() { - this->name = QString("estimate"); - this->description = QObject::tr("Estimate the entropy of a password."); + name = QString("estimate"); + description = QObject::tr("Estimate the entropy of a password."); } 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 outputTextStream(stdout, QIODevice::WriteOnly); diff --git a/src/cli/Estimate.h b/src/cli/Estimate.h index 2cbe49104..15f922752 100644 --- a/src/cli/Estimate.h +++ b/src/cli/Estimate.h @@ -25,7 +25,7 @@ class Estimate : public Command public: Estimate(); ~Estimate(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); }; #endif // KEEPASSXC_ESTIMATE_H diff --git a/src/cli/Extract.cpp b/src/cli/Extract.cpp index 477f2b0e2..b48d5a6aa 100644 --- a/src/cli/Extract.cpp +++ b/src/cli/Extract.cpp @@ -33,15 +33,15 @@ Extract::Extract() { - this->name = QString("extract"); - this->description = QObject::tr("Extract and print the content of a database."); + name = QString("extract"); + description = QObject::tr("Extract and print the content of a database."); } Extract::~Extract() { } -int Extract::execute(QStringList arguments) +int Extract::execute(const QStringList& arguments) { QTextStream out(stdout); QTextStream errorTextStream(stderr); diff --git a/src/cli/Extract.h b/src/cli/Extract.h index bef6a7821..2939afddb 100644 --- a/src/cli/Extract.h +++ b/src/cli/Extract.h @@ -25,7 +25,7 @@ class Extract : public Command public: Extract(); ~Extract(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); }; #endif // KEEPASSXC_EXTRACT_H diff --git a/src/cli/Generate.cpp b/src/cli/Generate.cpp new file mode 100644 index 000000000..eb8fea5e8 --- /dev/null +++ b/src/cli/Generate.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * 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 . + */ + +#include +#include + +#include "Generate.h" + +#include +#include + +#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; +} diff --git a/src/cli/Generate.h b/src/cli/Generate.h new file mode 100644 index 000000000..607fc105c --- /dev/null +++ b/src/cli/Generate.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * 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 . + */ + +#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 diff --git a/src/cli/List.cpp b/src/cli/List.cpp index 73830cab8..bdedaf210 100644 --- a/src/cli/List.cpp +++ b/src/cli/List.cpp @@ -29,15 +29,15 @@ List::List() { - this->name = QString("ls"); - this->description = QObject::tr("List database entries."); + name = QString("ls"); + description = QObject::tr("List database entries."); } List::~List() { } -int List::execute(QStringList arguments) +int List::execute(const QStringList& arguments) { QTextStream out(stdout); diff --git a/src/cli/List.h b/src/cli/List.h index d12105f3c..98b8b5a45 100644 --- a/src/cli/List.h +++ b/src/cli/List.h @@ -25,7 +25,7 @@ class List : public Command public: List(); ~List(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); int listGroup(Database* database, QString groupPath = QString("")); }; diff --git a/src/cli/Locate.cpp b/src/cli/Locate.cpp index 83a3c5ce0..f80372885 100644 --- a/src/cli/Locate.cpp +++ b/src/cli/Locate.cpp @@ -31,15 +31,15 @@ Locate::Locate() { - this->name = QString("locate"); - this->description = QObject::tr("Find entries quickly."); + name = QString("locate"); + description = QObject::tr("Find entries quickly."); } Locate::~Locate() { } -int Locate::execute(QStringList arguments) +int Locate::execute(const QStringList& arguments) { QTextStream out(stdout); diff --git a/src/cli/Locate.h b/src/cli/Locate.h index c919b0cb3..3677a034d 100644 --- a/src/cli/Locate.h +++ b/src/cli/Locate.h @@ -25,7 +25,7 @@ class Locate : public Command public: Locate(); ~Locate(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); int locateEntry(Database* database, QString searchTerm); }; diff --git a/src/cli/Merge.cpp b/src/cli/Merge.cpp index 5df6b0188..6b114bff3 100644 --- a/src/cli/Merge.cpp +++ b/src/cli/Merge.cpp @@ -26,15 +26,15 @@ Merge::Merge() { - this->name = QString("merge"); - this->description = QObject::tr("Merge two databases."); + name = QString("merge"); + description = QObject::tr("Merge two databases."); } Merge::~Merge() { } -int Merge::execute(QStringList arguments) +int Merge::execute(const QStringList& arguments) { QTextStream out(stdout); diff --git a/src/cli/Merge.h b/src/cli/Merge.h index 4f0b42836..496c66b86 100644 --- a/src/cli/Merge.h +++ b/src/cli/Merge.h @@ -25,7 +25,7 @@ class Merge : public Command public: Merge(); ~Merge(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); }; #endif // KEEPASSXC_MERGE_H diff --git a/src/cli/Remove.cpp b/src/cli/Remove.cpp index 6abb68f1c..64a5976e9 100644 --- a/src/cli/Remove.cpp +++ b/src/cli/Remove.cpp @@ -34,15 +34,15 @@ Remove::Remove() { - this->name = QString("rm"); - this->description = QString("Remove an entry from the database."); + name = QString("rm"); + description = QString("Remove an entry from the database."); } Remove::~Remove() { } -int Remove::execute(QStringList arguments) +int Remove::execute(const QStringList& arguments) { QTextStream outputTextStream(stdout, QIODevice::WriteOnly); diff --git a/src/cli/Remove.h b/src/cli/Remove.h index 2440c201c..5465530ed 100644 --- a/src/cli/Remove.h +++ b/src/cli/Remove.h @@ -27,7 +27,7 @@ class Remove : public Command public: Remove(); ~Remove(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); int removeEntry(Database* database, QString databasePath, QString entryPath); }; diff --git a/src/cli/Show.cpp b/src/cli/Show.cpp index 66225c56a..54561b1f7 100644 --- a/src/cli/Show.cpp +++ b/src/cli/Show.cpp @@ -29,15 +29,15 @@ Show::Show() { - this->name = QString("show"); - this->description = QObject::tr("Show an entry's information."); + name = QString("show"); + description = QObject::tr("Show an entry's information."); } Show::~Show() { } -int Show::execute(QStringList arguments) +int Show::execute(const QStringList& arguments) { QTextStream out(stdout); diff --git a/src/cli/Show.h b/src/cli/Show.h index f2caefdbf..18b6d7049 100644 --- a/src/cli/Show.h +++ b/src/cli/Show.h @@ -25,7 +25,7 @@ class Show : public Command public: Show(); ~Show(); - int execute(QStringList arguments); + int execute(const QStringList& arguments); int showEntry(Database* database, QStringList attributes, QString entryPath); }; diff --git a/src/cli/Utils.cpp b/src/cli/Utils.cpp index f42095cbb..35e7cce38 100644 --- a/src/cli/Utils.cpp +++ b/src/cli/Utils.cpp @@ -76,7 +76,7 @@ QString Utils::getPassword() * A valid and running event loop is needed to use the global QClipboard, * so we need to use this from the CLI. */ -int Utils::clipText(QString text) +int Utils::clipText(const QString& text) { QString programName = ""; diff --git a/src/cli/Utils.h b/src/cli/Utils.h index 0c6b749a3..1f8051183 100644 --- a/src/cli/Utils.h +++ b/src/cli/Utils.h @@ -25,7 +25,7 @@ class Utils public: static void setStdinEcho(bool enable); static QString getPassword(); - static int clipText(QString text); + static int clipText(const QString& text); }; #endif // KEEPASSXC_UTILS_H diff --git a/src/cli/keepassxc-cli.1 b/src/cli/keepassxc-cli.1 index a9145b27e..cc1e7b8d7 100644 --- a/src/cli/keepassxc-cli.1 +++ b/src/cli/keepassxc-cli.1 @@ -1,4 +1,4 @@ -.TH KEEPASSXC-CLI 1 "Aug 22, 2017" +.TH KEEPASSXC-CLI 1 "Jan 19, 2018" .SH NAME 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] [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. +.IP "diceware [options]" +Generate a random diceware passphrase. + .IP "edit [options] " 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] " Extracts and prints the contents of a database to standard output in XML format. +.IP "generate [options]" +Generate a random password. + .IP "locate [options] " 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. +.SS "Diceware options" + +.IP "-W, --words " +Desired number of words for the generated passphrase. [Default: 7] + +.IP "-w, --word-list " +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 " +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 Bugs and feature requests can be reported on GitHub at https://github.com/keepassxreboot/keepassxc/issues. diff --git a/src/core/FilePath.cpp b/src/core/FilePath.cpp index f694f548b..6b555075a 100644 --- a/src/core/FilePath.cpp +++ b/src/core/FilePath.cpp @@ -91,6 +91,11 @@ QString FilePath::pluginPath(const QString& name) return QString(); } +QString FilePath::wordlistPath(const QString& name) +{ + return m_instance->dataPath("wordlists/" + name); +} + QIcon FilePath::applicationIcon() { bool darkIcon = useDarkIcon(); diff --git a/src/core/FilePath.h b/src/core/FilePath.h index 2db496937..f84f84e0e 100644 --- a/src/core/FilePath.h +++ b/src/core/FilePath.h @@ -27,6 +27,7 @@ class FilePath public: QString dataPath(const QString& name); QString pluginPath(const QString& name); + QString wordlistPath(const QString& name); QIcon applicationIcon(); QIcon trayIconLocked(); QIcon trayIconUnlocked(); diff --git a/src/core/PassphraseGenerator.cpp b/src/core/PassphraseGenerator.cpp index 115c70d6d..2bc2be56d 100644 --- a/src/core/PassphraseGenerator.cpp +++ b/src/core/PassphraseGenerator.cpp @@ -24,9 +24,12 @@ #include "crypto/Random.h" #include "core/FilePath.h" +const QString PassphraseGenerator::DefaultSeparator = " "; +const QString PassphraseGenerator::DefaultWordList = "eff_large.wordlist"; + PassphraseGenerator::PassphraseGenerator() : m_wordCount(0) - , m_separator(' ') + , m_separator(PassphraseGenerator::DefaultSeparator) { } @@ -48,7 +51,7 @@ void PassphraseGenerator::setWordCount(int wordCount) m_wordCount = wordCount; } else { // safe default if something goes wrong - m_wordCount = 7; + m_wordCount = DefaultWordCount; } } @@ -76,7 +79,7 @@ void PassphraseGenerator::setWordList(QString path) void PassphraseGenerator::setDefaultWordList() { - const QString path = filePath()->dataPath("wordlists/eff_large.wordlist"); + const QString path = filePath()->wordlistPath(PassphraseGenerator::DefaultWordList); setWordList(path); } diff --git a/src/core/PassphraseGenerator.h b/src/core/PassphraseGenerator.h index 20845ff21..4a489827d 100644 --- a/src/core/PassphraseGenerator.h +++ b/src/core/PassphraseGenerator.h @@ -36,6 +36,10 @@ public: QString generatePassphrase() const; + static const int DefaultWordCount = 7; + static const QString DefaultSeparator; + static const QString DefaultWordList; + private: int m_wordCount; QString m_separator; diff --git a/src/core/PasswordGenerator.cpp b/src/core/PasswordGenerator.cpp index 21aa590e0..740fb5467 100644 --- a/src/core/PasswordGenerator.cpp +++ b/src/core/PasswordGenerator.cpp @@ -35,11 +35,19 @@ double PasswordGenerator::calculateEntropy(QString password) void PasswordGenerator::setLength(int length) { + if (length <= 0) { + m_length = DefaultLength; + return; + } m_length = length; } void PasswordGenerator::setCharClasses(const CharClasses& classes) { + if (classes == 0) { + m_classes = DefaultCharset; + return; + } m_classes = classes; } diff --git a/src/core/PasswordGenerator.h b/src/core/PasswordGenerator.h index 98bb58b6a..15a0dcefe 100644 --- a/src/core/PasswordGenerator.h +++ b/src/core/PasswordGenerator.h @@ -34,14 +34,16 @@ public: UpperLetters = 0x2, Numbers = 0x4, SpecialCharacters = 0x8, - EASCII = 0x10 + EASCII = 0x10, + DefaultCharset = LowerLetters | UpperLetters | Numbers }; Q_DECLARE_FLAGS(CharClasses, CharClass) enum GeneratorFlag { ExcludeLookAlike = 0x1, - CharFromEveryGroup = 0x2 + CharFromEveryGroup = 0x2, + DefaultFlags = ExcludeLookAlike | CharFromEveryGroup }; Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag) @@ -59,6 +61,13 @@ public: int getbits() const; 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: QVector passwordGroups() const; diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index c9c10aa56..e6cb0a92d 100644 --- a/src/gui/PasswordGeneratorWidget.cpp +++ b/src/gui/PasswordGeneratorWidget.cpp @@ -68,9 +68,9 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) } // 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); m_ui->comboBoxWordList->addItems(files); if (files.size() > 1) { @@ -93,19 +93,19 @@ PasswordGeneratorWidget::~PasswordGeneratorWidget() void PasswordGeneratorWidget::loadSettings() { // Password config - m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", true).toBool()); - m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", true).toBool()); - m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", true).toBool()); - m_ui->checkBoxSpecialChars->setChecked(config()->get("generator/SpecialChars", false).toBool()); - m_ui->checkBoxExtASCII->setChecked(config()->get("generator/EASCII", false).toBool()); - m_ui->checkBoxExcludeAlike->setChecked(config()->get("generator/ExcludeAlike", true).toBool()); - m_ui->checkBoxEnsureEvery->setChecked(config()->get("generator/EnsureEvery", true).toBool()); + m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", PasswordGenerator::DefaultLower).toBool()); + m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", PasswordGenerator::DefaultUpper).toBool()); + m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool()); + m_ui->checkBoxSpecialChars->setChecked(config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool()); + m_ui->checkBoxExtASCII->setChecked(config()->get("generator/EASCII", PasswordGenerator::DefaultEASCII).toBool()); + m_ui->checkBoxExcludeAlike->setChecked(config()->get("generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).toBool()); + m_ui->checkBoxEnsureEvery->setChecked(config()->get("generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool()); m_ui->spinBoxLength->setValue(config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt()); // Diceware config - m_ui->spinBoxWordCount->setValue(config()->get("generator/WordCount", 6).toInt()); - m_ui->editWordSeparator->setText(config()->get("generator/WordSeparator", " ").toString()); - m_ui->comboBoxWordList->setCurrentText(config()->get("generator/WordList", "eff_large.wordlist").toString()); + m_ui->spinBoxWordCount->setValue(config()->get("generator/WordCount", PassphraseGenerator::DefaultWordCount).toInt()); + m_ui->editWordSeparator->setText(config()->get("generator/WordSeparator", PassphraseGenerator::DefaultSeparator).toString()); + m_ui->comboBoxWordList->setCurrentText(config()->get("generator/WordList", PassphraseGenerator::DefaultWordList).toString()); // Password or diceware? m_ui->tabWidget->setCurrentIndex(config()->get("generator/Type", 0).toInt()); @@ -394,7 +394,7 @@ void PasswordGeneratorWidget::updateGenerator() m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value()); 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->setWordSeparator(m_ui->editWordSeparator->text()); diff --git a/src/http/HttpPasswordGeneratorWidget.cpp b/src/http/HttpPasswordGeneratorWidget.cpp index b722a85f3..f08bc3d36 100644 --- a/src/http/HttpPasswordGeneratorWidget.cpp +++ b/src/http/HttpPasswordGeneratorWidget.cpp @@ -48,13 +48,14 @@ HttpPasswordGeneratorWidget::~HttpPasswordGeneratorWidget() void HttpPasswordGeneratorWidget::loadSettings() { - m_ui->checkBoxLower->setChecked(config()->get("Http/generator/LowerCase", true).toBool()); - m_ui->checkBoxUpper->setChecked(config()->get("Http/generator/UpperCase", true).toBool()); - m_ui->checkBoxNumbers->setChecked(config()->get("Http/generator/Numbers", true).toBool()); - m_ui->checkBoxSpecialChars->setChecked(config()->get("Http/generator/SpecialChars", false).toBool()); + m_ui->checkBoxLower->setChecked(config()->get("Http/generator/LowerCase", PasswordGenerator::DefaultLower).toBool()); + m_ui->checkBoxUpper->setChecked(config()->get("Http/generator/UpperCase", PasswordGenerator::DefaultUpper).toBool()); + m_ui->checkBoxNumbers->setChecked(config()->get("Http/generator/Numbers", PasswordGenerator::DefaultNumbers).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->checkBoxEnsureEvery->setChecked(config()->get("Http/generator/EnsureEvery", true).toBool()); + m_ui->checkBoxExcludeAlike->setChecked(config()->get("Http/generator/ExcludeAlike", PasswordGenerator::DefaultLookAlike).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()); } @@ -65,6 +66,7 @@ void HttpPasswordGeneratorWidget::saveSettings() config()->set("Http/generator/UpperCase", m_ui->checkBoxUpper->isChecked()); config()->set("Http/generator/Numbers", m_ui->checkBoxNumbers->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/EnsureEvery", m_ui->checkBoxEnsureEvery->isChecked()); @@ -120,6 +122,10 @@ PasswordGenerator::CharClasses HttpPasswordGeneratorWidget::charClasses() classes |= PasswordGenerator::SpecialCharacters; } + if (m_ui->checkBoxExtASCII->isChecked()) { + classes |= PasswordGenerator::EASCII; + } + return classes; } diff --git a/src/http/HttpPasswordGeneratorWidget.ui b/src/http/HttpPasswordGeneratorWidget.ui index 066b9c512..71df88730 100644 --- a/src/http/HttpPasswordGeneratorWidget.ui +++ b/src/http/HttpPasswordGeneratorWidget.ui @@ -142,6 +142,22 @@ + + + + Extended ASCII + + + Extended ASCII + + + true + + + optionButtons + + + diff --git a/src/http/HttpSettings.cpp b/src/http/HttpSettings.cpp index 60a35940c..7ff0dbaa4 100644 --- a/src/http/HttpSettings.cpp +++ b/src/http/HttpSettings.cpp @@ -145,7 +145,7 @@ void HttpSettings::setHttpPort(int port) 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) @@ -155,7 +155,7 @@ void HttpSettings::setPasswordUseNumbers(bool useNumbers) 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) @@ -165,7 +165,7 @@ void HttpSettings::setPasswordUseLowercase(bool useLowercase) 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) @@ -175,7 +175,7 @@ void HttpSettings::setPasswordUseUppercase(bool useUppercase) 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) @@ -183,9 +183,19 @@ void HttpSettings::setPasswordUseSpecial(bool 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() { - return config()->get("Http/generator/EnsureEvery", true).toBool(); + return config()->get("Http/generator/EnsureEvery", PasswordGenerator::DefaultFromEveryGroup).toBool(); } void HttpSettings::setPasswordEveryGroup(bool everyGroup) @@ -195,7 +205,7 @@ void HttpSettings::setPasswordEveryGroup(bool everyGroup) 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) @@ -205,7 +215,7 @@ void HttpSettings::setPasswordExcludeAlike(bool excludeAlike) 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) @@ -217,14 +227,21 @@ void HttpSettings::setPasswordLength(int length) PasswordGenerator::CharClasses HttpSettings::passwordCharClasses() { PasswordGenerator::CharClasses classes; - if (passwordUseLowercase()) + if (passwordUseLowercase()) { classes |= PasswordGenerator::LowerLetters; - if (passwordUseUppercase()) + } + if (passwordUseUppercase()) { classes |= PasswordGenerator::UpperLetters; - if (passwordUseNumbers()) + } + if (passwordUseNumbers()) { classes |= PasswordGenerator::Numbers; - if (passwordUseSpecial()) + } + if (passwordUseSpecial()) { classes |= PasswordGenerator::SpecialCharacters; + } + if (passwordUseEASCII()) { + classes |= PasswordGenerator::EASCII; + } return classes; } diff --git a/src/http/HttpSettings.h b/src/http/HttpSettings.h index a4aee1a63..63c2963cf 100644 --- a/src/http/HttpSettings.h +++ b/src/http/HttpSettings.h @@ -58,6 +58,8 @@ public: static void setPasswordUseUppercase(bool useUppercase); static bool passwordUseSpecial(); static void setPasswordUseSpecial(bool useSpecial); + static bool passwordUseEASCII(); + static void setPasswordUseEASCII(bool useExtended); static bool passwordEveryGroup(); static void setPasswordEveryGroup(bool everyGroup); static bool passwordExcludeAlike();