diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/GpgFrontendContext.h | 2 | ||||
-rw-r--r-- | src/core/GpgCoreInit.cpp | 10 | ||||
-rw-r--r-- | src/core/GpgCoreInit.h | 6 | ||||
-rw-r--r-- | src/core/function/SecureMemoryAllocator.h | 10 | ||||
-rw-r--r-- | src/core/function/basic/SingletonStorage.cpp | 17 | ||||
-rw-r--r-- | src/core/function/gpg/GpgContext.cpp | 129 | ||||
-rw-r--r-- | src/core/function/gpg/GpgContext.h | 3 | ||||
-rw-r--r-- | src/core/module/ModuleManager.cpp | 7 | ||||
-rw-r--r-- | src/core/module/ModuleManager.h | 7 | ||||
-rw-r--r-- | src/core/utils/MemoryUtils.h | 14 | ||||
-rw-r--r-- | src/init.cpp | 4 | ||||
-rw-r--r-- | src/main.cpp | 1 | ||||
-rw-r--r-- | src/test/core/GpgCoreTest.h | 12 |
13 files changed, 132 insertions, 90 deletions
diff --git a/src/GpgFrontendContext.h b/src/GpgFrontendContext.h index 54d2f0b8..d72fb75b 100644 --- a/src/GpgFrontendContext.h +++ b/src/GpgFrontendContext.h @@ -38,6 +38,8 @@ struct GpgFrontendContext { bool load_ui_env; std::unique_ptr<QCoreApplication> app; + bool gather_external_gnupg_info; + /** * @brief Create a Instance object * diff --git a/src/core/GpgCoreInit.cpp b/src/core/GpgCoreInit.cpp index e2aa50ff..05f3002c 100644 --- a/src/core/GpgCoreInit.cpp +++ b/src/core/GpgCoreInit.cpp @@ -193,6 +193,9 @@ auto InitGpgME() -> bool { engine_info = engine_info->next; } + // release gpgme context + gpgme_release(p_ctx); + const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gnupg_version", std::string{"0.0.0"}); SPDLOG_DEBUG("got gnupg version from rt: {}", gnupg_version); @@ -208,7 +211,7 @@ auto InitGpgME() -> bool { return true; } -void InitGpgFrontendCore() { +void InitGpgFrontendCore(CoreInitArgs args) { // initialize global register table Module::UpsertRTValue("core", "env.state.gpgme", std::string{"0"}); Module::UpsertRTValue("core", "env.state.ctx", std::string{"0"}); @@ -231,7 +234,7 @@ void InitGpgFrontendCore() { GpgFrontend::Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner() ->PostTask(new Thread::Task( - [](const DataObjectPtr&) -> int { + [args](const DataObjectPtr&) -> int { // read settings from config file auto forbid_all_gnupg_connection = GlobalSettingStation::GetInstance().LookupSettings( @@ -338,7 +341,8 @@ void InitGpgFrontendCore() { Module::UpsertRTValue("core", "env.state.ctx", std::string{"1"}); // if gnupg-info-gathering module activated - if (Module::IsModuleAcivate("com.bktus.gpgfrontend.module." + if (args.gather_external_gnupg_info && + Module::IsModuleAcivate("com.bktus.gpgfrontend.module." "integrated.gnupg-info-gathering")) { SPDLOG_DEBUG("gnupg-info-gathering is activated"); diff --git a/src/core/GpgCoreInit.h b/src/core/GpgCoreInit.h index 7666761a..33d40e58 100644 --- a/src/core/GpgCoreInit.h +++ b/src/core/GpgCoreInit.h @@ -32,6 +32,10 @@ namespace GpgFrontend { +struct CoreInitArgs { + bool gather_external_gnupg_info; +}; + /** * @brief * @@ -55,6 +59,6 @@ void GPGFRONTEND_CORE_EXPORT DestroyGpgFrontendCore(); * @brief * */ -void GPGFRONTEND_CORE_EXPORT InitGpgFrontendCore(); +void GPGFRONTEND_CORE_EXPORT InitGpgFrontendCore(CoreInitArgs); } // namespace GpgFrontend diff --git a/src/core/function/SecureMemoryAllocator.h b/src/core/function/SecureMemoryAllocator.h index a0905ba7..593172c5 100644 --- a/src/core/function/SecureMemoryAllocator.h +++ b/src/core/function/SecureMemoryAllocator.h @@ -29,6 +29,7 @@ #pragma once #include <cstdint> +#include <memory> namespace GpgFrontend { @@ -45,12 +46,17 @@ template <typename T> struct SecureObjectDeleter { void operator()(T *ptr) { if (ptr) { - SPDLOG_TRACE("secure object deleter trys to free object, obj: {}", - static_cast<void *>(ptr)); + SPDLOG_TRACE( + "secure object deleter trys to deconstruct and free object, " + "type: {}, addr: {}", + typeid(T).name(), static_cast<void *>(ptr)); ptr->~T(); SecureMemoryAllocator::Deallocate(ptr); } } }; +template <typename T> +using UniquePtrWithSecureDeleter = std::unique_ptr<T, SecureObjectDeleter<T>>; + } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/basic/SingletonStorage.cpp b/src/core/function/basic/SingletonStorage.cpp index 211a51b3..4786ad93 100644 --- a/src/core/function/basic/SingletonStorage.cpp +++ b/src/core/function/basic/SingletonStorage.cpp @@ -71,7 +71,8 @@ class SingletonStorage::Impl { auto SetObjectInChannel(int channel, ChannelObjectPtr p_obj) -> GpgFrontend::ChannelObject* { { - SPDLOG_TRACE("set channel object in channel: {}, address: {}", channel, + SPDLOG_TRACE("set channel object, type: {} in channel: {}, address: {}", + typeid(p_obj.get()).name(), channel, static_cast<void*>(p_obj.get())); assert(p_obj != nullptr); @@ -84,12 +85,14 @@ class SingletonStorage::Impl { p_obj->SetChannel(channel); auto* raw_obj = p_obj.get(); - SPDLOG_TRACE( - "register channel object to instances map, " - "channel: {}, address: {}", - channel, static_cast<void*>(p_obj.get())); - std::unique_lock<std::shared_mutex> lock(instances_mutex_); - instances_map_.insert({channel, std::move(p_obj)}); + { + SPDLOG_TRACE( + "register channel object to instances map, " + "channel: {}, address: {}", + channel, static_cast<void*>(p_obj.get())); + std::unique_lock<std::shared_mutex> lock(instances_mutex_); + instances_map_[channel] = std::move(p_obj); + } SPDLOG_TRACE( "set channel: {} success, current channel object address: {}", diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 9b24af3c..20ccf70f 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -38,6 +38,7 @@ #include "core/module/ModuleManager.h" #include "core/utils/GpgUtils.h" #include "spdlog/spdlog.h" +#include "utils/MemoryUtils.h" #ifdef _WIN32 #include <windows.h> @@ -45,15 +46,6 @@ namespace GpgFrontend { -struct CtxRefDeleter { - void operator()(gpgme_ctx_t _ctx) { - if (_ctx != nullptr) gpgme_release(_ctx); - } -}; - -using CtxRefHandler = - std::unique_ptr<struct gpgme_context, CtxRefDeleter>; ///< - class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { public: /** @@ -66,25 +58,33 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { args_(args), good_(default_ctx_initialize(args) && binary_ctx_initialize(args)) {} - [[nodiscard]] auto BinaryContext() const -> gpgme_ctx_t { - return binary_ctx_ref_.get(); + ~Impl() { + if (ctx_ref_ != nullptr) { + gpgme_release(ctx_ref_); + } + + if (binary_ctx_ref_ != nullptr) { + gpgme_release(binary_ctx_ref_); + } } - [[nodiscard]] auto DefaultContext() const -> gpgme_ctx_t { - return ctx_ref_.get(); + [[nodiscard]] auto BinaryContext() const -> gpgme_ctx_t { + return binary_ctx_ref_; } + [[nodiscard]] auto DefaultContext() const -> gpgme_ctx_t { return ctx_ref_; } + [[nodiscard]] auto Good() const -> bool { return good_; } - auto SetPassphraseCb(const CtxRefHandler &ctx, gpgme_passphrase_cb_t cb) + auto SetPassphraseCb(const gpgme_ctx_t &ctx, gpgme_passphrase_cb_t cb) -> bool { - if (gpgme_get_pinentry_mode(ctx.get()) != GPGME_PINENTRY_MODE_LOOPBACK) { + if (gpgme_get_pinentry_mode(ctx) != GPGME_PINENTRY_MODE_LOOPBACK) { if (CheckGpgError(gpgme_set_pinentry_mode( - ctx.get(), GPGME_PINENTRY_MODE_LOOPBACK)) != GPG_ERR_NO_ERROR) { + ctx, GPGME_PINENTRY_MODE_LOOPBACK)) != GPG_ERR_NO_ERROR) { return false; } } - gpgme_set_passphrase_cb(ctx.get(), cb, reinterpret_cast<void *>(parent_)); + gpgme_set_passphrase_cb(ctx, cb, reinterpret_cast<void *>(parent_)); return true; } @@ -154,19 +154,19 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { private: GpgContext *parent_; - GpgContextInitArgs args_{}; ///< - CtxRefHandler ctx_ref_ = nullptr; ///< - CtxRefHandler binary_ctx_ref_ = nullptr; ///< + GpgContextInitArgs args_{}; ///< + gpgme_ctx_t ctx_ref_ = nullptr; ///< + gpgme_ctx_t binary_ctx_ref_ = nullptr; ///< bool good_ = true; - static auto set_ctx_key_list_mode(const CtxRefHandler &ctx) -> bool { - assert(ctx.get() != nullptr); + static auto set_ctx_key_list_mode(const gpgme_ctx_t &ctx) -> bool { + assert(ctx != nullptr); const auto gpgme_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.version", std::string{"0.0.0"}); SPDLOG_DEBUG("got gpgme version version from rt: {}", gpgme_version); - if (gpgme_get_keylist_mode(ctx.get()) == 0) { + if (gpgme_get_keylist_mode(ctx) == 0) { SPDLOG_ERROR( "ctx is not a valid pointer, reported by gpgme_get_keylist_mode"); return false; @@ -174,20 +174,47 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { // set keylist mode return CheckGpgError(gpgme_set_keylist_mode( - ctx.get(), - GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | - GPGME_KEYLIST_MODE_SIGS | GPGME_KEYLIST_MODE_SIG_NOTATIONS | - GPGME_KEYLIST_MODE_WITH_TOFU)) == GPG_ERR_NO_ERROR; + ctx, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | + GPGME_KEYLIST_MODE_SIGS | + GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_WITH_TOFU)) == GPG_ERR_NO_ERROR; } - auto common_ctx_initialize(const CtxRefHandler &ctx, + static auto set_ctx_openpgp_engine_info(gpgme_ctx_t ctx) -> bool { + const auto app_path = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.app_path", std::string{}); + const auto database_path = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.database_path", std::string{}); + + SPDLOG_DEBUG("ctx set engine info, db path: {}, app path: {}", + database_path, app_path); + + const char *app_path_c_str = app_path.c_str(); + const char *db_path_c_str = database_path.c_str(); + + if (app_path.empty()) { + app_path_c_str = nullptr; + } + + if (database_path.empty()) { + db_path_c_str = nullptr; + } + + auto err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, + app_path_c_str, db_path_c_str); + + assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); + return CheckGpgError(err) == GPG_ERR_NO_ERROR; + } + + auto common_ctx_initialize(const gpgme_ctx_t &ctx, const GpgContextInitArgs &args) -> bool { - assert(ctx.get() != nullptr); + assert(ctx != nullptr); if (args.custom_gpgconf && !args.custom_gpgconf_path.empty()) { SPDLOG_DEBUG("set custom gpgconf path: {}", args.custom_gpgconf_path); auto err = - gpgme_ctx_set_engine_info(ctx.get(), GPGME_PROTOCOL_GPGCONF, + gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_GPGCONF, args.custom_gpgconf_path.c_str(), nullptr); assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); @@ -198,14 +225,14 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { // set context offline mode SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); - gpgme_set_offline(ctx.get(), args_.offline_mode ? 1 : 0); + gpgme_set_offline(ctx, args_.offline_mode ? 1 : 0); // set option auto import missing key // invalid at offline mode SPDLOG_DEBUG("gpg context auto import missing key: {}", args_.offline_mode); if (!args.offline_mode && args.auto_import_missing_key) { - if (CheckGpgError(gpgme_set_ctx_flag(ctx.get(), "auto-key-import", - "1")) != GPG_ERR_NO_ERROR) { + if (CheckGpgError(gpgme_set_ctx_flag(ctx, "auto-key-import", "1")) != + GPG_ERR_NO_ERROR) { return false; } } @@ -232,21 +259,11 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { if (!args_.db_path.empty()) { Module::UpsertRTValue("core", "gpgme.ctx.database_path", std::string(args_.db_path)); + } - const auto app_path = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.app_path", std::string{}); - const auto database_path = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.database_path", std::string{}); - - auto err = - gpgme_ctx_set_engine_info(ctx_ref_.get(), GPGME_PROTOCOL_OpenPGP, - app_path.c_str(), database_path.c_str()); - SPDLOG_DEBUG("ctx set custom key db path: {}", database_path); - - assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); - if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { - return false; - } + if (!set_ctx_openpgp_engine_info(ctx)) { + SPDLOG_ERROR("set gpgme context openpgp engine info failed"); + return false; } return true; @@ -258,7 +275,7 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { return false; } assert(p_ctx != nullptr); - binary_ctx_ref_ = CtxRefHandler(p_ctx); + binary_ctx_ref_ = p_ctx; if (!common_ctx_initialize(binary_ctx_ref_, args)) { SPDLOG_ERROR("get new ctx failed, binary"); @@ -267,7 +284,7 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { /** Setting the output type must be done at the beginning */ /** think this means ascii-armor --> ? */ - gpgme_set_armor(binary_ctx_ref_.get(), 0); + gpgme_set_armor(binary_ctx_ref_, 0); return true; } @@ -278,24 +295,24 @@ class GpgContext::Impl : public SingletonFunctionObject<GpgContext::Impl> { return false; } assert(p_ctx != nullptr); - ctx_ref_ = CtxRefHandler(p_ctx); + ctx_ref_ = p_ctx; - if (!common_ctx_initialize(ctx_ref_, args)) { - return false; - } + // if (!common_ctx_initialize(ctx_ref_, args)) { + // return false; + // } - gpgme_set_armor(ctx_ref_.get(), 1); + // gpgme_set_armor(ctx_ref_, 1); return true; } }; GpgContext::GpgContext(int channel) : SingletonFunctionObject<GpgContext>(channel), - p_(std::make_unique<Impl>(this, GpgContextInitArgs{}, channel)) {} + p_(SecureCreateUniqueObject<Impl>(this, GpgContextInitArgs{}, channel)) {} GpgContext::GpgContext(const GpgContextInitArgs &args, int channel) : SingletonFunctionObject<GpgContext>(channel), - p_(std::make_unique<Impl>(this, args, channel)) {} + p_(SecureCreateUniqueObject<Impl>(this, args, channel)) {} auto GpgContext::Good() const -> bool { return p_->Good(); } diff --git a/src/core/function/gpg/GpgContext.h b/src/core/function/gpg/GpgContext.h index b53344fd..5f6b5b86 100644 --- a/src/core/function/gpg/GpgContext.h +++ b/src/core/function/gpg/GpgContext.h @@ -28,6 +28,7 @@ #pragma once +#include "core/function/SecureMemoryAllocator.h" #include "core/function/basic/GpgFunctionObject.h" namespace GpgFrontend { @@ -72,6 +73,6 @@ class GPGFRONTEND_CORE_EXPORT GpgContext private: class Impl; - std::unique_ptr<Impl> p_; + UniquePtrWithSecureDeleter<Impl> p_; }; } // namespace GpgFrontend diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp index 03ac21a8..26974f1c 100644 --- a/src/core/module/ModuleManager.cpp +++ b/src/core/module/ModuleManager.cpp @@ -36,11 +36,10 @@ #include "core/module/Module.h" #include "core/thread/Task.h" #include "core/thread/TaskRunner.h" +#include "utils/MemoryUtils.h" namespace GpgFrontend::Module { -ModuleMangerPtr ModuleManager::g_ = nullptr; - class ModuleManager::Impl { public: Impl() @@ -138,8 +137,8 @@ ModuleManager::ModuleManager() : p_(std::make_unique<Impl>()) {} ModuleManager::~ModuleManager() = default; auto ModuleManager::GetInstance() -> ModuleMangerPtr { - if (g_ == nullptr) g_ = std::shared_ptr<ModuleManager>(new ModuleManager()); - return g_; + static ModuleMangerPtr g = SecureCreateSharedObject<ModuleManager>(); + return g; } void ModuleManager::RegisterModule(ModulePtr module) { diff --git a/src/core/module/ModuleManager.h b/src/core/module/ModuleManager.h index bc05860b..1b1133da 100644 --- a/src/core/module/ModuleManager.h +++ b/src/core/module/ModuleManager.h @@ -57,7 +57,9 @@ using LPCallback = std::function<void(Namespace, Key, int, std::any)>; class GPGFRONTEND_CORE_EXPORT ModuleManager : public QObject { Q_OBJECT public: - ~ModuleManager() override; + ModuleManager(); + + virtual ~ModuleManager() override; static auto GetInstance() -> ModuleMangerPtr; @@ -85,9 +87,6 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager : public QObject { private: class Impl; std::unique_ptr<Impl> p_; - static ModuleMangerPtr g_; - - ModuleManager(); }; template <typename T, typename... Args> diff --git a/src/core/utils/MemoryUtils.h b/src/core/utils/MemoryUtils.h index 6cbbfec8..4c68e864 100644 --- a/src/core/utils/MemoryUtils.h +++ b/src/core/utils/MemoryUtils.h @@ -112,8 +112,8 @@ template <typename T, typename... Args> static auto SecureCreateObject(Args &&...args) -> T * { void *mem = SecureMemoryAllocator::Allocate(sizeof(T)); if (!mem) return nullptr; - SPDLOG_TRACE("alloc secure memnory success, mem: {}", - static_cast<void *>(mem)); + SPDLOG_TRACE("alloc secure memnory success, type: {}, size: {}, addr: {}", + typeid(T).name(), sizeof(T), mem); try { return new (mem) T(std::forward<Args>(args)...); @@ -137,8 +137,9 @@ static auto SecureCreateUniqueObject(Args &&...args) -> std::unique_ptr<T, SecureObjectDeleter<T>> { void *mem = SecureMemoryAllocator::Allocate(sizeof(T)); if (!mem) throw std::bad_alloc(); - SPDLOG_TRACE("alloc secure memnory success, unique ptr, type: {}, mem: {}", - typeid(T).name(), mem); + SPDLOG_TRACE( + "alloc secure memnory success, unique ptr, type: {}, size: {}, addr: {}", + typeid(T).name(), sizeof(T), mem); try { return std::unique_ptr<T, SecureObjectDeleter<T>>( @@ -153,8 +154,9 @@ template <typename T, typename... Args> auto SecureCreateSharedObject(Args &&...args) -> std::shared_ptr<T> { void *mem = SecureMemoryAllocator::Allocate(sizeof(T)); if (!mem) throw std::bad_alloc(); - SPDLOG_TRACE("alloc secure memnory success, shared ptr, type: {}, mem: {}", - typeid(T).name(), mem); + SPDLOG_TRACE( + "alloc secure memnory success, shared ptr, type: {}, size: {}, addr: {}", + typeid(T).name(), sizeof(T), mem); try { T *obj = new (mem) T(std::forward<Args>(args)...); diff --git a/src/init.cpp b/src/init.cpp index 77007ff1..02e90836 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -186,8 +186,10 @@ void InitGlobalBasicalEnv(const GFCxtWPtr &p_ctx) { UI::PreInitGpgFrontendUI(); } + CoreInitArgs core_init_args; + core_init_args.gather_external_gnupg_info = ctx->gather_external_gnupg_info; // then load core - InitGpgFrontendCore(); + InitGpgFrontendCore(core_init_args); } void ShutdownGlobalBasicalEnv(const GFCxtWPtr &p_ctx) { diff --git a/src/main.cpp b/src/main.cpp index a37506a1..0ee4f200 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,6 +99,7 @@ auto main(int argc, char* argv[]) -> int { } if (vm.count("test") != 0U) { + ctx->gather_external_gnupg_info = false; InitGlobalBasicalEnv(p_ctx); return RunTest(ctx); } diff --git a/src/test/core/GpgCoreTest.h b/src/test/core/GpgCoreTest.h index 5730b6e5..22504f5d 100644 --- a/src/test/core/GpgCoreTest.h +++ b/src/test/core/GpgCoreTest.h @@ -28,7 +28,9 @@ #pragma once +#include <QtWidgets/qapplication.h> #include <gtest/gtest.h> +#include <qcoreapplication.h> #include <boost/date_time.hpp> #include <boost/dll.hpp> @@ -49,14 +51,14 @@ class GpgCoreTest : public ::testing::Test { private: void import_private_keys(const libconfig::Setting& root); + std::filesystem::path app_path_ = std::filesystem::path{ + QCoreApplication::applicationDirPath().toStdString()}; + // Configure File Location - std::filesystem::path config_path_ = - GlobalSettingStation::GetInstance().GetAppDir() / "test" / "conf" / - "core.cfg"; + std::filesystem::path config_path_ = app_path_ / "test" / "conf" / "core.cfg"; // Data File Directory Location - std::filesystem::path data_path_ = - GlobalSettingStation::GetInstance().GetAppDir() / "test" / "data"; + std::filesystem::path data_path_ = app_path_ / "test" / "data"; }; } // namespace GpgFrontend::Test
\ No newline at end of file |