From a58e3d5ee0113019adea182830b2fcc9e5387184 Mon Sep 17 00:00:00 2001 From: louib Date: Mon, 18 Feb 2019 20:17:28 -0500 Subject: [PATCH] Adding debug info to CLI. Adding debug info to the CLI and the general option of the main Qt app. Also took time to: * use `EXIT_SUCCESS`/`EXIT_FAILURE` constants for main.cpp (this is what is used in `src/cli`); * fixed `m_initalized` typo; * added info on debugging mode being disabled or not; * regrouped Qt related stuff in the debug output. --- src/cli/keepassxc-cli.1 | 5 +- src/cli/keepassxc-cli.cpp | 8 +++ src/core/Tools.cpp | 76 ++++++++++++++++++++++++++++ src/core/Tools.h | 1 + src/crypto/Crypto.cpp | 22 ++++---- src/crypto/Crypto.h | 6 +-- src/crypto/CryptoHash.cpp | 2 +- src/crypto/Random.cpp | 2 +- src/crypto/SymmetricCipherGcrypt.cpp | 2 +- src/gui/AboutDialog.cpp | 66 ++---------------------- src/main.cpp | 18 +++++-- 11 files changed, 126 insertions(+), 82 deletions(-) diff --git a/src/cli/keepassxc-cli.1 b/src/cli/keepassxc-cli.1 index 22cf88a3a..4cee31774 100644 --- a/src/cli/keepassxc-cli.1 +++ b/src/cli/keepassxc-cli.1 @@ -56,6 +56,9 @@ Shows the title, username, password, URL and notes of a database entry. Can also .SS "General options" +.IP "--debug-info" +Displays debugging information. + .IP "-k, --key-file " Specifies a path to a key file for unlocking the database. In a merge operation this option is used to specify the key file path for the first database. @@ -66,7 +69,7 @@ Silence password prompt and other secondary outputs. Displays help information. .IP "-v, --version" -Shows the program version. +Displays the program version. .SS "Merge options" diff --git a/src/cli/keepassxc-cli.cpp b/src/cli/keepassxc-cli.cpp index b9e3853f2..2c6ce4660 100644 --- a/src/cli/keepassxc-cli.cpp +++ b/src/cli/keepassxc-cli.cpp @@ -26,6 +26,7 @@ #include "config-keepassx.h" #include "core/Bootstrap.h" +#include "core/Tools.h" #include "crypto/Crypto.h" #if defined(WITH_ASAN) && defined(WITH_LSAN) @@ -60,6 +61,9 @@ int main(int argc, char** argv) parser.addPositionalArgument("command", QObject::tr("Name of the command to execute.")); + QCommandLineOption debugInfoOption(QStringList() << "debug-info", + QObject::tr("Displays debugging information.")); + parser.addOption(debugInfoOption); parser.addHelpOption(); parser.addVersionOption(); // TODO : use the setOptionsAfterPositionalArgumentsMode (Qt 5.6) function @@ -72,6 +76,10 @@ int main(int argc, char** argv) // Switch to parser.showVersion() when available (QT 5.4). out << KEEPASSXC_VERSION << endl; return EXIT_SUCCESS; + } else if (parser.isSet(debugInfoOption)) { + QString debugInfo = Tools::debugInfo().append("\n").append(Crypto::debugInfo()); + out << debugInfo << endl; + return EXIT_SUCCESS; } parser.showHelp(); } diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index b77a460d4..09938b82a 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -18,6 +18,8 @@ */ #include "Tools.h" + +#include "config-keepassx.h" #include "core/Config.h" #include "core/Translator.h" @@ -28,8 +30,10 @@ #include #include #include +#include #include #include +#include "git-info.h" #ifdef Q_OS_WIN #include // for Sleep() @@ -41,6 +45,78 @@ namespace Tools { + QString debugInfo() + { + QString debugInfo = "KeePassXC - "; + debugInfo.append(QObject::tr("Version %1").arg(KEEPASSXC_VERSION).append("\n")); +#ifndef KEEPASSXC_BUILD_TYPE_RELEASE + debugInfo.append(QObject::tr("Build Type: %1").arg(KEEPASSXC_BUILD_TYPE).append("\n")); +#endif + + QString commitHash; + if (!QString(GIT_HEAD).isEmpty()) { + commitHash = GIT_HEAD; + } + if (!commitHash.isEmpty()) { + debugInfo.append(QObject::tr("Revision: %1").arg(commitHash.left(7)).append("\n")); + } + +#ifdef KEEPASSXC_DIST + debugInfo.append(QObject::tr("Distribution: %1").arg(KEEPASSXC_DIST_TYPE).append("\n")); +#endif + + // Qt related debugging information. + debugInfo.append("\n"); + debugInfo.append("Qt ").append(QString::fromLocal8Bit(qVersion())).append("\n"); +#ifdef QT_NO_DEBUG + debugInfo.append(QObject::tr("Debugging mode is disabled.").append("\n")); +#else + debugInfo.append(QObject::tr("Debugging mode is enabled.").append("\n")); +#endif + debugInfo.append("\n"); + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + debugInfo.append(QObject::tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4") + .arg(QSysInfo::prettyProductName(), + QSysInfo::currentCpuArchitecture(), + QSysInfo::kernelType(), + QSysInfo::kernelVersion())); + + debugInfo.append("\n\n"); +#endif + + QString extensions; +#ifdef WITH_XC_AUTOTYPE + extensions += "\n- " + QObject::tr("Auto-Type"); +#endif +#ifdef WITH_XC_BROWSER + extensions += "\n- " + QObject::tr("Browser Integration"); +#endif +#ifdef WITH_XC_SSHAGENT + extensions += "\n- " + QObject::tr("SSH Agent"); +#endif +#if defined(WITH_XC_KEESHARE_SECURE) && defined(WITH_XC_KEESHARE_INSECURE) + extensions += "\n- " + QObject::tr("KeeShare (signed and unsigned sharing)"); +#elif defined(WITH_XC_KEESHARE_SECURE) + extensions += "\n- " + QObject::tr("KeeShare (only signed sharing)"); +#elif defined(WITH_XC_KEESHARE_INSECURE) + extensions += "\n- " + QObject::tr("KeeShare (only unsigned sharing)"); +#endif +#ifdef WITH_XC_YUBIKEY + extensions += "\n- " + QObject::tr("YubiKey"); +#endif +#ifdef WITH_XC_TOUCHID + extensions += "\n- " + QObject::tr("TouchID"); +#endif + + if (extensions.isEmpty()) + extensions = " " + QObject::tr("None"); + + debugInfo.append(QObject::tr("Enabled extensions:").append(extensions).append("\n")); + return debugInfo; + } + QString humanReadableFileSize(qint64 bytes, quint32 precision) { constexpr auto kibibyte = 1024; diff --git a/src/core/Tools.h b/src/core/Tools.h index a2c09efe2..1fa5e6a9a 100644 --- a/src/core/Tools.h +++ b/src/core/Tools.h @@ -32,6 +32,7 @@ class QRegularExpression; namespace Tools { + QString debugInfo(); QString humanReadableFileSize(qint64 bytes, quint32 precision = 2); bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384); bool readAllFromDevice(QIODevice* device, QByteArray& data); diff --git a/src/crypto/Crypto.cpp b/src/crypto/Crypto.cpp index ab97322ca..4f54ac1d3 100644 --- a/src/crypto/Crypto.cpp +++ b/src/crypto/Crypto.cpp @@ -25,7 +25,7 @@ #include "crypto/CryptoHash.h" #include "crypto/SymmetricCipher.h" -bool Crypto::m_initalized(false); +bool Crypto::m_initialized(false); QString Crypto::m_errorStr; QString Crypto::m_backendVersion; @@ -35,8 +35,8 @@ Crypto::Crypto() bool Crypto::init() { - if (m_initalized) { - qWarning("Crypto::init: already initalized"); + if (m_initialized) { + qWarning("Crypto::init: already initialized"); return true; } @@ -48,19 +48,19 @@ bool Crypto::init() } // has to be set before testing Crypto classes - m_initalized = true; + m_initialized = true; if (!backendSelfTest() || !selfTest()) { - m_initalized = false; + m_initialized = false; return false; } return true; } -bool Crypto::initalized() +bool Crypto::initialized() { - return m_initalized; + return m_initialized; } QString Crypto::errorString() @@ -68,9 +68,13 @@ QString Crypto::errorString() return m_errorStr; } -QString Crypto::backendVersion() +QString Crypto::debugInfo() { - return QString("libgcrypt ").append(m_backendVersion); + Q_ASSERT(Crypto::initialized()); + + QString debugInfo = QObject::tr("Cryptographic libraries:").append("\n"); + debugInfo.append(" libgcrypt ").append(m_backendVersion).append("\n"); + return debugInfo; } bool Crypto::backendSelfTest() diff --git a/src/crypto/Crypto.h b/src/crypto/Crypto.h index 379068eb4..4346f5055 100644 --- a/src/crypto/Crypto.h +++ b/src/crypto/Crypto.h @@ -24,10 +24,10 @@ class Crypto { public: static bool init(); - static bool initalized(); + static bool initialized(); static bool backendSelfTest(); static QString errorString(); - static QString backendVersion(); + static QString debugInfo(); private: Crypto(); @@ -42,7 +42,7 @@ private: static bool testSalsa20(); static bool testChaCha20(); - static bool m_initalized; + static bool m_initialized; static QString m_errorStr; static QString m_backendVersion; }; diff --git a/src/crypto/CryptoHash.cpp b/src/crypto/CryptoHash.cpp index 07bf5efc9..5eab8567a 100644 --- a/src/crypto/CryptoHash.cpp +++ b/src/crypto/CryptoHash.cpp @@ -33,7 +33,7 @@ CryptoHash::CryptoHash(Algorithm algo, bool hmac) { Q_D(CryptoHash); - Q_ASSERT(Crypto::initalized()); + Q_ASSERT(Crypto::initialized()); int algoGcrypt = -1; unsigned int flagsGcrypt = GCRY_MD_FLAG_SECURE; diff --git a/src/crypto/Random.cpp b/src/crypto/Random.cpp index 4203b6c0c..024a82f91 100644 --- a/src/crypto/Random.cpp +++ b/src/crypto/Random.cpp @@ -93,7 +93,7 @@ Random::Random(RandomBackend* backend) void RandomBackendGcrypt::randomize(void* data, int len) { - Q_ASSERT(Crypto::initalized()); + Q_ASSERT(Crypto::initialized()); gcry_randomize(data, len, GCRY_STRONG_RANDOM); } diff --git a/src/crypto/SymmetricCipherGcrypt.cpp b/src/crypto/SymmetricCipherGcrypt.cpp index fb436522d..4d12d25a9 100644 --- a/src/crypto/SymmetricCipherGcrypt.cpp +++ b/src/crypto/SymmetricCipherGcrypt.cpp @@ -90,7 +90,7 @@ void SymmetricCipherGcrypt::setError(const gcry_error_t& err) bool SymmetricCipherGcrypt::init() { - Q_ASSERT(Crypto::initalized()); + Q_ASSERT(Crypto::initialized()); gcry_error_t error; diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 0de79fccc..f37baedc0 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -21,11 +21,11 @@ #include "config-keepassx.h" #include "core/FilePath.h" +#include "core/Tools.h" #include "crypto/Crypto.h" -#include "git-info.h" #include -#include + static const QString aboutMaintainers = R"(

    @@ -175,67 +175,7 @@ AboutDialog::AboutDialog(QWidget* parent) m_ui->iconLabel->setPixmap(filePath()->applicationIcon().pixmap(48)); - QString commitHash; - if (!QString(GIT_HEAD).isEmpty()) { - commitHash = GIT_HEAD; - } - - QString debugInfo = "KeePassXC - "; - debugInfo.append(tr("Version %1").arg(KEEPASSXC_VERSION).append("\n")); -#ifndef KEEPASSXC_BUILD_TYPE_RELEASE - debugInfo.append(tr("Build Type: %1").arg(KEEPASSXC_BUILD_TYPE).append("\n")); -#endif - if (!commitHash.isEmpty()) { - debugInfo.append(tr("Revision: %1").arg(commitHash.left(7)).append("\n")); - } - -#ifdef KEEPASSXC_DIST - debugInfo.append(tr("Distribution: %1").arg(KEEPASSXC_DIST_TYPE).append("\n")); -#endif - - debugInfo.append("\n").append( - QString("%1\n- Qt %2\n- %3\n\n") - .arg(tr("Libraries:"), QString::fromLocal8Bit(qVersion()), Crypto::backendVersion())); - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - debugInfo.append(tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4") - .arg(QSysInfo::prettyProductName(), - QSysInfo::currentCpuArchitecture(), - QSysInfo::kernelType(), - QSysInfo::kernelVersion())); - - debugInfo.append("\n\n"); -#endif - - QString extensions; -#ifdef WITH_XC_AUTOTYPE - extensions += "\n- " + tr("Auto-Type"); -#endif -#ifdef WITH_XC_BROWSER - extensions += "\n- " + tr("Browser Integration"); -#endif -#ifdef WITH_XC_SSHAGENT - extensions += "\n- " + tr("SSH Agent"); -#endif -#if defined(WITH_XC_KEESHARE_SECURE) && defined(WITH_XC_KEESHARE_INSECURE) - extensions += "\n- " + tr("KeeShare (signed and unsigned sharing)"); -#elif defined(WITH_XC_KEESHARE_SECURE) - extensions += "\n- " + tr("KeeShare (only signed sharing)"); -#elif defined(WITH_XC_KEESHARE_INSECURE) - extensions += "\n- " + tr("KeeShare (only unsigned sharing)"); -#endif -#ifdef WITH_XC_YUBIKEY - extensions += "\n- " + tr("YubiKey"); -#endif -#ifdef WITH_XC_TOUCHID - extensions += "\n- " + tr("TouchID"); -#endif - - if (extensions.isEmpty()) - extensions = " " + tr("None"); - - debugInfo.append(tr("Enabled extensions:").append(extensions)); - + QString debugInfo = Tools::debugInfo().append("\n").append(Crypto::debugInfo()); m_ui->debugInfo->setPlainText(debugInfo); m_ui->maintainers->setText(aboutMaintainers); diff --git a/src/main.cpp b/src/main.cpp index a546c0491..e975a6b9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -82,16 +82,19 @@ int main(int argc, char** argv) QCommandLineOption helpOption = parser.addHelpOption(); QCommandLineOption versionOption = parser.addVersionOption(); + QCommandLineOption debugInfoOption(QStringList() << "debug-info", + QObject::tr("Displays debugging information.")); parser.addOption(configOption); parser.addOption(keyfileOption); parser.addOption(pwstdinOption); parser.addOption(parentWindowOption); + parser.addOption(debugInfoOption); parser.process(app); // Don't try and do anything with the application if we're only showing the help / version if (parser.isSet(versionOption) || parser.isSet(helpOption)) { - return 0; + return EXIT_SUCCESS; } const QStringList fileNames = parser.positionalArguments(); @@ -101,7 +104,7 @@ int main(int argc, char** argv) app.sendFileNamesToRunningInstance(fileNames); } qWarning() << QObject::tr("Another instance of KeePassXC is already running.").toUtf8().constData(); - return 0; + return EXIT_SUCCESS; } QApplication::setQuitOnLastWindowClosed(false); @@ -111,7 +114,16 @@ int main(int argc, char** argv) error.append("\n"); error.append(Crypto::errorString()); MessageBox::critical(nullptr, QObject::tr("KeePassXC - Error"), error); - return 1; + return EXIT_FAILURE; + } + + // Displaying the debugging informations must be done after Crypto::init, + // to make sure we know which libgcrypt version is used. + if (parser.isSet(debugInfoOption)) { + QTextStream out(stdout, QIODevice::WriteOnly); + QString debugInfo = Tools::debugInfo().append("\n").append(Crypto::debugInfo()); + out << debugInfo << endl; + return EXIT_SUCCESS; } if (parser.isSet(configOption)) {