diff options
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 = { |