From 0251f35c93e3f0e0a6853a50fb5bd82c1b9e4187 Mon Sep 17 00:00:00 2001 From: saturneric Date: Mon, 6 Nov 2023 17:17:47 +0800 Subject: refactor: clean up core's codes --- src/core/function/gpg/GpgContext.cpp | 399 +++++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 src/core/function/gpg/GpgContext.cpp (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp new file mode 100644 index 00000000..fb51f09f --- /dev/null +++ b/src/core/function/gpg/GpgContext.cpp @@ -0,0 +1,399 @@ +/** + * Copyright (C) 2021 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 "core/function/gpg/GpgContext.h" + +#include +#include +#include + +#include "core/GpgConstants.h" +#include "core/common/CoreCommonUtil.h" +#include "core/function/CoreSignalStation.h" +#include "core/function/basic/GpgFunctionObject.h" +#include "core/function/gpg/GpgCommandExecutor.h" +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/module/ModuleManager.h" +#include "core/thread/Task.h" +#include "core/thread/TaskRunnerGetter.h" + +#ifdef _WIN32 +#include +#endif + +namespace GpgFrontend { + +class GpgContext::Impl : public SingletonFunctionObject { + public: + /** + * Constructor + * Set up gpgme-context, set paths to app-run path + */ + Impl(GpgContext *parent, const GpgContextInitArgs &args, int channel) + : SingletonFunctionObject(channel), + parent_(parent), + args_(args) { + gpgme_ctx_t p_ctx; + + // get gpgme library version + Module::UpsertRTValue("core", "gpgme.version", + std::string(gpgme_check_version(nullptr))); + + // create a new context + CheckGpgError(gpgme_new(&p_ctx)); + ctx_ref_ = CtxRefHandler(p_ctx); + + 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_ref_.get(), GPGME_PROTOCOL_GPGCONF, + args.custom_gpgconf_path.c_str(), nullptr); + assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); + } + + // set context offline mode + SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); + gpgme_set_offline(ctx_ref_.get(), 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) { + CheckGpgError(gpgme_set_ctx_flag(ctx_ref_.get(), "auto-key-import", "1")); + } + + // get engine info + auto *engine_info = gpgme_ctx_get_engine_info(*this); + // Check ENV before running + bool check_passed = false; + bool find_openpgp = false; + bool find_gpgconf = false; + bool find_cms = false; + + while (engine_info != nullptr) { + if (strcmp(engine_info->version, "1.0.0") == 0) { + engine_info = engine_info->next; + continue; + } + + SPDLOG_DEBUG( + "gpg context engine info: {} {} {} {}", + gpgme_get_protocol_name(engine_info->protocol), + std::string(engine_info->file_name == nullptr + ? "null" + : engine_info->file_name), + std::string(engine_info->home_dir == nullptr ? "null" + : engine_info->home_dir), + std::string(engine_info->version ? "null" : engine_info->version)); + + switch (engine_info->protocol) { + case GPGME_PROTOCOL_OpenPGP: + find_openpgp = true; + + Module::UpsertRTValue("core", "gpgme.ctx.app_path", + std::string(engine_info->file_name)); + Module::UpsertRTValue("core", "gpgme.ctx.gnupg_version", + std::string(engine_info->version)); + Module::UpsertRTValue("core", "gpgme.ctx.database_path", + std::string(engine_info->home_dir == nullptr + ? "default" + : engine_info->home_dir)); + break; + case GPGME_PROTOCOL_CMS: + find_cms = true; + Module::UpsertRTValue("core", "gpgme.ctx.cms_path", + std::string(engine_info->file_name)); + + break; + case GPGME_PROTOCOL_GPGCONF: + find_gpgconf = true; + Module::UpsertRTValue("core", "gpgme.ctx.gpgconf_path", + std::string(engine_info->file_name)); + break; + case GPGME_PROTOCOL_ASSUAN: + Module::UpsertRTValue("core", "gpgme.ctx.assuan_path", + std::string(engine_info->file_name)); + break; + case GPGME_PROTOCOL_G13: + break; + case GPGME_PROTOCOL_UISERVER: + break; + case GPGME_PROTOCOL_SPAWN: + break; + case GPGME_PROTOCOL_DEFAULT: + break; + case GPGME_PROTOCOL_UNKNOWN: + break; + } + engine_info = engine_info->next; + } + + 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); + + // conditional check: only support gpg 2.x now + if ((CompareSoftwareVersion(gnupg_version, "2.0.0") >= 0 && find_gpgconf && + find_openpgp && find_cms)) { + check_passed = true; + } + + if (!check_passed) { + this->good_ = false; + SPDLOG_ERROR("env check failed"); + return; + } + + // speed up loading process + gpgme_set_offline(*this, 1); + + // set keylist mode + if (gnupg_version >= "2.0.0") { + CheckGpgError(gpgme_set_keylist_mode( + *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | + GPGME_KEYLIST_MODE_SIGS | + GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_WITH_TOFU)); + } else { + CheckGpgError(gpgme_set_keylist_mode( + *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS | + GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_WITH_TOFU)); + } + + // async, init context + Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_GPG) + ->PostTask(new Thread::Task( + [=](const DataObjectPtr &) -> int { + ctx_post_initialize(); + return 0; + }, + "ctx_post_initialize")); + + good_ = true; + } + + /** + * @brief + * + * @return gpgme_ctx_t + */ + operator gpgme_ctx_t() const { return ctx_ref_.get(); } + + [[nodiscard]] auto Good() const -> bool { return good_; } + + void SetPassphraseCb(gpgme_passphrase_cb_t cb) { + const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.gnupg_version", std::string{"2.0.0"}); + + if (CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0) { + if (gpgme_get_pinentry_mode(*this) != GPGME_PINENTRY_MODE_LOOPBACK) { + gpgme_set_pinentry_mode(*this, GPGME_PINENTRY_MODE_LOOPBACK); + } + gpgme_set_passphrase_cb(*this, cb, reinterpret_cast(parent_)); + } else { + SPDLOG_ERROR("not supported for gnupg version: {}", gnupg_version); + } + } + + static auto TestPassphraseCb(void *opaque, const char *uid_hint, + const char *passphrase_info, int last_was_bad, + int fd) -> gpgme_error_t { + size_t res; + std::string pass = "abcdefg\n"; + auto pass_len = pass.size(); + + size_t off = 0; + + do { + res = gpgme_io_write(fd, &pass[off], pass_len - off); + if (res > 0) off += res; + } while (res > 0 && off != pass_len); + + return off == pass_len ? 0 : gpgme_error_from_errno(errno); + } + + static auto CustomPassphraseCb(void *hook, const char *uid_hint, + const char *passphrase_info, int last_was_bad, + int fd) -> gpgme_error_t { + auto *p_ctx = static_cast(hook); + SPDLOG_DEBUG("custom passphrase cb called, bad times: {}", last_was_bad); + + if (last_was_bad > 3) { + SPDLOG_WARN("failure_counts is over three times"); + return gpgme_error_from_errno(GPG_ERR_CANCELED); + } + + std::string passphrase = + CoreCommonUtil::GetInstance()->GetTempCacheValue("__key_passphrase"); + // no pawword is an error situation + if (passphrase.empty()) { + // user input passphrase + SPDLOG_DEBUG("might need user to input passparase"); + passphrase = p_ctx->ShowPasswordInputDialog(); + if (passphrase.empty()) { + gpgme_io_write(fd, "\n", 1); + return gpgme_error_from_errno(GPG_ERR_CANCELED); + } + } + + // the user must at least write a newline character before returning from + // the callback. + passphrase = passphrase.append("\n"); + auto passpahrase_size = passphrase.size(); + + size_t off = 0; + size_t res = 0; + do { + res = gpgme_io_write(fd, &passphrase[off], passpahrase_size - off); + if (res > 0) off += res; + } while (res > 0 && off != passpahrase_size); + + return off == passpahrase_size ? 0 + : gpgme_error_from_errno(GPG_ERR_CANCELED); + } + + static auto TestStatusCb(void *hook, const char *keyword, const char *args) + -> gpgme_error_t { + SPDLOG_DEBUG("keyword {}", keyword); + return GPG_ERR_NO_ERROR; + } + + auto ShowPasswordInputDialog() -> std::string { + emit parent_->SignalNeedUserInputPassphrase(); + + std::string final_passphrase; + bool input_done = false; + SPDLOG_DEBUG("loop start to wait from user"); + auto connection = QObject::connect( + CoreSignalStation::GetInstance(), + &CoreSignalStation::SignalUserInputPassphraseDone, parent_, + [&](const QString &passphrase) { + SPDLOG_DEBUG("SignalUserInputPassphraseDone emitted"); + final_passphrase = passphrase.toStdString(); + input_done = true; + }); + while (!input_done) { + QCoreApplication::processEvents(QEventLoop::AllEvents, 800); + } + QObject::disconnect(connection); + + SPDLOG_DEBUG("lopper end"); + return final_passphrase; + } + + private: + struct CtxRefDeleter { + void operator()(gpgme_ctx_t _ctx) { + if (_ctx != nullptr) gpgme_release(_ctx); + } + }; + + using CtxRefHandler = + std::unique_ptr; ///< + + GpgContext *parent_; + GpgContextInitArgs args_{}; ///< + CtxRefHandler ctx_ref_ = nullptr; ///< + bool good_ = true; + + void ctx_post_initialize() { + const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( + "core", "gpgme.ctx.gnupg_version", std::string{"2.0.0"}); + + if (args_.ascii) { + /** Setting the output type must be done at the beginning */ + /** think this means ascii-armor --> ? */ + gpgme_set_armor(*this, 1); + } else { + /** Setting the output type must be done at the beginning */ + /** think this means ascii-armor --> ? */ + gpgme_set_armor(*this, 0); + } + + // for unit test + if (args_.test_mode) { + if (CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0) { + SetPassphraseCb(TestPassphraseCb); + } + gpgme_set_status_cb(*this, TestStatusCb, nullptr); + } + + if (!args_.use_pinentry) { + SetPassphraseCb(CustomPassphraseCb); + } + + // set custom key db path + 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); + } + + QObject::connect(parent_, &GpgContext::SignalNeedUserInputPassphrase, + CoreSignalStation::GetInstance(), + &CoreSignalStation::SignalNeedUserInputPassphrase); + } +}; + +GpgContext::GpgContext(int channel) + : SingletonFunctionObject(channel), + p_(std::make_unique(this, GpgContextInitArgs{}, channel)) {} + +GpgContext::GpgContext(const GpgContextInitArgs &args, int channel) + : SingletonFunctionObject(channel), + p_(std::make_unique(this, args, channel)) {} + +auto GpgContext::Good() const -> bool { return p_->Good(); } + +void GpgContext::SetPassphraseCb(gpgme_passphrase_cb_t passphrase_cb) const { + p_->SetPassphraseCb(passphrase_cb); +} + +GpgContext::operator gpgme_ctx_t() const { + return static_cast(*p_); +} + +auto GpgContext::ShowPasswordInputDialog() -> std::string { + return p_->ShowPasswordInputDialog(); +} + +GpgContext::~GpgContext() = default; + +} // namespace GpgFrontend \ No newline at end of file -- cgit v1.2.3 From 889cb8092381b073a0f4a0411a4ede04cd7bdd14 Mon Sep 17 00:00:00 2001 From: saturneric Date: Mon, 6 Nov 2023 20:49:44 +0800 Subject: refactor: improve the code structure of core --- src/core/function/gpg/GpgContext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index fb51f09f..3df684ea 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -32,7 +32,6 @@ #include #include -#include "core/GpgConstants.h" #include "core/common/CoreCommonUtil.h" #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" @@ -41,6 +40,8 @@ #include "core/module/ModuleManager.h" #include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" +#include "core/utils/CommonUtils.h" +#include "core/utils/GpgUtils.h" #ifdef _WIN32 #include -- cgit v1.2.3 From 3ad7fecdb6458fdd6f146bed19fe643c7f93e905 Mon Sep 17 00:00:00 2001 From: saturneric Date: Tue, 7 Nov 2023 15:18:06 +0800 Subject: refactor: remove CommonUtils at core --- src/core/function/gpg/GpgContext.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 3df684ea..fe8dc5cd 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -32,7 +32,6 @@ #include #include -#include "core/common/CoreCommonUtil.h" #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" #include "core/function/gpg/GpgCommandExecutor.h" @@ -40,6 +39,7 @@ #include "core/module/ModuleManager.h" #include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" +#include "core/utils/CacheUtils.h" #include "core/utils/CommonUtils.h" #include "core/utils/GpgUtils.h" @@ -251,8 +251,7 @@ class GpgContext::Impl : public SingletonFunctionObject { return gpgme_error_from_errno(GPG_ERR_CANCELED); } - std::string passphrase = - CoreCommonUtil::GetInstance()->GetTempCacheValue("__key_passphrase"); + std::string passphrase = GetTempCacheValue("__key_passphrase"); // no pawword is an error situation if (passphrase.empty()) { // user input passphrase -- cgit v1.2.3 From 9ea9c03263ad14c09d02cc3a9d25c9e890581046 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 1 Dec 2023 20:38:52 +0800 Subject: fix: discover and fix some bugs --- src/core/function/gpg/GpgContext.cpp | 39 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index fe8dc5cd..e6975ea4 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include "core/function/CoreSignalStation.h" @@ -42,6 +44,7 @@ #include "core/utils/CacheUtils.h" #include "core/utils/CommonUtils.h" #include "core/utils/GpgUtils.h" +#include "spdlog/spdlog.h" #ifdef _WIN32 #include @@ -256,8 +259,15 @@ class GpgContext::Impl : public SingletonFunctionObject { if (passphrase.empty()) { // user input passphrase SPDLOG_DEBUG("might need user to input passparase"); - passphrase = p_ctx->ShowPasswordInputDialog(); + + p_ctx->ShowPasswordInputDialog(); + passphrase = GetTempCacheValue("__key_passphrase"); + + SPDLOG_DEBUG("use may has inputed the passphrase"); + if (passphrase.empty()) { + SPDLOG_ERROR("cannot get passphrase from use or passphrase is empty"); + gpgme_io_write(fd, "\n", 1); return gpgme_error_from_errno(GPG_ERR_CANCELED); } @@ -285,27 +295,16 @@ class GpgContext::Impl : public SingletonFunctionObject { return GPG_ERR_NO_ERROR; } - auto ShowPasswordInputDialog() -> std::string { + void ShowPasswordInputDialog() { emit parent_->SignalNeedUserInputPassphrase(); - std::string final_passphrase; - bool input_done = false; - SPDLOG_DEBUG("loop start to wait from user"); - auto connection = QObject::connect( - CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalUserInputPassphraseDone, parent_, - [&](const QString &passphrase) { - SPDLOG_DEBUG("SignalUserInputPassphraseDone emitted"); - final_passphrase = passphrase.toStdString(); - input_done = true; - }); - while (!input_done) { - QCoreApplication::processEvents(QEventLoop::AllEvents, 800); - } - QObject::disconnect(connection); + QEventLoop looper; + QObject::connect(CoreSignalStation::GetInstance(), + &CoreSignalStation::SignalUserInputPassphraseDone, &looper, + &QEventLoop::quit); + looper.exec(); - SPDLOG_DEBUG("lopper end"); - return final_passphrase; + SPDLOG_DEBUG("show password input dialog done"); } private: @@ -390,7 +389,7 @@ GpgContext::operator gpgme_ctx_t() const { return static_cast(*p_); } -auto GpgContext::ShowPasswordInputDialog() -> std::string { +void GpgContext::ShowPasswordInputDialog() { return p_->ShowPasswordInputDialog(); } -- cgit v1.2.3 From 0ec3358e4cfce7ad242e851c450292a25619221e Mon Sep 17 00:00:00 2001 From: saturneric Date: Sat, 2 Dec 2023 06:01:16 -0800 Subject: feat: add buddled qt pinentry and make it works --- src/core/function/gpg/GpgContext.cpp | 80 +++++++++++++++--------------------- 1 file changed, 33 insertions(+), 47 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index e6975ea4..9ee81bad 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -30,10 +30,19 @@ #include #include +#include +#include +#include #include +#include #include +#include +#include +#include #include +#include + #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" #include "core/function/gpg/GpgCommandExecutor.h" @@ -44,6 +53,7 @@ #include "core/utils/CacheUtils.h" #include "core/utils/CommonUtils.h" #include "core/utils/GpgUtils.h" +#include "function/CacheManager.h" #include "spdlog/spdlog.h" #ifdef _WIN32 @@ -247,36 +257,28 @@ class GpgContext::Impl : public SingletonFunctionObject { const char *passphrase_info, int last_was_bad, int fd) -> gpgme_error_t { auto *p_ctx = static_cast(hook); - SPDLOG_DEBUG("custom passphrase cb called, bad times: {}", last_was_bad); - - if (last_was_bad > 3) { - SPDLOG_WARN("failure_counts is over three times"); - return gpgme_error_from_errno(GPG_ERR_CANCELED); - } + std::string passphrase; - std::string passphrase = GetTempCacheValue("__key_passphrase"); - // no pawword is an error situation - if (passphrase.empty()) { - // user input passphrase - SPDLOG_DEBUG("might need user to input passparase"); + SPDLOG_DEBUG( + "custom passphrase cb called, uid: {}, info: {}, last_was_bad: {}", + uid_hint == nullptr ? "" : std::string{uid_hint}, + passphrase_info == nullptr ? "" : std::string{passphrase_info}, + last_was_bad); - p_ctx->ShowPasswordInputDialog(); - passphrase = GetTempCacheValue("__key_passphrase"); + emit CoreSignalStation::GetInstance()->SignalNeedUserInputPassphrase(); - SPDLOG_DEBUG("use may has inputed the passphrase"); - - if (passphrase.empty()) { - SPDLOG_ERROR("cannot get passphrase from use or passphrase is empty"); - - gpgme_io_write(fd, "\n", 1); - return gpgme_error_from_errno(GPG_ERR_CANCELED); - } - } + QEventLoop looper; + QObject::connect( + CoreSignalStation::GetInstance(), + &CoreSignalStation::SignalUserInputPassphraseCallback, &looper, + [&](const QByteArray &buffer) { passphrase = buffer.toStdString(); }); + QObject::connect(CoreSignalStation::GetInstance(), + &CoreSignalStation::SignalUserInputPassphraseCallback, + &looper, &QEventLoop::quit); + looper.exec(); - // the user must at least write a newline character before returning from - // the callback. - passphrase = passphrase.append("\n"); auto passpahrase_size = passphrase.size(); + SPDLOG_DEBUG("get passphrase from pinentry size: {}", passpahrase_size); size_t off = 0; size_t res = 0; @@ -285,8 +287,12 @@ class GpgContext::Impl : public SingletonFunctionObject { if (res > 0) off += res; } while (res > 0 && off != passpahrase_size); - return off == passpahrase_size ? 0 - : gpgme_error_from_errno(GPG_ERR_CANCELED); + res += gpgme_io_write(fd, "\n", 1); + + SPDLOG_DEBUG("custom passphrase cd is about to return, res: {}", res); + return res == passpahrase_size + 1 + ? 0 + : gpgme_error_from_errno(GPG_ERR_CANCELED); } static auto TestStatusCb(void *hook, const char *keyword, const char *args) @@ -295,18 +301,6 @@ class GpgContext::Impl : public SingletonFunctionObject { return GPG_ERR_NO_ERROR; } - void ShowPasswordInputDialog() { - emit parent_->SignalNeedUserInputPassphrase(); - - QEventLoop looper; - QObject::connect(CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalUserInputPassphraseDone, &looper, - &QEventLoop::quit); - looper.exec(); - - SPDLOG_DEBUG("show password input dialog done"); - } - private: struct CtxRefDeleter { void operator()(gpgme_ctx_t _ctx) { @@ -364,10 +358,6 @@ class GpgContext::Impl : public SingletonFunctionObject { SPDLOG_DEBUG("ctx set custom key db path: {}", database_path); assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); } - - QObject::connect(parent_, &GpgContext::SignalNeedUserInputPassphrase, - CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalNeedUserInputPassphrase); } }; @@ -389,10 +379,6 @@ GpgContext::operator gpgme_ctx_t() const { return static_cast(*p_); } -void GpgContext::ShowPasswordInputDialog() { - return p_->ShowPasswordInputDialog(); -} - GpgContext::~GpgContext() = default; } // namespace GpgFrontend \ No newline at end of file -- cgit v1.2.3 From e0bc882bd46c40c86d9497fa043bbfe3e469888f Mon Sep 17 00:00:00 2001 From: saturneric Date: Sat, 2 Dec 2023 23:28:41 -0800 Subject: feat: introduce mimalloc to replace secmem --- src/core/function/gpg/GpgContext.cpp | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 9ee81bad..a6040231 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -30,18 +30,6 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" @@ -54,7 +42,6 @@ #include "core/utils/CommonUtils.h" #include "core/utils/GpgUtils.h" #include "function/CacheManager.h" -#include "spdlog/spdlog.h" #ifdef _WIN32 #include -- cgit v1.2.3 From 883db05d54510e76b6548e107593187e1306117d Mon Sep 17 00:00:00 2001 From: saturneric Date: Sun, 3 Dec 2023 04:28:46 -0800 Subject: feat: general improvements of aync execution and memory security --- src/core/function/gpg/GpgContext.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index a6040231..40a70cee 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -243,7 +243,6 @@ class GpgContext::Impl : public SingletonFunctionObject { static auto CustomPassphraseCb(void *hook, const char *uid_hint, const char *passphrase_info, int last_was_bad, int fd) -> gpgme_error_t { - auto *p_ctx = static_cast(hook); std::string passphrase; SPDLOG_DEBUG( -- cgit v1.2.3 From 054e6e28cca2517dda2319ef683314b3318c39a6 Mon Sep 17 00:00:00 2001 From: saturneric Date: Sun, 3 Dec 2023 12:25:21 -0800 Subject: feat: standarized and speed up app env loading process --- src/core/function/gpg/GpgContext.cpp | 334 ++++++++++++++--------------------- 1 file changed, 137 insertions(+), 197 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 40a70cee..9b24af3c 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -31,17 +31,13 @@ #include #include +#include + #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" -#include "core/function/gpg/GpgCommandExecutor.h" -#include "core/function/gpg/GpgKeyGetter.h" #include "core/module/ModuleManager.h" -#include "core/thread/Task.h" -#include "core/thread/TaskRunnerGetter.h" -#include "core/utils/CacheUtils.h" -#include "core/utils/CommonUtils.h" #include "core/utils/GpgUtils.h" -#include "function/CacheManager.h" +#include "spdlog/spdlog.h" #ifdef _WIN32 #include @@ -49,6 +45,15 @@ namespace GpgFrontend { +struct CtxRefDeleter { + void operator()(gpgme_ctx_t _ctx) { + if (_ctx != nullptr) gpgme_release(_ctx); + } +}; + +using CtxRefHandler = + std::unique_ptr; ///< + class GpgContext::Impl : public SingletonFunctionObject { public: /** @@ -58,169 +63,29 @@ class GpgContext::Impl : public SingletonFunctionObject { Impl(GpgContext *parent, const GpgContextInitArgs &args, int channel) : SingletonFunctionObject(channel), parent_(parent), - args_(args) { - gpgme_ctx_t p_ctx; - - // get gpgme library version - Module::UpsertRTValue("core", "gpgme.version", - std::string(gpgme_check_version(nullptr))); - - // create a new context - CheckGpgError(gpgme_new(&p_ctx)); - ctx_ref_ = CtxRefHandler(p_ctx); - - 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_ref_.get(), GPGME_PROTOCOL_GPGCONF, - args.custom_gpgconf_path.c_str(), nullptr); - assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); - } - - // set context offline mode - SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); - gpgme_set_offline(ctx_ref_.get(), 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) { - CheckGpgError(gpgme_set_ctx_flag(ctx_ref_.get(), "auto-key-import", "1")); - } - - // get engine info - auto *engine_info = gpgme_ctx_get_engine_info(*this); - // Check ENV before running - bool check_passed = false; - bool find_openpgp = false; - bool find_gpgconf = false; - bool find_cms = false; - - while (engine_info != nullptr) { - if (strcmp(engine_info->version, "1.0.0") == 0) { - engine_info = engine_info->next; - continue; - } - - SPDLOG_DEBUG( - "gpg context engine info: {} {} {} {}", - gpgme_get_protocol_name(engine_info->protocol), - std::string(engine_info->file_name == nullptr - ? "null" - : engine_info->file_name), - std::string(engine_info->home_dir == nullptr ? "null" - : engine_info->home_dir), - std::string(engine_info->version ? "null" : engine_info->version)); - - switch (engine_info->protocol) { - case GPGME_PROTOCOL_OpenPGP: - find_openpgp = true; - - Module::UpsertRTValue("core", "gpgme.ctx.app_path", - std::string(engine_info->file_name)); - Module::UpsertRTValue("core", "gpgme.ctx.gnupg_version", - std::string(engine_info->version)); - Module::UpsertRTValue("core", "gpgme.ctx.database_path", - std::string(engine_info->home_dir == nullptr - ? "default" - : engine_info->home_dir)); - break; - case GPGME_PROTOCOL_CMS: - find_cms = true; - Module::UpsertRTValue("core", "gpgme.ctx.cms_path", - std::string(engine_info->file_name)); - - break; - case GPGME_PROTOCOL_GPGCONF: - find_gpgconf = true; - Module::UpsertRTValue("core", "gpgme.ctx.gpgconf_path", - std::string(engine_info->file_name)); - break; - case GPGME_PROTOCOL_ASSUAN: - Module::UpsertRTValue("core", "gpgme.ctx.assuan_path", - std::string(engine_info->file_name)); - break; - case GPGME_PROTOCOL_G13: - break; - case GPGME_PROTOCOL_UISERVER: - break; - case GPGME_PROTOCOL_SPAWN: - break; - case GPGME_PROTOCOL_DEFAULT: - break; - case GPGME_PROTOCOL_UNKNOWN: - break; - } - engine_info = engine_info->next; - } - - 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); - - // conditional check: only support gpg 2.x now - if ((CompareSoftwareVersion(gnupg_version, "2.0.0") >= 0 && find_gpgconf && - find_openpgp && find_cms)) { - check_passed = true; - } - - if (!check_passed) { - this->good_ = false; - SPDLOG_ERROR("env check failed"); - return; - } + args_(args), + good_(default_ctx_initialize(args) && binary_ctx_initialize(args)) {} - // speed up loading process - gpgme_set_offline(*this, 1); - - // set keylist mode - if (gnupg_version >= "2.0.0") { - CheckGpgError(gpgme_set_keylist_mode( - *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | - GPGME_KEYLIST_MODE_SIGS | - GPGME_KEYLIST_MODE_SIG_NOTATIONS | - GPGME_KEYLIST_MODE_WITH_TOFU)); - } else { - CheckGpgError(gpgme_set_keylist_mode( - *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS | - GPGME_KEYLIST_MODE_SIG_NOTATIONS | - GPGME_KEYLIST_MODE_WITH_TOFU)); - } - - // async, init context - Thread::TaskRunnerGetter::GetInstance() - .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_GPG) - ->PostTask(new Thread::Task( - [=](const DataObjectPtr &) -> int { - ctx_post_initialize(); - return 0; - }, - "ctx_post_initialize")); - - good_ = true; + [[nodiscard]] auto BinaryContext() const -> gpgme_ctx_t { + return binary_ctx_ref_.get(); } - /** - * @brief - * - * @return gpgme_ctx_t - */ - operator gpgme_ctx_t() const { return ctx_ref_.get(); } + [[nodiscard]] auto DefaultContext() const -> gpgme_ctx_t { + return ctx_ref_.get(); + } [[nodiscard]] auto Good() const -> bool { return good_; } - void SetPassphraseCb(gpgme_passphrase_cb_t cb) { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", std::string{"2.0.0"}); - - if (CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0) { - if (gpgme_get_pinentry_mode(*this) != GPGME_PINENTRY_MODE_LOOPBACK) { - gpgme_set_pinentry_mode(*this, GPGME_PINENTRY_MODE_LOOPBACK); + auto SetPassphraseCb(const CtxRefHandler &ctx, gpgme_passphrase_cb_t cb) + -> bool { + if (gpgme_get_pinentry_mode(ctx.get()) != GPGME_PINENTRY_MODE_LOOPBACK) { + if (CheckGpgError(gpgme_set_pinentry_mode( + ctx.get(), GPGME_PINENTRY_MODE_LOOPBACK)) != GPG_ERR_NO_ERROR) { + return false; } - gpgme_set_passphrase_cb(*this, cb, reinterpret_cast(parent_)); - } else { - SPDLOG_ERROR("not supported for gnupg version: {}", gnupg_version); } + gpgme_set_passphrase_cb(ctx.get(), cb, reinterpret_cast(parent_)); + return true; } static auto TestPassphraseCb(void *opaque, const char *uid_hint, @@ -288,47 +153,82 @@ class GpgContext::Impl : public SingletonFunctionObject { } private: - struct CtxRefDeleter { - void operator()(gpgme_ctx_t _ctx) { - if (_ctx != nullptr) gpgme_release(_ctx); + GpgContext *parent_; + GpgContextInitArgs args_{}; ///< + CtxRefHandler ctx_ref_ = nullptr; ///< + CtxRefHandler binary_ctx_ref_ = nullptr; ///< + bool good_ = true; + + static auto set_ctx_key_list_mode(const CtxRefHandler &ctx) -> bool { + assert(ctx.get() != 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) { + SPDLOG_ERROR( + "ctx is not a valid pointer, reported by gpgme_get_keylist_mode"); + return false; } - }; - using CtxRefHandler = - std::unique_ptr; ///< + // 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; + } - GpgContext *parent_; - GpgContextInitArgs args_{}; ///< - CtxRefHandler ctx_ref_ = nullptr; ///< - bool good_ = true; + auto common_ctx_initialize(const CtxRefHandler &ctx, + const GpgContextInitArgs &args) -> bool { + assert(ctx.get() != nullptr); - void ctx_post_initialize() { - const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.gnupg_version", std::string{"2.0.0"}); - - if (args_.ascii) { - /** Setting the output type must be done at the beginning */ - /** think this means ascii-armor --> ? */ - gpgme_set_armor(*this, 1); - } else { - /** Setting the output type must be done at the beginning */ - /** think this means ascii-armor --> ? */ - gpgme_set_armor(*this, 0); + 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, + args.custom_gpgconf_path.c_str(), nullptr); + + assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); + if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { + return false; + } } - // for unit test - if (args_.test_mode) { - if (CompareSoftwareVersion(gnupg_version, "2.1.0") >= 0) { - SetPassphraseCb(TestPassphraseCb); + // set context offline mode + SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); + gpgme_set_offline(ctx.get(), 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) { + return false; } - gpgme_set_status_cb(*this, TestStatusCb, nullptr); } - if (!args_.use_pinentry) { - SetPassphraseCb(CustomPassphraseCb); + if (!set_ctx_key_list_mode(ctx)) { + SPDLOG_DEBUG("set ctx key list mode failed"); + return false; + } + + // for unit test + if (args_.test_mode) { + if (!SetPassphraseCb(ctx, TestPassphraseCb)) { + SPDLOG_ERROR("set passphrase cb failed, test"); + return false; + }; + } else if (!args_.use_pinentry) { + if (!SetPassphraseCb(ctx, CustomPassphraseCb)) { + SPDLOG_DEBUG("set passphrase cb failed, custom"); + return false; + } } - // set custom key db path + // set custom gpg key db path if (!args_.db_path.empty()) { Module::UpsertRTValue("core", "gpgme.ctx.database_path", std::string(args_.db_path)); @@ -342,8 +242,50 @@ class GpgContext::Impl : public SingletonFunctionObject { 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; + } } + + return true; + } + + auto binary_ctx_initialize(const GpgContextInitArgs &args) -> bool { + gpgme_ctx_t p_ctx; + if (CheckGpgError(gpgme_new(&p_ctx)) != GPG_ERR_NO_ERROR) { + return false; + } + assert(p_ctx != nullptr); + binary_ctx_ref_ = CtxRefHandler(p_ctx); + + if (!common_ctx_initialize(binary_ctx_ref_, args)) { + SPDLOG_ERROR("get new ctx failed, binary"); + return false; + } + + /** Setting the output type must be done at the beginning */ + /** think this means ascii-armor --> ? */ + gpgme_set_armor(binary_ctx_ref_.get(), 0); + return true; + } + + auto default_ctx_initialize(const GpgContextInitArgs &args) -> bool { + gpgme_ctx_t p_ctx; + if (CheckGpgError(gpgme_new(&p_ctx)) != GPG_ERR_NO_ERROR) { + SPDLOG_ERROR("get new ctx failed, default"); + return false; + } + assert(p_ctx != nullptr); + ctx_ref_ = CtxRefHandler(p_ctx); + + if (!common_ctx_initialize(ctx_ref_, args)) { + return false; + } + + gpgme_set_armor(ctx_ref_.get(), 1); + return true; } }; @@ -357,12 +299,10 @@ GpgContext::GpgContext(const GpgContextInitArgs &args, int channel) auto GpgContext::Good() const -> bool { return p_->Good(); } -void GpgContext::SetPassphraseCb(gpgme_passphrase_cb_t passphrase_cb) const { - p_->SetPassphraseCb(passphrase_cb); -} +auto GpgContext::BinaryContext() -> gpgme_ctx_t { return p_->BinaryContext(); } -GpgContext::operator gpgme_ctx_t() const { - return static_cast(*p_); +auto GpgContext::DefaultContext() -> gpgme_ctx_t { + return p_->DefaultContext(); } GpgContext::~GpgContext() = default; -- cgit v1.2.3 From 79783510863445b5068eef092a1f2650733a5b02 Mon Sep 17 00:00:00 2001 From: saturneric Date: Thu, 14 Dec 2023 16:58:53 +0800 Subject: fix: slove some memory issues --- src/core/function/gpg/GpgContext.cpp | 129 ++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 56 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') 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 @@ -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; ///< - class GpgContext::Impl : public SingletonFunctionObject { public: /** @@ -66,25 +58,33 @@ class GpgContext::Impl : public SingletonFunctionObject { 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(parent_)); + gpgme_set_passphrase_cb(ctx, cb, reinterpret_cast(parent_)); return true; } @@ -154,19 +154,19 @@ class GpgContext::Impl : public SingletonFunctionObject { 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 { // 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 { // 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 { 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 { 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 { /** 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 { 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(channel), - p_(std::make_unique(this, GpgContextInitArgs{}, channel)) {} + p_(SecureCreateUniqueObject(this, GpgContextInitArgs{}, channel)) {} GpgContext::GpgContext(const GpgContextInitArgs &args, int channel) : SingletonFunctionObject(channel), - p_(std::make_unique(this, args, channel)) {} + p_(SecureCreateUniqueObject(this, args, channel)) {} auto GpgContext::Good() const -> bool { return p_->Good(); } -- cgit v1.2.3 From beafe53c1b8671d8e84f0546eb404597300448c7 Mon Sep 17 00:00:00 2001 From: saturneric Date: Thu, 14 Dec 2023 20:39:48 +0800 Subject: fix: slove issues on memory and add asan support for debug --- src/core/function/gpg/GpgContext.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 20ccf70f..0477b00a 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -200,7 +200,7 @@ class GpgContext::Impl : public SingletonFunctionObject { db_path_c_str = nullptr; } - auto err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_OpenPGP, + auto err = gpgme_ctx_set_engine_info(ctx, gpgme_get_protocol(ctx), app_path_c_str, db_path_c_str); assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); @@ -297,11 +297,11 @@ class GpgContext::Impl : public SingletonFunctionObject { assert(p_ctx != nullptr); 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_, 1); + gpgme_set_armor(ctx_ref_, 1); return true; } }; -- cgit v1.2.3 From f5cf83e4b3fdf1e9ae82b00f39e45e189809c419 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 15 Dec 2023 17:04:59 +0800 Subject: fix: slove some issues on memory and intilizations --- src/core/function/gpg/GpgContext.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 0477b00a..443c139b 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -32,12 +32,12 @@ #include #include +#include #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" #include "core/module/ModuleManager.h" #include "core/utils/GpgUtils.h" -#include "spdlog/spdlog.h" #include "utils/MemoryUtils.h" #ifdef _WIN32 @@ -158,6 +158,8 @@ class GpgContext::Impl : public SingletonFunctionObject { gpgme_ctx_t ctx_ref_ = nullptr; ///< gpgme_ctx_t binary_ctx_ref_ = nullptr; ///< bool good_ = true; + std::mutex ctx_ref_lock_; + std::mutex binary_ctx_ref_lock_; static auto set_ctx_key_list_mode(const gpgme_ctx_t &ctx) -> bool { assert(ctx != nullptr); @@ -205,6 +207,8 @@ class GpgContext::Impl : public SingletonFunctionObject { assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); return CheckGpgError(err) == GPG_ERR_NO_ERROR; + + return true; } auto common_ctx_initialize(const gpgme_ctx_t &ctx, -- cgit v1.2.3 From f9a49043c35e73fc2d4ffb3ed9b39c33849c43b3 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 15 Dec 2023 21:14:17 +0800 Subject: fix: slove threading and memory issues --- src/core/function/gpg/GpgContext.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 443c139b..f7223e13 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -46,15 +46,14 @@ namespace GpgFrontend { -class GpgContext::Impl : public SingletonFunctionObject { +class GpgContext::Impl { public: /** * Constructor * Set up gpgme-context, set paths to app-run path */ - Impl(GpgContext *parent, const GpgContextInitArgs &args, int channel) - : SingletonFunctionObject(channel), - parent_(parent), + Impl(GpgContext *parent, const GpgContextInitArgs &args) + : parent_(parent), args_(args), good_(default_ctx_initialize(args) && binary_ctx_initialize(args)) {} @@ -281,14 +280,14 @@ class GpgContext::Impl : public SingletonFunctionObject { assert(p_ctx != nullptr); binary_ctx_ref_ = p_ctx; - if (!common_ctx_initialize(binary_ctx_ref_, args)) { - SPDLOG_ERROR("get new ctx failed, binary"); - return false; - } + // if (!common_ctx_initialize(binary_ctx_ref_, args)) { + // SPDLOG_ERROR("get new ctx failed, binary"); + // return false; + // } - /** Setting the output type must be done at the beginning */ - /** think this means ascii-armor --> ? */ - gpgme_set_armor(binary_ctx_ref_, 0); + // /** Setting the output type must be done at the beginning */ + // /** think this means ascii-armor --> ? */ + // gpgme_set_armor(binary_ctx_ref_, 0); return true; } @@ -301,22 +300,22 @@ class GpgContext::Impl : public SingletonFunctionObject { assert(p_ctx != nullptr); 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_, 1); + // gpgme_set_armor(ctx_ref_, 1); return true; } }; GpgContext::GpgContext(int channel) : SingletonFunctionObject(channel), - p_(SecureCreateUniqueObject(this, GpgContextInitArgs{}, channel)) {} + p_(SecureCreateUniqueObject(this, GpgContextInitArgs{})) {} GpgContext::GpgContext(const GpgContextInitArgs &args, int channel) : SingletonFunctionObject(channel), - p_(SecureCreateUniqueObject(this, args, channel)) {} + p_(SecureCreateUniqueObject(this, args)) {} auto GpgContext::Good() const -> bool { return p_->Good(); } -- cgit v1.2.3 From d6311ece3fa3e8e976befa7e253d453398046c7c Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 15 Dec 2023 21:41:38 -0800 Subject: fix: slove memory problem of gpg context --- src/core/function/gpg/GpgContext.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index f7223e13..7cde439c 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -280,14 +280,12 @@ class GpgContext::Impl { assert(p_ctx != nullptr); binary_ctx_ref_ = p_ctx; - // if (!common_ctx_initialize(binary_ctx_ref_, args)) { - // SPDLOG_ERROR("get new ctx failed, binary"); - // return false; - // } - - // /** Setting the output type must be done at the beginning */ - // /** think this means ascii-armor --> ? */ - // gpgme_set_armor(binary_ctx_ref_, 0); + if (!common_ctx_initialize(binary_ctx_ref_, args)) { + SPDLOG_ERROR("get new ctx failed, binary"); + return false; + } + + gpgme_set_armor(binary_ctx_ref_, 0); return true; } @@ -300,11 +298,11 @@ class GpgContext::Impl { assert(p_ctx != nullptr); 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_, 1); + gpgme_set_armor(ctx_ref_, 1); return true; } }; @@ -313,7 +311,7 @@ GpgContext::GpgContext(int channel) : SingletonFunctionObject(channel), p_(SecureCreateUniqueObject(this, GpgContextInitArgs{})) {} -GpgContext::GpgContext(const GpgContextInitArgs &args, int channel) +GpgContext::GpgContext(GpgContextInitArgs args, int channel) : SingletonFunctionObject(channel), p_(SecureCreateUniqueObject(this, args)) {} -- cgit v1.2.3 From 644aa4397b03dbef73f8bfedc13925b51cad836b Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 5 Jan 2024 20:55:15 +0800 Subject: feat: integrate logging api to core --- src/core/function/gpg/GpgContext.cpp | 37 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 7cde439c..30134191 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -109,7 +109,7 @@ class GpgContext::Impl { int fd) -> gpgme_error_t { std::string passphrase; - SPDLOG_DEBUG( + GF_CORE_LOG_DEBUG( "custom passphrase cb called, uid: {}, info: {}, last_was_bad: {}", uid_hint == nullptr ? "" : std::string{uid_hint}, passphrase_info == nullptr ? "" : std::string{passphrase_info}, @@ -128,7 +128,8 @@ class GpgContext::Impl { looper.exec(); auto passpahrase_size = passphrase.size(); - SPDLOG_DEBUG("get passphrase from pinentry size: {}", passpahrase_size); + GF_CORE_LOG_DEBUG("get passphrase from pinentry size: {}", + passpahrase_size); size_t off = 0; size_t res = 0; @@ -139,7 +140,7 @@ class GpgContext::Impl { res += gpgme_io_write(fd, "\n", 1); - SPDLOG_DEBUG("custom passphrase cd is about to return, res: {}", res); + GF_CORE_LOG_DEBUG("custom passphrase cd is about to return, res: {}", res); return res == passpahrase_size + 1 ? 0 : gpgme_error_from_errno(GPG_ERR_CANCELED); @@ -147,7 +148,7 @@ class GpgContext::Impl { static auto TestStatusCb(void *hook, const char *keyword, const char *args) -> gpgme_error_t { - SPDLOG_DEBUG("keyword {}", keyword); + GF_CORE_LOG_DEBUG("keyword {}", keyword); return GPG_ERR_NO_ERROR; } @@ -165,10 +166,10 @@ class GpgContext::Impl { const auto gpgme_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.version", std::string{"0.0.0"}); - SPDLOG_DEBUG("got gpgme version version from rt: {}", gpgme_version); + GF_CORE_LOG_DEBUG("got gpgme version version from rt: {}", gpgme_version); if (gpgme_get_keylist_mode(ctx) == 0) { - SPDLOG_ERROR( + GF_CORE_LOG_ERROR( "ctx is not a valid pointer, reported by gpgme_get_keylist_mode"); return false; } @@ -187,8 +188,8 @@ class GpgContext::Impl { 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); + GF_CORE_LOG_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(); @@ -215,7 +216,8 @@ class GpgContext::Impl { assert(ctx != nullptr); if (args.custom_gpgconf && !args.custom_gpgconf_path.empty()) { - SPDLOG_DEBUG("set custom gpgconf path: {}", args.custom_gpgconf_path); + GF_CORE_LOG_DEBUG("set custom gpgconf path: {}", + args.custom_gpgconf_path); auto err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_GPGCONF, args.custom_gpgconf_path.c_str(), nullptr); @@ -227,12 +229,13 @@ class GpgContext::Impl { } // set context offline mode - SPDLOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); + GF_CORE_LOG_DEBUG("gpg context offline mode: {}", args_.offline_mode); 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); + GF_CORE_LOG_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, "auto-key-import", "1")) != GPG_ERR_NO_ERROR) { @@ -241,19 +244,19 @@ class GpgContext::Impl { } if (!set_ctx_key_list_mode(ctx)) { - SPDLOG_DEBUG("set ctx key list mode failed"); + GF_CORE_LOG_DEBUG("set ctx key list mode failed"); return false; } // for unit test if (args_.test_mode) { if (!SetPassphraseCb(ctx, TestPassphraseCb)) { - SPDLOG_ERROR("set passphrase cb failed, test"); + GF_CORE_LOG_ERROR("set passphrase cb failed, test"); return false; }; } else if (!args_.use_pinentry) { if (!SetPassphraseCb(ctx, CustomPassphraseCb)) { - SPDLOG_DEBUG("set passphrase cb failed, custom"); + GF_CORE_LOG_DEBUG("set passphrase cb failed, custom"); return false; } } @@ -265,7 +268,7 @@ class GpgContext::Impl { } if (!set_ctx_openpgp_engine_info(ctx)) { - SPDLOG_ERROR("set gpgme context openpgp engine info failed"); + GF_CORE_LOG_ERROR("set gpgme context openpgp engine info failed"); return false; } @@ -281,7 +284,7 @@ class GpgContext::Impl { binary_ctx_ref_ = p_ctx; if (!common_ctx_initialize(binary_ctx_ref_, args)) { - SPDLOG_ERROR("get new ctx failed, binary"); + GF_CORE_LOG_ERROR("get new ctx failed, binary"); return false; } @@ -292,7 +295,7 @@ class GpgContext::Impl { auto default_ctx_initialize(const GpgContextInitArgs &args) -> bool { gpgme_ctx_t p_ctx; if (CheckGpgError(gpgme_new(&p_ctx)) != GPG_ERR_NO_ERROR) { - SPDLOG_ERROR("get new ctx failed, default"); + GF_CORE_LOG_ERROR("get new ctx failed, default"); return false; } assert(p_ctx != nullptr); -- cgit v1.2.3 From bf538056b24a68b8fd235b1c50991ee8eb46a776 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 12 Jan 2024 14:02:37 +0800 Subject: refactor: use QString instead of std::string and improve threading system --- src/core/function/gpg/GpgContext.cpp | 62 +++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 29 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 30134191..df525534 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -36,6 +36,7 @@ #include "core/function/CoreSignalStation.h" #include "core/function/basic/GpgFunctionObject.h" +#include "core/model/GpgPassphraseContext.h" #include "core/module/ModuleManager.h" #include "core/utils/GpgUtils.h" #include "utils/MemoryUtils.h" @@ -91,7 +92,7 @@ class GpgContext::Impl { const char *passphrase_info, int last_was_bad, int fd) -> gpgme_error_t { size_t res; - std::string pass = "abcdefg\n"; + QString pass = "abcdefg\n"; auto pass_len = pass.size(); size_t off = 0; @@ -105,38 +106,42 @@ class GpgContext::Impl { } static auto CustomPassphraseCb(void *hook, const char *uid_hint, - const char *passphrase_info, int last_was_bad, + const char *passphrase_info, int prev_was_bad, int fd) -> gpgme_error_t { - std::string passphrase; + auto context = + QSharedPointer(new GpgPassphraseContext( + uid_hint != nullptr ? uid_hint : "", + passphrase_info != nullptr ? passphrase_info : "", + prev_was_bad != 0)); GF_CORE_LOG_DEBUG( "custom passphrase cb called, uid: {}, info: {}, last_was_bad: {}", - uid_hint == nullptr ? "" : std::string{uid_hint}, - passphrase_info == nullptr ? "" : std::string{passphrase_info}, - last_was_bad); - - emit CoreSignalStation::GetInstance()->SignalNeedUserInputPassphrase(); + uid_hint == nullptr ? "" : QString{uid_hint}, + passphrase_info == nullptr ? "" : QString{passphrase_info}, + prev_was_bad); QEventLoop looper; - QObject::connect( - CoreSignalStation::GetInstance(), - &CoreSignalStation::SignalUserInputPassphraseCallback, &looper, - [&](const QByteArray &buffer) { passphrase = buffer.toStdString(); }); QObject::connect(CoreSignalStation::GetInstance(), &CoreSignalStation::SignalUserInputPassphraseCallback, &looper, &QEventLoop::quit); + + emit CoreSignalStation::GetInstance()->SignalNeedUserInputPassphrase( + context); looper.exec(); + auto passphrase = context->GetPassphrase().toStdString(); auto passpahrase_size = passphrase.size(); GF_CORE_LOG_DEBUG("get passphrase from pinentry size: {}", passpahrase_size); - size_t off = 0; size_t res = 0; - do { - res = gpgme_io_write(fd, &passphrase[off], passpahrase_size - off); - if (res > 0) off += res; - } while (res > 0 && off != passpahrase_size); + if (passpahrase_size > 0) { + size_t off = 0; + do { + res = gpgme_io_write(fd, &passphrase[off], passpahrase_size - off); + if (res > 0) off += res; + } while (res > 0 && off != passpahrase_size); + } res += gpgme_io_write(fd, "\n", 1); @@ -165,7 +170,7 @@ class GpgContext::Impl { assert(ctx != nullptr); const auto gpgme_version = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.version", std::string{"0.0.0"}); + "core", "gpgme.version", QString{"0.0.0"}); GF_CORE_LOG_DEBUG("got gpgme version version from rt: {}", gpgme_version); if (gpgme_get_keylist_mode(ctx) == 0) { @@ -184,21 +189,21 @@ class GpgContext::Impl { 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{}); + "core", "gpgme.ctx.app_path", QString{}); const auto database_path = Module::RetrieveRTValueTypedOrDefault<>( - "core", "gpgme.ctx.database_path", std::string{}); + "core", "gpgme.ctx.database_path", QString{}); GF_CORE_LOG_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(); + const char *app_path_c_str = app_path.toUtf8(); + const char *db_path_c_str = database_path.toUtf8(); - if (app_path.empty()) { + if (app_path.isEmpty()) { app_path_c_str = nullptr; } - if (database_path.empty()) { + if (database_path.isEmpty()) { db_path_c_str = nullptr; } @@ -215,12 +220,12 @@ class GpgContext::Impl { const GpgContextInitArgs &args) -> bool { assert(ctx != nullptr); - if (args.custom_gpgconf && !args.custom_gpgconf_path.empty()) { + if (args.custom_gpgconf && !args.custom_gpgconf_path.isEmpty()) { GF_CORE_LOG_DEBUG("set custom gpgconf path: {}", args.custom_gpgconf_path); auto err = gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_GPGCONF, - args.custom_gpgconf_path.c_str(), nullptr); + args.custom_gpgconf_path.toUtf8(), nullptr); assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { @@ -262,9 +267,8 @@ class GpgContext::Impl { } // set custom gpg key db path - if (!args_.db_path.empty()) { - Module::UpsertRTValue("core", "gpgme.ctx.database_path", - std::string(args_.db_path)); + if (!args_.db_path.isEmpty()) { + Module::UpsertRTValue("core", "gpgme.ctx.database_path", args_.db_path); } if (!set_ctx_openpgp_engine_info(ctx)) { -- cgit v1.2.3 From 57cc0c0d4c9a8b72385f5d9323ec70e812992ebc Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 12 Jan 2024 14:10:58 +0800 Subject: fix: slove a heap-use-after-free issue --- src/core/function/gpg/GpgContext.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index df525534..bc0787a4 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -196,19 +196,13 @@ class GpgContext::Impl { GF_CORE_LOG_DEBUG("ctx set engine info, db path: {}, app path: {}", database_path, app_path); - const char *app_path_c_str = app_path.toUtf8(); - const char *db_path_c_str = database_path.toUtf8(); + auto app_path_buffer = app_path.toUtf8(); + auto database_path_buffer = database_path.toUtf8(); - if (app_path.isEmpty()) { - app_path_c_str = nullptr; - } - - if (database_path.isEmpty()) { - db_path_c_str = nullptr; - } - - auto err = gpgme_ctx_set_engine_info(ctx, gpgme_get_protocol(ctx), - app_path_c_str, db_path_c_str); + auto err = gpgme_ctx_set_engine_info( + ctx, gpgme_get_protocol(ctx), + app_path.isEmpty() ? nullptr : app_path_buffer, + database_path.isEmpty() ? nullptr : database_path_buffer); assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); return CheckGpgError(err) == GPG_ERR_NO_ERROR; -- cgit v1.2.3 From 4994f4eaa1211d402b791660ad6221154a4c2405 Mon Sep 17 00:00:00 2001 From: saturneric Date: Tue, 16 Jan 2024 11:49:50 +0800 Subject: fix: make task and threading system safer --- src/core/function/gpg/GpgContext.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index bc0787a4..0849f240 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -221,8 +221,9 @@ class GpgContext::Impl { gpgme_ctx_set_engine_info(ctx, GPGME_PROTOCOL_GPGCONF, args.custom_gpgconf_path.toUtf8(), nullptr); - assert(CheckGpgError(err) == GPG_ERR_NO_ERROR); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { + GF_CORE_LOG_ERROR("set gpg context engine info error: {}", + DescribeGpgErrCode(err).second); return false; } } @@ -275,7 +276,9 @@ class GpgContext::Impl { auto binary_ctx_initialize(const GpgContextInitArgs &args) -> bool { gpgme_ctx_t p_ctx; - if (CheckGpgError(gpgme_new(&p_ctx)) != GPG_ERR_NO_ERROR) { + if (auto err = CheckGpgError(gpgme_new(&p_ctx)); err != GPG_ERR_NO_ERROR) { + GF_CORE_LOG_ERROR("get new gpg context error: {}", + DescribeGpgErrCode(err).second); return false; } assert(p_ctx != nullptr); -- cgit v1.2.3 From e352e8e6b8d03a24ef5d52eef3e4d370807b5bbd Mon Sep 17 00:00:00 2001 From: saturneric Date: Wed, 17 Jan 2024 19:39:47 +0800 Subject: fix: find and slove some bugs --- src/core/function/gpg/GpgContext.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 0849f240..104e254f 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -38,8 +38,9 @@ #include "core/function/basic/GpgFunctionObject.h" #include "core/model/GpgPassphraseContext.h" #include "core/module/ModuleManager.h" +#include "core/utils/CacheUtils.h" #include "core/utils/GpgUtils.h" -#include "utils/MemoryUtils.h" +#include "core/utils/MemoryUtils.h" #ifdef _WIN32 #include @@ -108,11 +109,13 @@ class GpgContext::Impl { static auto CustomPassphraseCb(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd) -> gpgme_error_t { + auto context_cache = GetCacheValue("PinentryContext"); + bool ask_for_new = context_cache == "NEW_PASSPHRASE"; auto context = QSharedPointer(new GpgPassphraseContext( uid_hint != nullptr ? uid_hint : "", passphrase_info != nullptr ? passphrase_info : "", - prev_was_bad != 0)); + prev_was_bad != 0, ask_for_new)); GF_CORE_LOG_DEBUG( "custom passphrase cb called, uid: {}, info: {}, last_was_bad: {}", @@ -129,6 +132,7 @@ class GpgContext::Impl { context); looper.exec(); + ResetCacheValue("PinentryContext"); auto passphrase = context->GetPassphrase().toStdString(); auto passpahrase_size = passphrase.size(); GF_CORE_LOG_DEBUG("get passphrase from pinentry size: {}", -- cgit v1.2.3 From e0d2c4021483e6e1366c1050ccb5a30e53e172bb Mon Sep 17 00:00:00 2001 From: saturneric Date: Thu, 18 Jan 2024 20:58:37 +0800 Subject: fix: add test cases and solve discovered issues --- src/core/function/gpg/GpgContext.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/core/function/gpg/GpgContext.cpp') diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 104e254f..6523386c 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -94,16 +94,19 @@ class GpgContext::Impl { int fd) -> gpgme_error_t { size_t res; QString pass = "abcdefg\n"; - auto pass_len = pass.size(); + auto passpahrase_size = pass.size(); size_t off = 0; do { - res = gpgme_io_write(fd, &pass[off], pass_len - off); + res = gpgme_io_write(fd, &pass[off], passpahrase_size - off); if (res > 0) off += res; - } while (res > 0 && off != pass_len); + } while (res > 0 && off != passpahrase_size); - return off == pass_len ? 0 : gpgme_error_from_errno(errno); + res += gpgme_io_write(fd, "\n", 1); + return res == passpahrase_size + 1 + ? 0 + : gpgme_error_from_errno(GPG_ERR_CANCELED); } static auto CustomPassphraseCb(void *hook, const char *uid_hint, -- cgit v1.2.3