diff --git a/src/browser/BrowserSettings.cpp b/src/browser/BrowserSettings.cpp index 2df7fc1c..ecaf8e23 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 13023b5b..5c97299b 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 14356c41..5769249c 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 225ce47d..a5126f99 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 6b458a67..886f8ecc 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 a9e24fae..e9423123 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 6ec07b7a..ef694888 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 b751c4a8..2ebdd77b 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 00000000..c71b57d7 --- /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 00000000..61fe724c --- /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 25d2fd45..967ddd8e 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 e52069ff..2c413bea 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 80226a27..9a2ab0b0 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 2cbe4910..15f92275 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 477f2b0e..b48d5a6a 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 bef6a782..2939afdd 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 00000000..eb8fea5e --- /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 00000000..607fc105 --- /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 73830cab..bdedaf21 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 d12105f3..98b8b5a4 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 83a3c5ce..f8037288 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 c919b0cb..3677a034 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 5df6b018..6b114bff 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 4f0b4283..496c66b8 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 6abb68f1..64a5976e 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 2440c201..5465530e 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 66225c56..54561b1f 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 f2caefdb..18b6d704 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 f42095cb..35e7cce3 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 0c6b749a..1f805118 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 a9145b27..cc1e7b8d 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 f694f548..6b555075 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 2db49693..f84f84e0 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 115c70d6..2bc2be56 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 20845ff2..4a489827 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 21aa590e..740fb546 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 98bb58b6..15a0dcef 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 c9c10aa5..e6cb0a92 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 b722a85f..f08bc3d3 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 066b9c51..71df8873 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 60a35940..7ff0dbaa 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 a4aee1a6..63c2963c 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();