mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-22 07:29:52 -05:00
Adding db-info CLI command. (#4231)
This adds a basic db-show CLI command, to display the information related to a database.
This commit is contained in:
parent
04be724614
commit
b78ca924fd
@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2.6 (unreleased)
|
||||
|
||||
### Added
|
||||
- Added CLI db-info command [#4231]
|
||||
|
||||
### Changed
|
||||
- Renamed CLI create command to db-create [#4231]
|
||||
|
||||
## 2.5.3 (2020-01-19)
|
||||
|
||||
### Fixed
|
||||
|
@ -28,9 +28,12 @@ Copies the password or the current TOTP (\fI-t\fP option) of a database entry to
|
||||
.IP "\fBclose\fP"
|
||||
In interactive mode, closes the currently opened database (see \fIopen\fP).
|
||||
|
||||
.IP "\fBcreate\fP [options] <database>"
|
||||
.IP "\fBdb-create\fP [options] <database>"
|
||||
Creates a new database with a key file and/or password. The key file will be created if the file that is referred to does not exist. If both the key file and password are empty, no database will be created.
|
||||
|
||||
.IP "\fBdb-info\fP [options] <database>"
|
||||
Show a database's information.
|
||||
|
||||
.IP "\fBdiceware\fP [options]"
|
||||
Generates a random diceware passphrase.
|
||||
|
||||
|
@ -30,6 +30,7 @@ set(cli_SOURCES
|
||||
Generate.cpp
|
||||
Help.cpp
|
||||
Import.cpp
|
||||
Info.cpp
|
||||
List.cpp
|
||||
Locate.cpp
|
||||
Merge.cpp
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "Generate.h"
|
||||
#include "Help.h"
|
||||
#include "Import.h"
|
||||
#include "Info.h"
|
||||
#include "List.h"
|
||||
#include "Locate.h"
|
||||
#include "Merge.h"
|
||||
@ -160,7 +161,8 @@ namespace Commands
|
||||
s_commands.insert(QStringLiteral("analyze"), QSharedPointer<Command>(new Analyze()));
|
||||
s_commands.insert(QStringLiteral("clip"), QSharedPointer<Command>(new Clip()));
|
||||
s_commands.insert(QStringLiteral("close"), QSharedPointer<Command>(new Close()));
|
||||
s_commands.insert(QStringLiteral("create"), QSharedPointer<Command>(new Create()));
|
||||
s_commands.insert(QStringLiteral("db-create"), QSharedPointer<Command>(new Create()));
|
||||
s_commands.insert(QStringLiteral("db-info"), QSharedPointer<Command>(new Info()));
|
||||
s_commands.insert(QStringLiteral("diceware"), QSharedPointer<Command>(new Diceware()));
|
||||
s_commands.insert(QStringLiteral("edit"), QSharedPointer<Command>(new Edit()));
|
||||
s_commands.insert(QStringLiteral("estimate"), QSharedPointer<Command>(new Estimate()));
|
||||
|
53
src/cli/Info.cpp
Normal file
53
src/cli/Info.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 "Info.h"
|
||||
|
||||
#include "core/Database.h"
|
||||
#include "core/Metadata.h"
|
||||
#include "format/KeePass2.h"
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
Info::Info()
|
||||
{
|
||||
name = QString("db-show");
|
||||
description = QObject::tr("Show a database's information.");
|
||||
}
|
||||
|
||||
int Info::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser>)
|
||||
{
|
||||
TextStream out(Utils::STDOUT, QIODevice::WriteOnly);
|
||||
|
||||
out << QObject::tr("UUID: ") << database->uuid().toString() << endl;
|
||||
out << QObject::tr("Name: ") << database->metadata()->name() << endl;
|
||||
out << QObject::tr("Description: ") << database->metadata()->description() << endl;
|
||||
for (auto& cipher : asConst(KeePass2::CIPHERS)) {
|
||||
if (cipher.first == database->cipher()) {
|
||||
out << QObject::tr("Cipher: ") << cipher.second << endl;
|
||||
}
|
||||
}
|
||||
out << QObject::tr("KDF: ") << database->kdf()->toString() << endl;
|
||||
if (database->metadata()->recycleBinEnabled()) {
|
||||
out << QObject::tr("Recycle bin is enabled.") << endl;
|
||||
} else {
|
||||
out << QObject::tr("Recycle bin is not enabled.") << endl;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
31
src/cli/Info.h
Normal file
31
src/cli/Info.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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_INFO_H
|
||||
#define KEEPASSXC_INFO_H
|
||||
|
||||
#include "DatabaseCommand.h"
|
||||
|
||||
class Info : public DatabaseCommand
|
||||
{
|
||||
public:
|
||||
Info();
|
||||
|
||||
int executeWithDatabase(QSharedPointer<Database> db, QSharedPointer<QCommandLineParser> parser);
|
||||
};
|
||||
|
||||
#endif // KEEPASSXC_INFO_H
|
@ -125,3 +125,8 @@ int AesKdf::benchmarkImpl(int msec) const
|
||||
|
||||
return static_cast<int>(rounds * (static_cast<float>(msec) / timer.elapsed()));
|
||||
}
|
||||
|
||||
QString AesKdf::toString() const
|
||||
{
|
||||
return QObject::tr("AES (%1 rounds)").arg(QString::number(rounds()));
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
QVariantMap writeParameters() override;
|
||||
bool transform(const QByteArray& raw, QByteArray& result) const override;
|
||||
QSharedPointer<Kdf> clone() const override;
|
||||
QString toString() const override;
|
||||
|
||||
protected:
|
||||
int benchmarkImpl(int msec) const override;
|
||||
|
@ -211,3 +211,8 @@ int Argon2Kdf::benchmarkImpl(int msec) const
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
QString Argon2Kdf::toString() const
|
||||
{
|
||||
return QObject::tr("Argon2 (%1 rounds, %2 KB)").arg(QString::number(rounds()), QString::number(memory()));
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
bool setMemory(quint64 kibibytes);
|
||||
quint32 parallelism() const;
|
||||
bool setParallelism(quint32 threads);
|
||||
QString toString() const override;
|
||||
|
||||
protected:
|
||||
int benchmarkImpl(int msec) const override;
|
||||
|
@ -44,6 +44,8 @@ public:
|
||||
virtual bool transform(const QByteArray& raw, QByteArray& result) const = 0;
|
||||
virtual QSharedPointer<Kdf> clone() const = 0;
|
||||
|
||||
virtual QString toString() const = 0;
|
||||
|
||||
int benchmark(int msec) const;
|
||||
|
||||
protected:
|
||||
|
@ -48,9 +48,9 @@ const QString KeePass2::KDFPARAM_ARGON2_SECRET("K");
|
||||
const QString KeePass2::KDFPARAM_ARGON2_ASSOCDATA("A");
|
||||
|
||||
const QList<QPair<QUuid, QString>> KeePass2::CIPHERS{
|
||||
qMakePair(KeePass2::CIPHER_AES256, QObject::tr("AES: 256-bit")),
|
||||
qMakePair(KeePass2::CIPHER_TWOFISH, QObject::tr("Twofish: 256-bit")),
|
||||
qMakePair(KeePass2::CIPHER_CHACHA20, QObject::tr("ChaCha20: 256-bit"))};
|
||||
qMakePair(KeePass2::CIPHER_AES256, QObject::tr("AES 256-bit")),
|
||||
qMakePair(KeePass2::CIPHER_TWOFISH, QObject::tr("Twofish 256-bit")),
|
||||
qMakePair(KeePass2::CIPHER_CHACHA20, QObject::tr("ChaCha20 256-bit"))};
|
||||
|
||||
const QList<QPair<QUuid, QString>> KeePass2::KDFS{
|
||||
qMakePair(KeePass2::KDF_ARGON2, QObject::tr("Argon2 (KDBX 4 – recommended)")),
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "cli/Generate.h"
|
||||
#include "cli/Help.h"
|
||||
#include "cli/Import.h"
|
||||
#include "cli/Info.h"
|
||||
#include "cli/List.h"
|
||||
#include "cli/Locate.h"
|
||||
#include "cli/Merge.h"
|
||||
@ -192,7 +193,8 @@ void TestCli::testBatchCommands()
|
||||
QVERIFY(Commands::getCommand("analyze"));
|
||||
QVERIFY(Commands::getCommand("clip"));
|
||||
QVERIFY(Commands::getCommand("close"));
|
||||
QVERIFY(Commands::getCommand("create"));
|
||||
QVERIFY(Commands::getCommand("db-create"));
|
||||
QVERIFY(Commands::getCommand("db-info"));
|
||||
QVERIFY(Commands::getCommand("diceware"));
|
||||
QVERIFY(Commands::getCommand("edit"));
|
||||
QVERIFY(Commands::getCommand("estimate"));
|
||||
@ -210,7 +212,7 @@ void TestCli::testBatchCommands()
|
||||
QVERIFY(Commands::getCommand("rmdir"));
|
||||
QVERIFY(Commands::getCommand("show"));
|
||||
QVERIFY(!Commands::getCommand("doesnotexist"));
|
||||
QCOMPARE(Commands::getCommands().size(), 21);
|
||||
QCOMPARE(Commands::getCommands().size(), 22);
|
||||
}
|
||||
|
||||
void TestCli::testInteractiveCommands()
|
||||
@ -220,7 +222,8 @@ void TestCli::testInteractiveCommands()
|
||||
QVERIFY(Commands::getCommand("analyze"));
|
||||
QVERIFY(Commands::getCommand("clip"));
|
||||
QVERIFY(Commands::getCommand("close"));
|
||||
QVERIFY(Commands::getCommand("create"));
|
||||
QVERIFY(Commands::getCommand("db-create"));
|
||||
QVERIFY(Commands::getCommand("db-info"));
|
||||
QVERIFY(Commands::getCommand("diceware"));
|
||||
QVERIFY(Commands::getCommand("edit"));
|
||||
QVERIFY(Commands::getCommand("estimate"));
|
||||
@ -238,7 +241,7 @@ void TestCli::testInteractiveCommands()
|
||||
QVERIFY(Commands::getCommand("rmdir"));
|
||||
QVERIFY(Commands::getCommand("show"));
|
||||
QVERIFY(!Commands::getCommand("doesnotexist"));
|
||||
QCOMPARE(Commands::getCommands().size(), 21);
|
||||
QCOMPARE(Commands::getCommands().size(), 22);
|
||||
}
|
||||
|
||||
void TestCli::testAdd()
|
||||
@ -548,7 +551,7 @@ void TestCli::testCreate()
|
||||
QString databaseFilename = testDir->path() + "/testCreate1.kdbx";
|
||||
// Password
|
||||
Utils::Test::setNextPassword("a");
|
||||
createCmd.execute({"create", databaseFilename});
|
||||
createCmd.execute({"db-create", databaseFilename});
|
||||
|
||||
m_stderrFile->reset();
|
||||
m_stdoutFile->reset();
|
||||
@ -563,7 +566,7 @@ void TestCli::testCreate()
|
||||
// Should refuse to create the database if it already exists.
|
||||
qint64 pos = m_stdoutFile->pos();
|
||||
qint64 errPos = m_stderrFile->pos();
|
||||
createCmd.execute({"create", databaseFilename});
|
||||
createCmd.execute({"db-create", databaseFilename});
|
||||
m_stdoutFile->seek(pos);
|
||||
m_stderrFile->seek(errPos);
|
||||
// Output should be empty when there is an error.
|
||||
@ -577,7 +580,7 @@ void TestCli::testCreate()
|
||||
pos = m_stdoutFile->pos();
|
||||
errPos = m_stderrFile->pos();
|
||||
Utils::Test::setNextPassword("a");
|
||||
createCmd.execute({"create", databaseFilename2, "-k", keyfilePath});
|
||||
createCmd.execute({"db-create", databaseFilename2, "-k", keyfilePath});
|
||||
m_stdoutFile->seek(pos);
|
||||
m_stderrFile->seek(errPos);
|
||||
|
||||
@ -594,7 +597,7 @@ void TestCli::testCreate()
|
||||
pos = m_stdoutFile->pos();
|
||||
errPos = m_stderrFile->pos();
|
||||
Utils::Test::setNextPassword("a");
|
||||
createCmd.execute({"create", databaseFilename3, "-k", keyfilePath});
|
||||
createCmd.execute({"db-create", databaseFilename3, "-k", keyfilePath});
|
||||
m_stdoutFile->seek(pos);
|
||||
m_stderrFile->seek(errPos);
|
||||
|
||||
@ -607,6 +610,41 @@ void TestCli::testCreate()
|
||||
QVERIFY(db3);
|
||||
}
|
||||
|
||||
void TestCli::testInfo()
|
||||
{
|
||||
Info infoCmd;
|
||||
QVERIFY(!infoCmd.name.isEmpty());
|
||||
QVERIFY(infoCmd.getDescriptionLine().contains(infoCmd.name));
|
||||
|
||||
Utils::Test::setNextPassword("a");
|
||||
infoCmd.execute({"db-info", m_dbFile->fileName()});
|
||||
m_stdoutFile->reset();
|
||||
m_stderrFile->reset();
|
||||
m_stdoutFile->readLine(); // skip prompt line
|
||||
QCOMPARE(m_stderrFile->readAll(), QByteArray(""));
|
||||
QVERIFY(m_stdoutFile->readLine().contains(QByteArray("UUID: ")));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Name: \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Description: \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Cipher: AES 256-bit\n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("KDF: AES (6000 rounds)\n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Recycle bin is enabled.\n"));
|
||||
|
||||
// Test with quiet option.
|
||||
qint64 pos = m_stdoutFile->pos();
|
||||
qint64 errPos = m_stderrFile->pos();
|
||||
Utils::Test::setNextPassword("a");
|
||||
infoCmd.execute({"db-info", "-q", m_dbFile->fileName()});
|
||||
m_stdoutFile->seek(pos);
|
||||
m_stderrFile->seek(errPos);
|
||||
QCOMPARE(m_stderrFile->readAll(), QByteArray(""));
|
||||
QVERIFY(m_stdoutFile->readLine().contains(QByteArray("UUID: ")));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Name: \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Description: \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Cipher: AES 256-bit\n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("KDF: AES (6000 rounds)\n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Recycle bin is enabled.\n"));
|
||||
}
|
||||
|
||||
void TestCli::testDiceware()
|
||||
{
|
||||
Diceware dicewareCmd;
|
||||
@ -1446,10 +1484,10 @@ void TestCli::testMergeWithKeys()
|
||||
qint64 pos = m_stdoutFile->pos();
|
||||
|
||||
Utils::Test::setNextPassword("a");
|
||||
createCmd.execute({"create", sourceDatabaseFilename, "-k", sourceKeyfilePath});
|
||||
createCmd.execute({"db-create", sourceDatabaseFilename, "-k", sourceKeyfilePath});
|
||||
|
||||
Utils::Test::setNextPassword("b");
|
||||
createCmd.execute({"create", targetDatabaseFilename, "-k", targetKeyfilePath});
|
||||
createCmd.execute({"db-create", targetDatabaseFilename, "-k", targetKeyfilePath});
|
||||
|
||||
Utils::Test::setNextPassword("a");
|
||||
auto sourceDatabase = QSharedPointer<Database>(
|
||||
|
@ -59,6 +59,7 @@ private slots:
|
||||
void testGenerate_data();
|
||||
void testGenerate();
|
||||
void testImport();
|
||||
void testInfo();
|
||||
void testKeyFileOption();
|
||||
void testNoPasswordOption();
|
||||
void testHelp();
|
||||
|
Loading…
x
Reference in New Issue
Block a user