diff options
author | Saturneric <[email protected]> | 2021-12-25 01:54:57 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2021-12-25 01:54:57 +0000 |
commit | b5cd5eac82b6bbd8a00fb39c045d473d6517b5f4 (patch) | |
tree | f8ce246cb98222a24b8f59640d48a633464d333b | |
parent | Continue to add Standalone Support. (diff) | |
download | GpgFrontend-b5cd5eac82b6bbd8a00fb39c045d473d6517b5f4.tar.gz GpgFrontend-b5cd5eac82b6bbd8a00fb39c045d473d6517b5f4.zip |
<refactor, test>(core, test): core improved and test gpg alone mode
1. let modules known their channels.
2. let factory create a channel.
3. reduce dumplicate code.
4. add type check for function object.
5. test gpg alone mode.
6. remove some asserts.
7. rename importexportor to importexporter.
8. move args in gpg context constructor to a struct.
Diffstat (limited to '')
32 files changed, 440 insertions, 185 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index fa687fd9..eca4a86c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,16 +42,16 @@ else () endif () # Specify different compilation modes -if (BUILD_CONFIG) +if (GPGFRONTEND_BUILD_CONFIG) # Test Build - if (${BUILD_CONFIG} STREQUAL "test") - message(STATUS "Switch TEST_BUILD") - set(TEST_BUILD 1) - set(AppName GpgFrontendTest) + if (${GPGFRONTEND_BUILD_CONFIG} STREQUAL "test_core") + message(STATUS "Switch TEST_CORE_BUILD") + set(TEST_CORE_BUILD 1) + set(AppName GpgFrontendCoreTest) # Test Build With Coverage Test - elseif (${BUILD_CONFIG} STREQUAL "test_coverage") + elseif (${GPGFRONTEND_BUILD_CONFIG} STREQUAL "test_core_coverage") message(STATUS "Switch TEST_COVERAGE_BUILD") - set(TEST_BUILD 1) + set(TEST_CORE_BUILD 1) if (USING_COMPILER_CLANG OR USING_COMPILER_GCC) set(TEST_COVERAGE_BUILD 1) set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) @@ -61,11 +61,11 @@ if (BUILD_CONFIG) endif () set(AppName GpgFrontendTest) # Test Build with minimum UI - elseif (${BUILD_CONFIG} STREQUAL "test_ui") + elseif (${GPGFRONTEND_BUILD_CONFIG} STREQUAL "test_ui") message(STATUS "Switch TEST_MINIMUM_UI_BUILD") set(MINIMUM_APPLICATION_BUILD 1) set(AppName GpgFrontend) - elseif (${BUILD_CONFIG} STREQUAL "test_all") + elseif (${GPGFRONTEND_BUILD_CONFIG} STREQUAL "test_all") message(STATUS "Switch FULL_APPLICATION_BUILD") set(FULL_APPLICATION_BUILD 1) set(AppName GpgFrontend) @@ -171,13 +171,13 @@ if (APPLE) set(ENV{Qt5_DIR} /usr/local/opt/qt5/lib/cmake) - if(XCODE_BUILD) + if (XCODE_BUILD) set(XCODE_CODE_SIGN_IDENTITY "\"${XCODE_CODE_SIGN_IDENTITY}\"") message(STATUS "XCODE_CODE_SIGN_IDENTITY ${XCODE_CODE_SIGN_IDENTITY}") - if(APPLE_SANDBOX) + if (APPLE_SANDBOX) add_compile_definitions(APPLE_SANDBOX) - endif() - endif() + endif () + endif () include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/src @@ -224,9 +224,9 @@ endif () message(STATUS "OS_PLATFORM ${OS_PLATFORM}") -if(GPG_STANDALONE_MODE) +if (GPG_STANDALONE_MODE) add_compile_definitions(GPG_STANDALONE_MODE) -endif() +endif () # Basic Envirnoment Configure set(BASIC_ENV_CONFIG 1) @@ -274,7 +274,7 @@ elseif (STABLE_APPLICATION_BUILD) set(BASIC_ENV_CONFIG 1) set(SMTP_SUPPORT 1) set(MULTI_LANG_SUPPORT 1) -elseif (TEST_BUILD) +elseif (TEST_CORE_BUILD) message(STATUS "Build Test Cases") if (MODULES) @@ -329,7 +329,7 @@ endif () add_subdirectory(third_party) add_subdirectory(src) -if (TEST_BUILD) +if (TEST_CORE_BUILD) include(CTest) enable_testing() add_subdirectory(test) diff --git a/src/gpg/GpgConstants.cpp b/src/gpg/GpgConstants.cpp index fd3c56b4..b047ffe3 100644 --- a/src/gpg/GpgConstants.cpp +++ b/src/gpg/GpgConstants.cpp @@ -215,6 +215,12 @@ GpgFrontend::GpgVerifyResult GpgFrontend::_new_result( return {result, _result_ref_deletor()}; } +GpgFrontend::GpgGenKeyResult GpgFrontend::_new_result( + gpgme_genkey_result_t&& result) { + gpgme_result_ref(result); + return {result, _result_ref_deletor()}; +} + void GpgFrontend::_result_ref_deletor::operator()(void* _result) { DLOG(INFO) << _("Called") << _result; if (_result != nullptr) gpgme_result_unref(_result); diff --git a/src/gpg/GpgConstants.h b/src/gpg/GpgConstants.h index 14895df7..3c0240d2 100644 --- a/src/gpg/GpgConstants.h +++ b/src/gpg/GpgConstants.h @@ -58,12 +58,14 @@ using GpgEncrResult = std::shared_ptr<struct _gpgme_op_encrypt_result>; using GpgDecrResult = std::shared_ptr<struct _gpgme_op_decrypt_result>; using GpgSignResult = std::shared_ptr<struct _gpgme_op_sign_result>; using GpgVerifyResult = std::shared_ptr<struct _gpgme_op_verify_result>; +using GpgGenKeyResult = std::shared_ptr<struct _gpgme_op_genkey_result>; // Convert from gpgme_xxx_result to GpgXXXResult GpgEncrResult _new_result(gpgme_encrypt_result_t&& result); GpgDecrResult _new_result(gpgme_decrypt_result_t&& result); GpgSignResult _new_result(gpgme_sign_result_t&& result); GpgVerifyResult _new_result(gpgme_verify_result_t&& result); +GpgGenKeyResult _new_result(gpgme_genkey_result_t&& result); // Error Info Printer GpgError check_gpg_error(GpgError err); diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index d2b500e2..a39918e2 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -29,6 +29,7 @@ #include <functional> #include <string> +#include <utility> #include "GpgConstants.h" @@ -36,17 +37,13 @@ #include <windows.h> #endif -#define INT2VOIDP(i) (void*)(uintptr_t)(i) - namespace GpgFrontend { /** * Constructor * Set up gpgme-context, set paths to app-run path */ -GpgContext::GpgContext(bool independent_database, std::string db_path, - bool gpg_alone, std::string gpg_path, int channel) - : SingletonFunctionObject<GpgContext>(channel) { +GpgContext::GpgContext(const GpgContextInitArgs& args) { static bool _first = true; if (_first) { @@ -64,46 +61,57 @@ GpgContext::GpgContext(bool independent_database, std::string db_path, check_gpg_error(gpgme_new(&_p_ctx)); _ctx_ref = CtxRefHandler(_p_ctx); - if (gpg_alone) { - info.AppPath = gpg_path; + if (args.gpg_alone) { + info.AppPath = args.gpg_path; auto err = gpgme_ctx_set_engine_info(_ctx_ref.get(), GPGME_PROTOCOL_OpenPGP, info.AppPath.c_str(), info.DatabasePath.c_str()); assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); } - auto engineInfo = gpgme_ctx_get_engine_info(*this); + auto engine_info = gpgme_ctx_get_engine_info(*this); // Check ENV before running bool check_pass = false, find_openpgp = false, find_gpgconf = false, find_assuan = false, find_cms = false; - while (engineInfo != nullptr) { - if (engineInfo->protocol == GPGME_PROTOCOL_GPGCONF && - strcmp(engineInfo->version, "1.0.0") != 0) + while (engine_info != nullptr) { + if (engine_info->protocol == GPGME_PROTOCOL_GPGCONF && + strcmp(engine_info->version, "1.0.0") != 0) find_gpgconf = true; - if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && - strcmp(engineInfo->version, "1.0.0") != 0) - find_openpgp = true, info.AppPath = engineInfo->file_name, - info.DatabasePath = "default", info.GnupgVersion = engineInfo->version; - if (engineInfo->protocol == GPGME_PROTOCOL_CMS && - strcmp(engineInfo->version, "1.0.0") != 0) + if (engine_info->protocol == GPGME_PROTOCOL_OpenPGP && + strcmp(engine_info->version, "1.0.0") != 0) { + find_openpgp = true; + info.AppPath = engine_info->file_name; + info.DatabasePath = "default", info.GnupgVersion = engine_info->version; + DLOG(INFO) << "OpenPGP" + << std::string(engine_info->file_name == nullptr + ? "null" + : engine_info->file_name) + << std::string(engine_info->home_dir == nullptr + ? "null" + : engine_info->home_dir); + } + + if (engine_info->protocol == GPGME_PROTOCOL_CMS && + strcmp(engine_info->version, "1.0.0") != 0) find_cms = true; - if (engineInfo->protocol == GPGME_PROTOCOL_ASSUAN) find_assuan = true; - engineInfo = engineInfo->next; + if (engine_info->protocol == GPGME_PROTOCOL_ASSUAN) find_assuan = true; + engine_info = engine_info->next; } if (find_gpgconf && find_openpgp && find_cms && find_assuan) check_pass = true; if (!check_pass) { - good_ = false; + this->good_ = false; return; } else { - LOG(INFO) << "Gnupg Version" << info.GnupgVersion; + LOG(INFO) << "GnuPG version" << info.GnupgVersion; // Set Independent Database - if (independent_database) { - info.DatabasePath = db_path; + if (args.independent_database) { + info.DatabasePath = args.db_path; + LOG(INFO) << "gpg custom database path" << info.DatabasePath; auto err = gpgme_ctx_set_engine_info( _ctx_ref.get(), GPGME_PROTOCOL_OpenPGP, info.AppPath.c_str(), info.DatabasePath.c_str()); @@ -116,10 +124,20 @@ GpgContext::GpgContext(bool independent_database, std::string db_path, // Speed up loading process gpgme_set_offline(*this, 1); - check_gpg_error(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)); + if (info.GnupgVersion >= "2.0.0") { + LOG(INFO) << "Using GnuPG 2.x"; + check_gpg_error(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 { + LOG(INFO) << "Using GnuPG 1.x"; + check_gpg_error(gpgme_set_keylist_mode( + *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS | + GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_WITH_TOFU)); + } good_ = true; } } diff --git a/src/gpg/GpgContext.h b/src/gpg/GpgContext.h index da19bfd9..887bb7a6 100644 --- a/src/gpg/GpgContext.h +++ b/src/gpg/GpgContext.h @@ -32,14 +32,24 @@ namespace GpgFrontend { +struct GpgContextInitArgs { + bool independent_database = false; + std::string db_path = {}; + bool gpg_alone = false; + std::string gpg_path = {}; + + GpgContextInitArgs() = default; +}; + /** * Custom Encapsulation of GpgME APIs */ class GpgContext : public SingletonFunctionObject<GpgContext> { public: - explicit GpgContext(bool independent_database = false, - std::string path = std::string(), bool gpg_alone = false, - std::string gpg_path = std::string(), int channel = 0); + explicit GpgContext(const GpgContextInitArgs& args = {}); + + explicit GpgContext(int channel) + : SingletonFunctionObject<GpgContext>(channel) {} ~GpgContext() override = default; @@ -54,13 +64,13 @@ class GpgContext : public SingletonFunctionObject<GpgContext> { private: GpgInfo info; - struct _ctx_ref_deletor { + struct _ctx_ref_deleter { void operator()(gpgme_ctx_t _ctx) { if (_ctx != nullptr) gpgme_release(_ctx); } }; - using CtxRefHandler = std::unique_ptr<struct gpgme_context, _ctx_ref_deletor>; + using CtxRefHandler = std::unique_ptr<struct gpgme_context, _ctx_ref_deleter>; CtxRefHandler _ctx_ref = nullptr; bool good_ = true; diff --git a/src/gpg/GpgFunctionObject.h b/src/gpg/GpgFunctionObject.h index 6f1d60af..d81371d9 100644 --- a/src/gpg/GpgFunctionObject.h +++ b/src/gpg/GpgFunctionObject.h @@ -40,57 +40,52 @@ template <typename T> class SingletonFunctionObject { public: static T& GetInstance(int channel = 0) { - if (!channel) { - std::lock_guard<std::mutex> guard(_instance_mutex); - if (_instance == nullptr) _instance = std::make_unique<T>(); - return *_instance; - } else { - // read _instances_map - decltype(_instances_map.end()) _it; - { - std::shared_lock lock(_instances_mutex); - _it = _instances_map.find(channel); - } - if (_it != _instances_map.end()) - return *_it->second; - else - return CreateInstance(channel); - } + static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, + "T not derived from SingletonFunctionObject<T>"); + + auto _p_pbj = find_object_in_channel(channel); + if (_p_pbj == nullptr) + return *set_object_in_channel(channel, std::make_unique<T>(channel)); + else + return *_p_pbj; + } + + static T& CreateInstance(int channel, + std::function<std::unique_ptr<T>(void)> factory) { + static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, + "T not derived from SingletonFunctionObject<T>"); + + auto _p_pbj = find_object_in_channel(channel); + if (_p_pbj == nullptr) + return *set_object_in_channel(channel, std::move(factory())); + else + return *_p_pbj; } static T& CreateInstance(int channel, std::unique_ptr<T> p_obj = nullptr) { - if (!channel) return *_instance; + static_assert(std::is_base_of<SingletonFunctionObject<T>, T>::value, + "T not derived from SingletonFunctionObject<T>"); + + auto _p_pbj = find_object_in_channel(channel); + if (_p_pbj == nullptr) + return *set_object_in_channel(channel, std::move(p_obj)); + else + return *_p_pbj; + } - // read _instances_map + static T& ReleaseChannel(int channel) { decltype(_instances_map.end()) _it; { std::shared_lock lock(_instances_mutex); _it = _instances_map.find(channel); } - if (_it == _instances_map.end()) { - { - std::lock_guard<std::mutex> guard(_default_channel_mutex); - int tmp = channel; - std::swap(_default_channel, tmp); - if (p_obj == nullptr) p_obj = std::make_unique<T>(); - std::swap(_default_channel, tmp); - } - T* obj = p_obj.get(); - - // change _instances_map - { - std::unique_lock lock(_instances_mutex); - _instances_map.insert({channel, std::move(p_obj)}); - } - return *obj; - } else { - return *_it->second; - } + if (_it != _instances_map.end()) _instances_map.erase(_it); + DLOG(INFO) << "channel" << channel << "released"; } static int GetDefaultChannel() { return _default_channel; } - int GetChannel() const { return channel_; } + [[nodiscard]] int GetChannel() const { return channel_; } SingletonFunctionObject(T&&) = delete; @@ -99,29 +94,53 @@ class SingletonFunctionObject { void operator=(const T&) = delete; protected: - SingletonFunctionObject() {} + SingletonFunctionObject() = default; - SingletonFunctionObject(int channel) : channel_(channel) {} + explicit SingletonFunctionObject(int channel) : channel_(channel) {} virtual ~SingletonFunctionObject() = default; + void SetChannel(int channel) { this->channel_ = channel; } + private: int channel_ = _default_channel; static int _default_channel; - static std::mutex _default_channel_mutex; static std::mutex _instance_mutex; static std::shared_mutex _instances_mutex; static std::unique_ptr<T> _instance; static std::map<int, std::unique_ptr<T>> _instances_map; + + static T* find_object_in_channel(int channel) { + // read _instances_map + decltype(_instances_map.end()) _it; + { + std::shared_lock lock(_instances_mutex); + _it = _instances_map.find(channel); + if (_it == _instances_map.end()) + return nullptr; + else + return _it->second.get(); + } + } + + static T* set_object_in_channel(int channel, std::unique_ptr<T> p_obj) { + { + if (p_obj == nullptr) p_obj = std::make_unique<T>(); + T* obj = p_obj.get(); + obj->SetChannel(channel); + { + std::unique_lock lock(_instances_mutex); + _instances_map.insert({channel, std::move(p_obj)}); + } + return obj; + } + } }; template <typename T> int SingletonFunctionObject<T>::_default_channel = 0; template <typename T> -std::mutex SingletonFunctionObject<T>::_default_channel_mutex; - -template <typename T> std::mutex SingletonFunctionObject<T>::_instance_mutex; template <typename T> diff --git a/src/gpg/GpgGenKeyInfo.h b/src/gpg/GpgGenKeyInfo.h index 14290e17..cc679656 100644 --- a/src/gpg/GpgGenKeyInfo.h +++ b/src/gpg/GpgGenKeyInfo.h @@ -27,6 +27,7 @@ #include <boost/date_time.hpp> #include <boost/date_time/gregorian/greg_duration_types.hpp> +#include <boost/format.hpp> #include <string> #include <vector> @@ -34,7 +35,10 @@ namespace GpgFrontend { class GenKeyInfo { bool subKey = true; - std::string userid; + std::string name; + std::string email; + std::string comment; + std::string algo; int keySize = 2048; boost::posix_time::ptime expired = @@ -60,9 +64,23 @@ class GenKeyInfo { void setIsSubKey(bool m_sub_key) { GenKeyInfo::subKey = m_sub_key; } - [[nodiscard]] const std::string &getUserid() const { return userid; } + [[nodiscard]] std::string getUserid() const { + auto uid_format = boost::format("%1%(%2%)<%3%>") % this->name % + this->comment % this->email; + return uid_format.str(); + } + + void setName(const std::string &m_name) { this->name = m_name; } + + void setEmail(const std::string &m_email) { this->email = m_email; } + + void setComment(const std::string &m_comment) { this->comment = m_comment; } + + [[nodiscard]] std::string getName() const { return name; } + + [[nodiscard]] std::string getEmail() const { return email; } - void setUserid(const std::string &m_userid) { GenKeyInfo::userid = m_userid; } + [[nodiscard]] std::string getComment() const { return comment; } [[nodiscard]] const std::string &getAlgo() const { return algo; } diff --git a/src/gpg/function/BasicOperator.h b/src/gpg/function/BasicOperator.h index 4ea70eea..41bd9b7f 100644 --- a/src/gpg/function/BasicOperator.h +++ b/src/gpg/function/BasicOperator.h @@ -34,6 +34,10 @@ namespace GpgFrontend { class BasicOperator : public SingletonFunctionObject<BasicOperator> { public: + explicit BasicOperator( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<BasicOperator>(channel) {} + gpg_error_t Encrypt(KeyListPtr keys, BypeArrayRef in_buffer, ByteArrayPtr& out_buffer, GpgEncrResult& result); @@ -65,7 +69,7 @@ class BasicOperator : public SingletonFunctionObject<BasicOperator> { private: GpgContext& ctx = - GpgContext::GetInstance(SingletonFunctionObject::GetDefaultChannel()); + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/gpg/function/GpgCommandExecutor.h b/src/gpg/function/GpgCommandExecutor.h index f28caca8..dcdd318d 100644 --- a/src/gpg/function/GpgCommandExecutor.h +++ b/src/gpg/function/GpgCommandExecutor.h @@ -35,6 +35,9 @@ namespace GpgFrontend { class GpgCommandExecutor : public SingletonFunctionObject<GpgCommandExecutor> { public: + explicit GpgCommandExecutor( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<GpgCommandExecutor>(channel) {} #ifndef WINDOWS void Execute(StringArgsRef arguments, @@ -44,7 +47,8 @@ class GpgCommandExecutor : public SingletonFunctionObject<GpgCommandExecutor> { #endif private: - GpgContext &ctx = GpgContext::GetInstance(); + GpgContext &ctx = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/gpg/function/GpgFileOpera.h b/src/gpg/function/GpgFileOpera.h index 4aaf09f1..b7848440 100644 --- a/src/gpg/function/GpgFileOpera.h +++ b/src/gpg/function/GpgFileOpera.h @@ -33,6 +33,10 @@ namespace GpgFrontend { class GpgFileOpera : public SingletonFunctionObject<GpgFileOpera> { public: + explicit GpgFileOpera( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<GpgFileOpera>(channel) {} + static GpgError EncryptFile(KeyListPtr keys, const std::string& path, GpgEncrResult& result); diff --git a/src/gpg/function/GpgKeyGetter.cpp b/src/gpg/function/GpgKeyGetter.cpp index 664aff56..3457a8a7 100644 --- a/src/gpg/function/GpgKeyGetter.cpp +++ b/src/gpg/function/GpgKeyGetter.cpp @@ -65,6 +65,8 @@ GpgFrontend::KeyLinkListPtr GpgFrontend::GpgKeyGetter::FetchKey() { err = gpgme_op_keylist_end(ctx); + assert(check_gpg_error_2_err_code(err, GPG_ERR_EOF) == GPG_ERR_NO_ERROR); + return keys_list; } diff --git a/src/gpg/function/GpgKeyGetter.h b/src/gpg/function/GpgKeyGetter.h index 3af51815..fcd518d3 100644 --- a/src/gpg/function/GpgKeyGetter.h +++ b/src/gpg/function/GpgKeyGetter.h @@ -33,7 +33,9 @@ namespace GpgFrontend { class GpgKeyGetter : public SingletonFunctionObject<GpgKeyGetter> { public: - GpgKeyGetter() = default; + explicit GpgKeyGetter( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<GpgKeyGetter>(channel) {} GpgKey GetKey(const std::string& fpr); @@ -49,7 +51,7 @@ class GpgKeyGetter : public SingletonFunctionObject<GpgKeyGetter> { private: GpgContext& ctx = - GpgContext::GetInstance(SingletonFunctionObject::GetDefaultChannel()); + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/gpg/function/GpgKeyImportExportor.cpp b/src/gpg/function/GpgKeyImportExporter.cpp index 89d3b002..ca9b86d1 100644 --- a/src/gpg/function/GpgKeyImportExportor.cpp +++ b/src/gpg/function/GpgKeyImportExporter.cpp @@ -22,7 +22,7 @@ * */ -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" #include "GpgConstants.h" @@ -31,7 +31,7 @@ * @param inBuffer input byte array * @return Import information */ -GpgFrontend::GpgImportInformation GpgFrontend::GpgKeyImportExportor::ImportKey( +GpgFrontend::GpgImportInformation GpgFrontend::GpgKeyImportExporter::ImportKey( StdBypeArrayPtr in_buffer) { if (in_buffer->empty()) return {}; @@ -60,7 +60,7 @@ GpgFrontend::GpgImportInformation GpgFrontend::GpgKeyImportExportor::ImportKey( * @param out_buffer output byte array * @return if success */ -bool GpgFrontend::GpgKeyImportExportor::ExportKeys( +bool GpgFrontend::GpgKeyImportExporter::ExportKeys( KeyIdArgsListPtr& uid_list, ByteArrayPtr& out_buffer) const { if (uid_list->empty()) return false; @@ -87,7 +87,7 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKeys( * @param outBuffer output byte array * @return if success */ -bool GpgFrontend::GpgKeyImportExportor::ExportKeys( +bool GpgFrontend::GpgKeyImportExporter::ExportKeys( const KeyArgsList& keys, ByteArrayPtr& out_buffer) const { KeyIdArgsListPtr key_ids = std::make_unique<std::vector<std::string>>(); for (const auto& key : keys) key_ids->push_back(key.id()); @@ -100,7 +100,7 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKeys( * @param outBuffer output byte array * @return if successful */ -bool GpgFrontend::GpgKeyImportExportor::ExportSecretKey( +bool GpgFrontend::GpgKeyImportExporter::ExportSecretKey( const GpgKey& key, ByteArrayPtr& out_buffer) const { DLOG(INFO) << "Export Secret Key" << key.id().c_str(); @@ -117,7 +117,7 @@ bool GpgFrontend::GpgKeyImportExportor::ExportSecretKey( return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR; } -bool GpgFrontend::GpgKeyImportExportor::ExportKey( +bool GpgFrontend::GpgKeyImportExporter::ExportKey( const GpgFrontend::GpgKey& key, GpgFrontend::ByteArrayPtr& out_buffer) const { GpgData data_out; @@ -131,7 +131,7 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKey( return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR; } -bool GpgFrontend::GpgKeyImportExportor::ExportKeyOpenSSH( +bool GpgFrontend::GpgKeyImportExporter::ExportKeyOpenSSH( const GpgFrontend::GpgKey& key, GpgFrontend::ByteArrayPtr& out_buffer) const { GpgData data_out; @@ -145,7 +145,7 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKeyOpenSSH( return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR; } -bool GpgFrontend::GpgKeyImportExportor::ExportSecretKeyShortest( +bool GpgFrontend::GpgKeyImportExporter::ExportSecretKeyShortest( const GpgFrontend::GpgKey& key, GpgFrontend::ByteArrayPtr& out_buffer) const { GpgData data_out; diff --git a/src/gpg/function/GpgKeyImportExportor.h b/src/gpg/function/GpgKeyImportExporter.h index ad43d539..b6c91303 100644 --- a/src/gpg/function/GpgKeyImportExportor.h +++ b/src/gpg/function/GpgKeyImportExporter.h @@ -79,9 +79,13 @@ class GpgImportInformation { GpgImportedKeyList importedKeys; }; -class GpgKeyImportExportor - : public SingletonFunctionObject<GpgKeyImportExportor> { +class GpgKeyImportExporter + : public SingletonFunctionObject<GpgKeyImportExporter> { public: + explicit GpgKeyImportExporter( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<GpgKeyImportExporter>(channel) {} + GpgImportInformation ImportKey(StdBypeArrayPtr inBuffer); bool ExportKeys(KeyIdArgsListPtr& uid_list, ByteArrayPtr& out_buffer) const; @@ -99,7 +103,7 @@ class GpgKeyImportExportor private: GpgContext& ctx = - GpgContext::GetInstance(SingletonFunctionObject::GetDefaultChannel()); + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/gpg/function/GpgKeyManager.h b/src/gpg/function/GpgKeyManager.h index 01254962..b2444e8d 100644 --- a/src/gpg/function/GpgKeyManager.h +++ b/src/gpg/function/GpgKeyManager.h @@ -33,6 +33,10 @@ namespace GpgFrontend { class GpgKeyManager : public SingletonFunctionObject<GpgKeyManager> { public: + explicit GpgKeyManager( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<GpgKeyManager>(channel) {} + /** * Sign a key pair(actually a certain uid) * @param target target key pair @@ -50,7 +54,8 @@ class GpgKeyManager : public SingletonFunctionObject<GpgKeyManager> { std::unique_ptr<boost::posix_time::ptime>& expires); private: - GpgContext& ctx = GpgContext::GetInstance(); + GpgContext& ctx = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/gpg/function/GpgKeyOpera.cpp b/src/gpg/function/GpgKeyOpera.cpp index 4bad303d..4df06875 100644 --- a/src/gpg/function/GpgKeyOpera.cpp +++ b/src/gpg/function/GpgKeyOpera.cpp @@ -26,6 +26,7 @@ #include <boost/asio.hpp> #include <boost/date_time/posix_time/conversion.hpp> +#include <boost/format.hpp> #include <boost/process/async_pipe.hpp> #include <memory> #include <string> @@ -50,7 +51,7 @@ void GpgFrontend::GpgKeyOpera::DeleteKeys( err = check_gpg_error(gpgme_op_delete(ctx, gpgme_key_t(key), 1)); assert(gpg_err_code(err) == GPG_ERR_NO_ERROR); } else - LOG(WARNING) << "GpgKeyOpera DeleteKeys Get Key Bad"; + LOG(WARNING) << "GpgKeyOpera DeleteKeys get key failed" << key.fpr(); } } @@ -146,7 +147,7 @@ void GpgFrontend::GpgKeyOpera::GenerateRevokeCert( * @return error information */ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey( - const std::unique_ptr<GenKeyInfo>& params) { + const std::unique_ptr<GenKeyInfo>& params, GpgGenKeyResult& result) { auto userid_utf8 = params->getUserid(); const char* userid = userid_utf8.c_str(); auto algo_utf8 = params->getAlgo() + params->getKeySizeStr(); @@ -163,19 +164,53 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey( system_clock::to_time_t(system_clock::now()); } - unsigned int flags = 0; + GpgError err; - if (!params->isSubKey()) flags |= GPGME_CREATE_CERT; - if (params->isAllowEncryption()) flags |= GPGME_CREATE_ENCR; - if (params->isAllowSigning()) flags |= GPGME_CREATE_SIGN; - if (params->isAllowAuthentication()) flags |= GPGME_CREATE_AUTH; - if (params->isNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; - if (params->isNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; + if (ctx.GetInfo().GnupgVersion >= "2.1.0") { + unsigned int flags = 0; + + if (!params->isSubKey()) flags |= GPGME_CREATE_CERT; + if (params->isAllowEncryption()) flags |= GPGME_CREATE_ENCR; + if (params->isAllowSigning()) flags |= GPGME_CREATE_SIGN; + if (params->isAllowAuthentication()) flags |= GPGME_CREATE_AUTH; + if (params->isNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; + if (params->isNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; + + LOG(INFO) << "GpgFrontend::GpgKeyOpera::GenerateKey Args: " << userid + << algo << expires << flags; + + err = gpgme_op_createkey(ctx, userid, algo, 0, expires, nullptr, flags); - LOG(INFO) << "GpgFrontend::GpgKeyOpera::GenerateKey Args: " << userid << algo - << expires << flags; + } else { + std::stringstream ss; + + auto param_format = + boost::format{ + "<GnupgKeyParms format=\"internal\">\n" + "Key-Type: %1%\n" + "Subkey-Type: %2%\n" + "Name-Real: %3%\n" + "Name-Comment: %4%\n" + "Name-Email: %5%\n"} % + params->getAlgo() % params->getKeySize() % params->getName() % + params->getComment() % params->getEmail(); + ss << param_format; + + if (!params->isNonExpired()) + ss << boost::format{"Expire-Date: %1%\n"} % expires; + if (!params->isNoPassPhrase()) + ss << boost::format{"Passphrase: %1%\n"} % params->getPassPhrase(); + + ss << "</GnupgKeyParms>"; + + err = gpgme_op_genkey(ctx, ss.str().c_str(), nullptr, nullptr); + } + + if (check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR) { + auto temp_result = _new_result(gpgme_op_genkey_result(ctx)); + std::swap(temp_result, result); + } - auto err = gpgme_op_createkey(ctx, userid, algo, 0, expires, nullptr, flags); return check_gpg_error(err); } @@ -234,3 +269,9 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::ModifyTOFUPolicy( auto err = gpgme_op_tofu_policy(ctx, gpgme_key_t(key), tofu_policy); return check_gpg_error(err); } + +void GpgFrontend::GpgKeyOpera::DeleteKey(const GpgFrontend::KeyId& key_id) { + auto keys = std::make_unique<KeyIdArgsList>(); + keys->push_back(key_id); + DeleteKeys(std::move(keys)); +} diff --git a/src/gpg/function/GpgKeyOpera.h b/src/gpg/function/GpgKeyOpera.h index 7decfd79..73b8bdb5 100644 --- a/src/gpg/function/GpgKeyOpera.h +++ b/src/gpg/function/GpgKeyOpera.h @@ -33,8 +33,14 @@ namespace GpgFrontend { class GenKeyInfo; class GpgKeyOpera : public SingletonFunctionObject<GpgKeyOpera> { public: + explicit GpgKeyOpera( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<GpgKeyOpera>(channel) {} + void DeleteKeys(KeyIdArgsListPtr key_ids); + void DeleteKey(const KeyId& key_id); + GpgError SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr, std::unique_ptr<boost::posix_time::ptime>& expires); @@ -46,13 +52,15 @@ class GpgKeyOpera : public SingletonFunctionObject<GpgKeyOpera> { GpgFrontend::GpgError ModifyTOFUPolicy(const GpgKey& key, gpgme_tofu_policy_t tofu_policy); - GpgFrontend::GpgError GenerateKey(const std::unique_ptr<GenKeyInfo>& params); + GpgFrontend::GpgError GenerateKey(const std::unique_ptr<GenKeyInfo>& params, + GpgGenKeyResult& result); GpgFrontend::GpgError GenerateSubkey( const GpgKey& key, const std::unique_ptr<GenKeyInfo>& params); private: - GpgContext& ctx = GpgContext::GetInstance(); + GpgContext& ctx = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/gpg/function/UidOperator.h b/src/gpg/function/UidOperator.h index 7d5df254..d1a92b38 100644 --- a/src/gpg/function/UidOperator.h +++ b/src/gpg/function/UidOperator.h @@ -32,6 +32,10 @@ namespace GpgFrontend { class UidOperator : public SingletonFunctionObject<UidOperator> { public: + explicit UidOperator( + int channel = SingletonFunctionObject::GetDefaultChannel()) + : SingletonFunctionObject<UidOperator>(channel) {} + /** * create a new uid in certain key pair * @param key target key pair @@ -68,7 +72,8 @@ class UidOperator : public SingletonFunctionObject<UidOperator> { bool setPrimaryUID(const GpgKey& key, const std::string& uid); private: - GpgContext& ctx = GpgContext::GetInstance(); + GpgContext& ctx = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); }; } // namespace GpgFrontend diff --git a/src/ui/KeyImportDetailDialog.h b/src/ui/KeyImportDetailDialog.h index fe63baaa..a75d466d 100644 --- a/src/ui/KeyImportDetailDialog.h +++ b/src/ui/KeyImportDetailDialog.h @@ -25,7 +25,7 @@ #ifndef __KEYIMPORTDETAILSDIALOG_H__ #define __KEYIMPORTDETAILSDIALOG_H__ -#include <gpg/function/GpgKeyImportExportor.h> +#include <gpg/function/GpgKeyImportExporter.h> #include "gpg/GpgContext.h" #include "ui/GpgFrontendUI.h" diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp index c03b8e6b..9f599461 100755 --- a/src/ui/KeyMgmt.cpp +++ b/src/ui/KeyMgmt.cpp @@ -27,7 +27,7 @@ #include <utility> #include "gpg/function/GpgKeyGetter.h" -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" #include "gpg/function/GpgKeyOpera.h" #include "ui/SignalStation.h" #include "ui/UserInterfaceUtils.h" @@ -150,9 +150,8 @@ KeyMgmt::KeyMgmt(QWidget* parent) : QMainWindow(parent) { connect(this, SIGNAL(signalKeyStatusUpdated()), SignalStation::GetInstance(), SIGNAL(KeyDatabaseRefresh())); - connect(SignalStation::GetInstance(), - &SignalStation::signalRefreshStatusBar, this, - [=](const QString& message, int timeout) { + connect(SignalStation::GetInstance(), &SignalStation::signalRefreshStatusBar, + this, [=](const QString& message, int timeout) { statusBar()->showMessage(message, timeout); }); } diff --git a/src/ui/KeyServerImportDialog.cpp b/src/ui/KeyServerImportDialog.cpp index 844f2ae5..518b1b94 100644 --- a/src/ui/KeyServerImportDialog.cpp +++ b/src/ui/KeyServerImportDialog.cpp @@ -26,7 +26,7 @@ #include <utility> -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" #include "ui/SignalStation.h" #include "ui/settings/GlobalSettingStation.h" diff --git a/src/ui/KeyUploadDialog.cpp b/src/ui/KeyUploadDialog.cpp index 52aa2bd3..ab4e139e 100644 --- a/src/ui/KeyUploadDialog.cpp +++ b/src/ui/KeyUploadDialog.cpp @@ -27,15 +27,14 @@ #include <algorithm> #include "gpg/function/GpgKeyGetter.h" -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" #include "ui/settings/GlobalSettingStation.h" namespace GpgFrontend::UI { KeyUploadDialog::KeyUploadDialog(const KeyIdArgsListPtr& keys_ids, QWidget* parent) - : QDialog(parent), - mKeys(GpgKeyGetter::GetInstance().GetKeys(keys_ids)) { + : QDialog(parent), mKeys(GpgKeyGetter::GetInstance().GetKeys(keys_ids)) { auto* pb = new QProgressBar(); pb->setRange(0, 0); pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -60,7 +59,6 @@ void KeyUploadDialog::slotUpload() { void KeyUploadDialog::uploadKeyToServer( const GpgFrontend::ByteArray& keys_data) { - std::string target_keyserver; if (target_keyserver.empty()) { try { diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp index e4b9206a..8b5be042 100644 --- a/src/ui/keypair_details/KeyPairDetailTab.cpp +++ b/src/ui/keypair_details/KeyPairDetailTab.cpp @@ -25,7 +25,7 @@ #include "ui/keypair_details/KeyPairDetailTab.h" #include "gpg/function/GpgKeyGetter.h" -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" #include "gpg/function/GpgKeyOpera.h" #include "ui/SignalStation.h" #include "ui/UserInterfaceUtils.h" diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp index 2dd3f842..5671d943 100644 --- a/src/ui/main_window/MainWindowSlotFunction.cpp +++ b/src/ui/main_window/MainWindowSlotFunction.cpp @@ -37,7 +37,7 @@ #include "gpg/function/BasicOperator.h" #include "gpg/function/GpgKeyGetter.h" -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" #include "ui/UserInterfaceUtils.h" #include "ui/help/AboutDialog.h" #include "ui/settings/GlobalSettingStation.h" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 48b46832..cee1720b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,17 +7,21 @@ file(COPY ${CMAKE_SOURCE_DIR}/test/data DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ aux_source_directory(. TEST_SOURCE) add_executable( - ${AppName} - ${TEST_SOURCE} + ${AppName} + ${TEST_SOURCE} ) -if(GPG_CORE) +if (GPG_CORE) target_link_libraries(${AppName} gpg_core) -endif() +endif () + +if (GPG_STANDALONE_MODE) + file(COPY ${CMAKE_SOURCE_DIR}/test/gpg DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ FOLLOW_SYMLINK_CHAIN) +endif () target_link_libraries(${AppName} ${Boost_LIBRARIES} gtest gtest_main) -if(APPLE) -target_link_libraries(${AppName} intl) -endif() +if (APPLE) + target_link_libraries(${AppName} intl) +endif () add_test(AllTestsInGpgFrontend ${AppName}) diff --git a/test/GpgCoreTest.cpp b/test/GpgCoreTest.cpp new file mode 100644 index 00000000..ab9dbf28 --- /dev/null +++ b/test/GpgCoreTest.cpp @@ -0,0 +1,28 @@ +/** + * 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. + * + * Foobar 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 Foobar. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. + * + */ + +#include "GpgFrontendTest.h" + +// Should be used once and once-only +INITIALIZE_EASYLOGGINGPP diff --git a/test/GpgCoreTestImportExport.cpp b/test/GpgCoreTestImportExport.cpp index 9d01cc3e..1e226247 100644 --- a/test/GpgCoreTestImportExport.cpp +++ b/test/GpgCoreTestImportExport.cpp @@ -28,7 +28,7 @@ #include "GpgFrontendTest.h" #include "gpg/GpgConstants.h" #include "gpg/function/GpgKeyGetter.h" -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" #include "gpg/model/GpgKey.h" TEST_F(GpgCoreTest, CoreExportSecretTest) {}
\ No newline at end of file diff --git a/test/GpgCoreTestKeyModel.cpp b/test/GpgCoreTestKeyModel.cpp index 194eeed2..79cd7dcd 100644 --- a/test/GpgCoreTestKeyModel.cpp +++ b/test/GpgCoreTestKeyModel.cpp @@ -25,15 +25,11 @@ #include "GpgFrontendTest.h" #include "gpg/function/GpgKeyGetter.h" -// Should be used once and once-only -INITIALIZE_EASYLOGGINGPP - TEST_F(GpgCoreTest, CoreInitTest) { auto& ctx = GpgFrontend::GpgContext::GetInstance(default_channel); auto& ctx_default = GpgFrontend::GpgContext::GetInstance(); ASSERT_TRUE(ctx.good()); ASSERT_TRUE(ctx_default.good()); - ASSERT_EQ(ctx_default.GetInfo().DatabasePath, "default"); } TEST_F(GpgCoreTest, GpgDataTest) { diff --git a/test/GpgCoreTestKeyModelAlone.cpp b/test/GpgCoreTestKeyModelAlone.cpp index ecc7bcd2..3d5bd175 100644 --- a/test/GpgCoreTestKeyModelAlone.cpp +++ b/test/GpgCoreTestKeyModelAlone.cpp @@ -25,18 +25,12 @@ #include "GpgFrontendTest.h" #include "gpg/function/GpgKeyGetter.h" -// Should be used once and once-only -INITIALIZE_EASYLOGGINGPP - TEST_F(GpgCoreTest, CoreInitTestAlone) { auto& ctx = GpgFrontend::GpgContext::GetInstance(gpg_alone_channel); - auto& ctx_default = GpgFrontend::GpgContext::GetInstance(); ASSERT_TRUE(ctx.good()); - ASSERT_TRUE(ctx_default.good()); - ASSERT_EQ(ctx_default.GetInfo().DatabasePath, "default"); } -TEST_F(GpgCoreTest, GpgDataTest) { +TEST_F(GpgCoreTest, GpgDataTestAlone) { auto data_buff = std::string( "cqEh8fyKWtmiXrW2zzlszJVGJrpXDDpzgP7ZELGxhfZYFi8rMrSVKDwrpFZBSWMG"); @@ -46,6 +40,12 @@ TEST_F(GpgCoreTest, GpgDataTest) { ASSERT_EQ(out_buffer->size(), 64); } +TEST_F(GpgCoreTest, GpgKeyFetchTestAlone) { + auto keys = + GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel).FetchKey(); + ASSERT_EQ(keys->size(), 4); +} + TEST_F(GpgCoreTest, GpgKeyTestAlone) { auto key = GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel) .GetKey("9490795B78F8AFE9F93BD09281704859182661FB"); @@ -135,28 +135,16 @@ TEST_F(GpgCoreTest, GpgUIDTestAlone) { ASSERT_FALSE(uid.revoked()); } -TEST_F(GpgCoreTest, GpgKeySignatureTest) { +TEST_F(GpgCoreTest, GpgKeySignatureTestAlone) { auto key = GpgFrontend::GpgKeyGetter::GetInstance(gpg_alone_channel) .GetKey("9490795B78F8AFE9F93BD09281704859182661FB"); auto uids = key.uids(); ASSERT_EQ(uids->size(), 1); auto& uid = uids->front(); + // No key signature support auto signatures = uid.signatures(); - ASSERT_EQ(signatures->size(), 1); - auto& signature = signatures->front(); - - ASSERT_EQ(signature.name(), "GpgFrontendTest"); - ASSERT_TRUE(signature.comment().empty()); - ASSERT_EQ(signature.email(), "[email protected]"); - ASSERT_EQ(signature.keyid(), "81704859182661FB"); - ASSERT_EQ(signature.pubkey_algo(), "RSA"); - - ASSERT_FALSE(signature.revoked()); - ASSERT_FALSE(signature.invalid()); - ASSERT_EQ(GpgFrontend::check_gpg_error_2_err_code(signature.status()), - GPG_ERR_NO_ERROR); - ASSERT_EQ(signature.uid(), "GpgFrontendTest <[email protected]>"); + ASSERT_EQ(signatures->size(), 0); } TEST_F(GpgCoreTest, GpgKeyGetterTestAlone) { diff --git a/test/GpgCoreTestKeygen.cpp b/test/GpgCoreTestKeygen.cpp new file mode 100644 index 00000000..05d77af1 --- /dev/null +++ b/test/GpgCoreTestKeygen.cpp @@ -0,0 +1,52 @@ +/** + * 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. + * + * Foobar 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 Foobar. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from gpg4usb-team. + * Their source code version also complies with GNU General Public License. + * + * The source code version of this software was modified and released + * by Saturneric<[email protected]> starting on May 12, 2021. + * + */ + +#include "GpgFrontendTest.h" +#include "gpg/GpgGenKeyInfo.h" +#include "gpg/function/GpgKeyGetter.h" +#include "gpg/function/GpgKeyOpera.h" + +TEST_F(GpgCoreTest, GenerateKeyTest) { + auto& key_opera = GpgFrontend::GpgKeyOpera::GetInstance(default_channel); + auto keygen_info = std::make_unique<GpgFrontend::GenKeyInfo>(); + keygen_info->setName("foo"); + keygen_info->setEmail("[email protected]"); + keygen_info->setComment(""); + keygen_info->setAlgo("rsa"); + keygen_info->setNonExpired(true); + keygen_info->setNonPassPhrase(true); + + GpgFrontend::GpgGenKeyResult result = nullptr; + auto err = GpgFrontend::check_gpg_error_2_err_code( + key_opera.GenerateKey(keygen_info, result)); + ASSERT_EQ(err, GPG_ERR_NO_ERROR); + + auto fpr = result->fpr; + ASSERT_FALSE(fpr == nullptr); + + auto key = + GpgFrontend::GpgKeyGetter::GetInstance(default_channel).GetKey(fpr); + ASSERT_TRUE(key.good()); + key_opera.DeleteKey(fpr); +} diff --git a/test/GpgFrontendTest.h b/test/GpgFrontendTest.h index 0770c786..83778ee6 100644 --- a/test/GpgFrontendTest.h +++ b/test/GpgFrontendTest.h @@ -39,7 +39,7 @@ #include <vector> #include "gpg/GpgConstants.h" -#include "gpg/function/GpgKeyImportExportor.h" +#include "gpg/function/GpgKeyImportExporter.h" class GpgCoreTest : public ::testing::Test { protected: @@ -62,9 +62,14 @@ class GpgCoreTest : public ::testing::Test { GpgCoreTest() = default; - virtual ~GpgCoreTest() = default; + ~GpgCoreTest() override = default; + + void SetUp() override { + el::Loggers::addFlag(el::LoggingFlag::AutoSpacing); + el::Configurations defaultConf; + defaultConf.setToDefault(); + el::Loggers::reconfigureLogger("default", defaultConf); - virtual void SetUp() { using namespace libconfig; Config cfg; ASSERT_NO_THROW(cfg.readFile(config_path.c_str())); @@ -82,19 +87,34 @@ class GpgCoreTest : public ::testing::Test { dealing_private_keys(root); import_data(); + import_data_alone(); } - virtual void TearDown() {} + void TearDown() override {} private: void import_data() { GpgFrontend::GpgContext::GetInstance(default_channel) .SetPassphraseCb(GpgFrontend::GpgContext::test_passphrase_cb); + for (const auto& secret_key : secret_keys_) { + auto secret_key_copy = + std::make_unique<GpgFrontend::ByteArray>(*secret_key); + GpgFrontend::GpgKeyImportExporter::GetInstance(default_channel) + .ImportKey(std::move(secret_key_copy)); + } + } + + void import_data_alone() { + GpgFrontend::GpgContext::GetInstance(gpg_alone_channel) + .SetPassphraseCb(GpgFrontend::GpgContext::test_passphrase_cb); for (auto& secret_key : secret_keys_) { - GpgFrontend::GpgKeyImportExportor::GetInstance(default_channel) - .ImportKey(std::move(secret_key)); + auto secret_key_copy = + std::make_unique<GpgFrontend::ByteArray>(*secret_key); + GpgFrontend::GpgKeyImportExporter::GetInstance(gpg_alone_channel) + .ImportKey(std::move(secret_key_copy)); } } + void dealing_private_keys(const libconfig::Setting& root) { if (root.exists("load_keys.private_keys")) { auto& private_keys = root.lookup("load_keys.private_keys"); @@ -121,15 +141,24 @@ class GpgCoreTest : public ::testing::Test { auto gpg_path = parent_path / alone_gpg_path; std::string relative_db_path; - root.lookupValue("independent_db_path", relative_db_path); + root.lookupValue("alone_gpg_db_path", relative_db_path); auto db_path = parent_path / relative_db_path; if (!boost::filesystem::exists(db_path)) { boost::filesystem::create_directory(db_path); + } else { + boost::filesystem::remove_all(db_path); + boost::filesystem::create_directory(db_path); } GpgFrontend::GpgContext::CreateInstance( gpg_alone_channel, - std::make_unique<GpgFrontend::GpgContext>(true, db_path.c_str(), - true, gpg_path.c_str())); + [&]() -> std::unique_ptr<GpgFrontend::GpgContext> { + GpgFrontend::GpgContextInitArgs args; + args.gpg_alone = true; + args.independent_database = true; + args.db_path = db_path.string(); + args.gpg_path = gpg_path.string(); + return std::make_unique<GpgFrontend::GpgContext>(args); + }); } } } @@ -144,10 +173,18 @@ class GpgCoreTest : public ::testing::Test { auto db_path = parent_path / relative_db_path; if (!boost::filesystem::exists(db_path)) { boost::filesystem::create_directory(db_path); + } else { + boost::filesystem::remove_all(db_path); + boost::filesystem::create_directory(db_path); } + GpgFrontend::GpgContext::CreateInstance( - default_channel, - std::make_unique<GpgFrontend::GpgContext>(true, db_path.c_str())); + default_channel, [&]() -> std::unique_ptr<GpgFrontend::GpgContext> { + GpgFrontend::GpgContextInitArgs args; + args.independent_database = true; + args.db_path = db_path.string(); + return std::make_unique<GpgFrontend::GpgContext>(args); + }); } } } diff --git a/test/conf/core.cfg b/test/conf/core.cfg index c49767ea..7a9b76d6 100644 --- a/test/conf/core.cfg +++ b/test/conf/core.cfg @@ -3,7 +3,8 @@ version = "1.0"; independent_database = true; independent_db_path = "db"; alone_gpg = true; -alone_gpg_path = "gpg/gpg"; +alone_gpg_path = "gpg/gpg1"; +alone_gpg_db_path = "alone_db"; data_path = "data"; load_keys = { |