From a6b23476a2c38f2a2809cc4f80b3798a1e5c99a7 Mon Sep 17 00:00:00 2001 From: saturneric Date: Sat, 19 Apr 2025 02:08:03 +0200 Subject: fix: gpg context will take response of gpg-agent --- src/core/function/gpg/GpgAdvancedOperator.cpp | 18 ++--- src/core/function/gpg/GpgAdvancedOperator.h | 5 ++ src/core/function/gpg/GpgAssuanHelper.cpp | 5 +- src/core/function/gpg/GpgAssuanHelper.h | 4 +- src/core/function/gpg/GpgComponentInfoGetter.cpp | 64 ------------------ src/core/function/gpg/GpgComponentInfoGetter.h | 72 -------------------- src/core/function/gpg/GpgComponentManager.cpp | 86 ++++++++++++++++++++++++ src/core/function/gpg/GpgComponentManager.h | 86 ++++++++++++++++++++++++ src/core/function/gpg/GpgContext.cpp | 29 ++++++-- src/core/function/gpg/GpgContext.h | 39 +++++++++++ src/core/function/gpg/GpgSmartCardManager.h | 4 +- src/core/utils/GpgUtils.cpp | 6 +- 12 files changed, 254 insertions(+), 164 deletions(-) delete mode 100644 src/core/function/gpg/GpgComponentInfoGetter.cpp delete mode 100644 src/core/function/gpg/GpgComponentInfoGetter.h create mode 100644 src/core/function/gpg/GpgComponentManager.cpp create mode 100644 src/core/function/gpg/GpgComponentManager.h diff --git a/src/core/function/gpg/GpgAdvancedOperator.cpp b/src/core/function/gpg/GpgAdvancedOperator.cpp index c9af8b59..d6323901 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.cpp +++ b/src/core/function/gpg/GpgAdvancedOperator.cpp @@ -36,33 +36,27 @@ namespace GpgFrontend { auto GpgAdvancedOperator::ClearGpgPasswordCache() -> bool { - auto [ret, out] = exec_.GpgConfExecuteSync({{"--reload", "gpg-agent"}}); - return ret == 0; + return info_.ReloadGpgAgent(); } auto GpgAdvancedOperator::ReloadAllGpgComponents() -> bool { - auto [ret, out] = exec_.GpgConfExecuteSync({{"--reload", "all"}}); - return ret == 0; + return info_.ReloadGpgAgent(); } auto GpgAdvancedOperator::KillAllGpgComponents() -> bool { - auto [ret, out] = exec_.GpgConfExecuteSync({{"--kill", "all"}}); - return ret == 0; + return ctx_.RestartGpgAgent(); } auto GpgAdvancedOperator::ResetConfigures() -> bool { - auto [ret, out] = exec_.GpgConfExecuteSync({{"--apply-defaults"}}); - return ret == 0; + return info_.ReloadGpgAgent(); } auto GpgAdvancedOperator::LaunchAllGpgComponents() -> bool { - auto [ret, out] = exec_.GpgConfExecuteSync({{"--launch", "all"}}); - return ret == 0; + return ctx_.RestartGpgAgent(); } auto GpgAdvancedOperator::RestartGpgComponents() -> bool { - if (!KillAllGpgComponents()) return false; - return LaunchAllGpgComponents(); + return ctx_.RestartGpgAgent(); } GpgAdvancedOperator::GpgAdvancedOperator(int channel) diff --git a/src/core/function/gpg/GpgAdvancedOperator.h b/src/core/function/gpg/GpgAdvancedOperator.h index 1099c3b3..e6934f42 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.h +++ b/src/core/function/gpg/GpgAdvancedOperator.h @@ -34,6 +34,7 @@ #include "core/function/basic/GpgFunctionObject.h" #include "core/function/gpg/GpgCommandExecutor.h" +#include "core/function/gpg/GpgComponentManager.h" #include "core/model/DataObject.h" namespace GpgFrontend { @@ -97,6 +98,10 @@ class GPGFRONTEND_CORE_EXPORT GpgAdvancedOperator private: GpgCommandExecutor& exec_ = GpgCommandExecutor::GetInstance(SingletonFunctionObject::GetChannel()); + GpgContext& ctx_ = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); + GpgComponentManager& info_ = + GpgComponentManager::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgAssuanHelper.cpp b/src/core/function/gpg/GpgAssuanHelper.cpp index 128ecaa9..a83c5655 100644 --- a/src/core/function/gpg/GpgAssuanHelper.cpp +++ b/src/core/function/gpg/GpgAssuanHelper.cpp @@ -75,7 +75,8 @@ auto GpgAssuanHelper::ConnectToSocket(GpgComponentType type) -> GpgError { auto err = assuan_socket_connect(a_ctx, info.absoluteFilePath().toUtf8(), ASSUAN_INVALID_PID, 0); if (err != GPG_ERR_NO_ERROR) { - LOG_W() << "failed to connect to socket:" << CheckGpgError(err); + LOG_W() << "failed to connect to socket:" << info.absoluteFilePath() + << "err:" << CheckGpgError(err); return err; } @@ -165,7 +166,7 @@ auto GpgAssuanHelper::SendStatusCommand(GpgComponentType type, auto GpgAssuanHelper::SendDataCommand(GpgComponentType type, const QString& command) - -> std::tuple { + -> std::tuple { QStringList lines; GpgAssuanHelper::DataCallback d_cb = [&](const QSharedPointer& ctx) diff --git a/src/core/function/gpg/GpgAssuanHelper.h b/src/core/function/gpg/GpgAssuanHelper.h index 7f3854b6..adf6d0ff 100644 --- a/src/core/function/gpg/GpgAssuanHelper.h +++ b/src/core/function/gpg/GpgAssuanHelper.h @@ -115,8 +115,8 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper * @param command * @return auto */ - auto SendDataCommand(GpgComponentType type, - const QString& command) -> std::tuple; + auto SendDataCommand(GpgComponentType type, const QString& command) + -> std::tuple; private: GpgContext& ctx_ = diff --git a/src/core/function/gpg/GpgComponentInfoGetter.cpp b/src/core/function/gpg/GpgComponentInfoGetter.cpp deleted file mode 100644 index 317f334f..00000000 --- a/src/core/function/gpg/GpgComponentInfoGetter.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (C) 2021-2024 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend 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 GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#include "GpgComponentInfoGetter.h" - -namespace GpgFrontend { - -GpgComponentInfoGetter::GpgComponentInfoGetter(int channel) - : GpgFrontend::SingletonFunctionObject(channel) {} - -auto GpgComponentInfoGetter::GetGpgAgentVersion() -> QString { - if (!gpg_agent_version_.isEmpty()) return gpg_agent_version_; - - auto [r, s] = - assuan_.SendDataCommand(GpgComponentType::kGPG_AGENT, "GETINFO version"); - if (s.isEmpty()) { - LOG_D() << "invalid response of GETINFO version: " << s; - return {}; - } - - gpg_agent_version_ = s.front(); - return gpg_agent_version_; -} - -auto GpgComponentInfoGetter::GetScdaemonVersion() -> QString { - if (!scdaemon_version_.isEmpty()) return scdaemon_version_; - - auto [r, s] = assuan_.SendDataCommand(GpgComponentType::kGPG_AGENT, - "SCD GETINFO version"); - if (s.isEmpty()) { - LOG_D() << "invalid response of SCD GETINFO version: " << s; - return {}; - } - - scdaemon_version_ = s.front(); - return scdaemon_version_; -} - -} // namespace GpgFrontend \ No newline at end of file diff --git a/src/core/function/gpg/GpgComponentInfoGetter.h b/src/core/function/gpg/GpgComponentInfoGetter.h deleted file mode 100644 index 3f8b560b..00000000 --- a/src/core/function/gpg/GpgComponentInfoGetter.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (C) 2021-2024 Saturneric - * - * This file is part of GpgFrontend. - * - * GpgFrontend 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 3 of the License, or - * (at your option) any later version. - * - * GpgFrontend 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 GpgFrontend. If not, see . - * - * The initial version of the source code is inherited from - * the gpg4usb project, which is under GPL-3.0-or-later. - * - * All the source code of GpgFrontend was modified and released by - * Saturneric starting on May 12, 2021. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#pragma once - -#include "core/function/gpg/GpgAssuanHelper.h" -#include "core/function/gpg/GpgContext.h" - -namespace GpgFrontend { - -class GPGFRONTEND_CORE_EXPORT GpgComponentInfoGetter - : public SingletonFunctionObject { - public: - /** - * @brief Construct a new Gpg Assuan Helper object - * - * @param channel - */ - explicit GpgComponentInfoGetter(int channel); - - /** - * @brief - * - * @return true - * @return false - */ - auto GetGpgAgentVersion() -> QString; - - /** - * @brief - * - * @return true - * @return false - */ - auto GetScdaemonVersion() -> QString; - - private: - GpgContext& ctx_ = - GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); - GpgAssuanHelper& assuan_ = - GpgAssuanHelper::GetInstance(SingletonFunctionObject::GetChannel()); - - QString gpg_agent_version_; - QString scdaemon_version_; -}; - -}; // namespace GpgFrontend \ No newline at end of file diff --git a/src/core/function/gpg/GpgComponentManager.cpp b/src/core/function/gpg/GpgComponentManager.cpp new file mode 100644 index 00000000..1b302631 --- /dev/null +++ b/src/core/function/gpg/GpgComponentManager.cpp @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2021-2024 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend 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 GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GpgComponentManager.h" + +namespace GpgFrontend { + +GpgComponentManager::GpgComponentManager(int channel) + : GpgFrontend::SingletonFunctionObject(channel) {} + +auto GpgComponentManager::GetGpgAgentVersion() -> QString { + if (!gpg_agent_version_.isEmpty()) return gpg_agent_version_; + + auto [r, s] = + assuan_.SendDataCommand(GpgComponentType::kGPG_AGENT, "GETINFO version"); + if (s.isEmpty()) { + LOG_D() << "invalid response of GETINFO version: " << s; + return {}; + } + + gpg_agent_version_ = s.front(); + return gpg_agent_version_; +} + +auto GpgComponentManager::GetScdaemonVersion() -> QString { + if (!scdaemon_version_.isEmpty()) return scdaemon_version_; + + auto [r, s] = assuan_.SendDataCommand(GpgComponentType::kGPG_AGENT, + "SCD GETINFO version"); + if (s.isEmpty()) { + LOG_D() << "invalid response of SCD GETINFO version: " << s; + return {}; + } + + scdaemon_version_ = s.front(); + return scdaemon_version_; +} + +auto GpgComponentManager::ReloadGpgAgent() -> bool { + auto [r, s] = + assuan_.SendStatusCommand(GpgComponentType::kGPG_AGENT, "RELOADAGENT"); + if (r != GPG_ERR_NO_ERROR) { + LOG_D() << "invalid response of RELOADAGENT: " << s; + return false; + } + + return true; +} + +auto GpgComponentManager::GpgKillAgent() -> bool { + auto [r, s] = + assuan_.SendStatusCommand(GpgComponentType::kGPG_AGENT, "KILLAGENT"); + if (r != GPG_ERR_NO_ERROR) { + LOG_D() << "invalid response of KILLAGENT: " << s; + return false; + } + + return true; +} + +} // namespace GpgFrontend \ No newline at end of file diff --git a/src/core/function/gpg/GpgComponentManager.h b/src/core/function/gpg/GpgComponentManager.h new file mode 100644 index 00000000..cfd6a99f --- /dev/null +++ b/src/core/function/gpg/GpgComponentManager.h @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2021-2024 Saturneric + * + * This file is part of GpgFrontend. + * + * GpgFrontend 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 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend 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 GpgFrontend. If not, see . + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/function/gpg/GpgAssuanHelper.h" +#include "core/function/gpg/GpgContext.h" + +namespace GpgFrontend { + +class GPGFRONTEND_CORE_EXPORT GpgComponentManager + : public SingletonFunctionObject { + public: + /** + * @brief Construct a new Gpg Assuan Helper object + * + * @param channel + */ + explicit GpgComponentManager(int channel); + + /** + * @brief + * + * @return true + * @return false + */ + auto GetGpgAgentVersion() -> QString; + + /** + * @brief + * + * @return true + * @return false + */ + auto GetScdaemonVersion() -> QString; + + /** + * @brief + * + */ + auto ReloadGpgAgent() -> bool; + + /** + * @brief + * + * @return true + * @return false + */ + auto GpgKillAgent() -> bool; + + private: + GpgContext& ctx_ = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); + GpgAssuanHelper& assuan_ = + GpgAssuanHelper::GetInstance(SingletonFunctionObject::GetChannel()); + + QString gpg_agent_version_; + QString scdaemon_version_; +}; + +}; // namespace GpgFrontend \ No newline at end of file diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 7c7cde3d..49d39650 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -137,10 +137,10 @@ class GpgContext::Impl { gpgconf_path_(Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gpgconf_path", QString{})), database_path_(args.db_path), - agent_(parent->GetChannel(), - Module::RetrieveRTValueTypedOrDefault<>( - "core", "gnupg.components.gpg-agent.path", QString{}), - args.db_path) { + gpg_agent_path_(Module::RetrieveRTValueTypedOrDefault<>( + "core", "gnupg.components.gpg-agent.path", QString{})), + agent_(QSharedPointer::create( + parent->GetChannel(), gpg_agent_path_, database_path_)) { init(args); } @@ -273,6 +273,18 @@ class GpgContext::Impl { [[nodiscard]] auto KeyDBName() const -> QString { return db_name_; } + auto RestartGpgAgent() -> bool { + if (agent_ != nullptr) { + agent_ = QSharedPointer::create( + parent_->GetChannel(), gpg_agent_path_, database_path_); + } + + // ensure all gpg-agent are killed. + kill_gpg_agent(); + + return launch_gpg_agent(); + } + private: GpgContext *parent_; GpgContextInitArgs args_{}; ///< @@ -286,8 +298,9 @@ class GpgContext::Impl { QString db_name_; QString gpgconf_path_; QString database_path_; + QString gpg_agent_path_; QMap component_dirs_; - GpgAgentProcess agent_; + QSharedPointer agent_; void init(const GpgContextInitArgs &args) { assert(!gpgconf_path_.isEmpty()); @@ -551,8 +564,8 @@ class GpgContext::Impl { } auto launch_gpg_agent() -> bool { - agent_.Start(); - return true; + if (agent_ == nullptr) return false; + return agent_->Start(); } }; @@ -583,4 +596,6 @@ auto GpgContext::ComponentDirectory(GpgComponentType type) const -> QString { } auto GpgContext::KeyDBName() const -> QString { return p_->KeyDBName(); } + +auto GpgContext::RestartGpgAgent() -> bool { return p_->RestartGpgAgent(); } } // namespace GpgFrontend \ No newline at end of file diff --git a/src/core/function/gpg/GpgContext.h b/src/core/function/gpg/GpgContext.h index 350c153e..57df610c 100644 --- a/src/core/function/gpg/GpgContext.h +++ b/src/core/function/gpg/GpgContext.h @@ -65,18 +65,57 @@ class GPGFRONTEND_CORE_EXPORT GpgContext ~GpgContext(); + /** + * @brief + * + * @return true + * @return false + */ [[nodiscard]] auto Good() const -> bool; + /** + * @brief + * + * @return gpgme_ctx_t + */ auto BinaryContext() -> gpgme_ctx_t; + /** + * @brief + * + * @return gpgme_ctx_t + */ auto DefaultContext() -> gpgme_ctx_t; + /** + * @brief + * + * @return QString + */ [[nodiscard]] auto KeyDBName() const -> QString; + /** + * @brief + * + * @return QString + */ [[nodiscard]] auto HomeDirectory() const -> QString; + /** + * @brief + * + * @return QString + */ [[nodiscard]] auto ComponentDirectory(GpgComponentType) const -> QString; + /** + * @brief + * + * @return true + * @return false + */ + auto RestartGpgAgent() -> bool; + private: class Impl; SecureUniquePtr p_; diff --git a/src/core/function/gpg/GpgSmartCardManager.h b/src/core/function/gpg/GpgSmartCardManager.h index 02b07fa2..95fcd7c7 100644 --- a/src/core/function/gpg/GpgSmartCardManager.h +++ b/src/core/function/gpg/GpgSmartCardManager.h @@ -30,7 +30,7 @@ #include "core/function/basic/GpgFunctionObject.h" #include "core/function/gpg/GpgAssuanHelper.h" -#include "core/function/gpg/GpgComponentInfoGetter.h" +#include "core/function/gpg/GpgComponentManager.h" #include "core/function/gpg/GpgContext.h" #include "core/model/GpgOpenPGPCard.h" @@ -123,7 +123,7 @@ class GPGFRONTEND_CORE_EXPORT GpgSmartCardManager GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///< GpgAssuanHelper& assuan_ = GpgAssuanHelper::GetInstance(SingletonFunctionObject::GetChannel()); ///< - GpgComponentInfoGetter& info_ = GpgComponentInfoGetter::GetInstance( + GpgComponentManager& info_ = GpgComponentManager::GetInstance( SingletonFunctionObject::GetChannel()); ///< QString cached_scd_serialno_status_hash_; diff --git a/src/core/utils/GpgUtils.cpp b/src/core/utils/GpgUtils.cpp index c8f58889..c51b7e37 100644 --- a/src/core/utils/GpgUtils.cpp +++ b/src/core/utils/GpgUtils.cpp @@ -30,7 +30,7 @@ #include "core/function/GlobalSettingStation.h" #include "core/function/gpg/GpgAbstractKeyGetter.h" -#include "core/function/gpg/GpgComponentInfoGetter.h" +#include "core/function/gpg/GpgComponentManager.h" #include "core/model/GpgKey.h" #include "core/model/GpgKeyGroup.h" #include "core/model/KeyDatabaseInfo.h" @@ -430,13 +430,13 @@ auto GPGFRONTEND_CORE_EXPORT IsKeyGroupID(const KeyId& id) -> bool { auto GPGFRONTEND_CORE_EXPORT GpgAgentVersionGreaterThan(int channel, const QString& v) -> bool { return GFSoftwareVersionGreaterThan( - GpgComponentInfoGetter::GetInstance(channel).GetGpgAgentVersion(), v); + GpgComponentManager::GetInstance(channel).GetGpgAgentVersion(), v); } auto GPGFRONTEND_CORE_EXPORT CheckGpgVersion(int channel, const QString& v) -> bool { const auto ver = - GpgComponentInfoGetter::GetInstance(channel).GetGpgAgentVersion(); + GpgComponentManager::GetInstance(channel).GetGpgAgentVersion(); if (ver.isEmpty() || !GFSoftwareVersionGreaterThan(ver, v)) { LOG_W() << "operation not support for gpg-agent version: " << ver -- cgit v1.2.3