diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpg/GpgContext.cpp | 35 | ||||
-rw-r--r-- | src/gpg/GpgContext.h | 31 | ||||
-rw-r--r-- | src/gpg/GpgFunctionObject.h | 113 | ||||
-rw-r--r-- | src/gpg/function/GpgKeyGetter.cpp | 1 | ||||
-rw-r--r-- | src/gpg/function/GpgKeyGetter.h | 18 | ||||
-rw-r--r-- | src/gpg/function/GpgKeyImportExportor.cpp | 64 | ||||
-rw-r--r-- | src/gpg/function/GpgKeyImportExportor.h | 22 |
7 files changed, 208 insertions, 76 deletions
diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index a8c9a6de..c1911a17 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -23,9 +23,13 @@ */ #include "gpg/GpgContext.h" -#include "GpgConstants.h" +#include <gpg-error.h> +#include <gpgme.h> #include <functional> +#include <string> + +#include "GpgConstants.h" #ifdef _WIN32 #include <windows.h> @@ -39,7 +43,10 @@ namespace GpgFrontend { * Constructor * Set up gpgme-context, set paths to app-run path */ -GpgContext::GpgContext() { +GpgContext::GpgContext(bool independent_database, + std::string db_path, + int channel) + : SingletonFunctionObject<GpgContext>(channel) { static bool _first = true; if (_first) { @@ -57,25 +64,26 @@ GpgContext::GpgContext() { check_gpg_error(gpgme_new(&_p_ctx)); _ctx_ref = CtxRefHandler(_p_ctx); - LOG(INFO) << "GpgContext _ctx_ref Created"; + DLOG(INFO) << "GpgContext _ctx_ref Created"; auto engineInfo = gpgme_ctx_get_engine_info(*this); - LOG(INFO) << "GpgContext gpgme_ctx_get_engine_info Called"; + DLOG(INFO) << "GpgContext gpgme_ctx_get_engine_info Called"; // Check ENV before running bool check_pass = false, find_openpgp = false, find_gpgconf = false, find_assuan = false, find_cms = false; while (engineInfo != nullptr) { - LOG(INFO) << gpgme_get_protocol_name(engineInfo->protocol) << " " - << engineInfo->file_name << " " << engineInfo->version; + DLOG(INFO) << gpgme_get_protocol_name(engineInfo->protocol) << " " + << engineInfo->file_name << " " << engineInfo->version; if (engineInfo->protocol == GPGME_PROTOCOL_GPGCONF && strcmp(engineInfo->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; + find_openpgp = true, info.AppPath = engineInfo->file_name, + info.DatabasePath = "default"; if (engineInfo->protocol == GPGME_PROTOCOL_CMS && strcmp(engineInfo->version, "1.0.0") != 0) find_cms = true; @@ -87,11 +95,21 @@ GpgContext::GpgContext() { if (find_gpgconf && find_openpgp && find_cms && find_assuan) check_pass = true; - LOG(INFO) << "GpgContext check_pass " << check_pass; + DLOG(INFO) << "GpgContext check_pass " << check_pass; if (!check_pass) { good_ = false; return; } else { + // Set Independent Database + if (independent_database) { + info.DatabasePath = db_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); + DLOG(INFO) << "Set independent_database path" << db_path; + } + /** Setting the output type must be done at the beginning */ /** think this means ascii-armor --> ? */ gpgme_set_armor(*this, 1); @@ -104,6 +122,7 @@ GpgContext::GpgContext() { GPGME_KEYLIST_MODE_WITH_TOFU)); good_ = true; } + DLOG(INFO) << "GpgContext init done "; } bool GpgContext::good() const { diff --git a/src/gpg/GpgContext.h b/src/gpg/GpgContext.h index 21fb5aee..0aa41f2f 100644 --- a/src/gpg/GpgContext.h +++ b/src/gpg/GpgContext.h @@ -35,21 +35,22 @@ namespace GpgFrontend { * Custom Encapsulation of GpgME APIs */ class GpgContext : public SingletonFunctionObject<GpgContext> { - -public: - GpgContext(); + public: + GpgContext(bool independent_database = false, + std::string path = std::string(), + int channel = 0); ~GpgContext() override = default; [[nodiscard]] bool good() const; - [[nodiscard]] const GpgInfo &GetInfo() const { return info; } + [[nodiscard]] const GpgInfo& GetInfo() const { return info; } static std::string getGpgmeVersion(); operator gpgme_ctx_t() const { return _ctx_ref.get(); } -private: + private: GpgInfo info; struct _ctx_ref_deletor { @@ -59,17 +60,17 @@ private: } }; - using CtxRefHandler = - std::unique_ptr<struct gpgme_context, _ctx_ref_deletor>; + using CtxRefHandler = std::unique_ptr<struct gpgme_context, _ctx_ref_deletor>; CtxRefHandler _ctx_ref = nullptr; bool good_ = true; -public: - static gpgme_error_t test_passphrase_cb(void *opaque, const char *uid_hint, - const char *passphrase_info, - int last_was_bad, int fd) { - + public: + static gpgme_error_t test_passphrase_cb(void* opaque, + const char* uid_hint, + const char* passphrase_info, + int last_was_bad, + int fd) { LOG(INFO) << "test_passphrase_cb Called"; size_t res; char pass[] = "abcdefg\n"; @@ -82,7 +83,7 @@ public: (void)last_was_bad; do { - res = gpgme_io_write(fd, &pass[off], pass_len - off); + res = gpgme_io_write(fd, &pass[off], pass_len - off); if (res > 0) off += res; } while (res > 0 && off != pass_len); @@ -92,6 +93,6 @@ public: void SetPassphraseCb(decltype(test_passphrase_cb) func) const; }; -} // namespace GpgFrontend +} // namespace GpgFrontend -#endif // __SGPGMEPP_CONTEXT_H__ +#endif // __SGPGMEPP_CONTEXT_H__ diff --git a/src/gpg/GpgFunctionObject.h b/src/gpg/GpgFunctionObject.h index 654f81d3..cb55cf92 100644 --- a/src/gpg/GpgFunctionObject.h +++ b/src/gpg/GpgFunctionObject.h @@ -25,44 +25,121 @@ #ifndef GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H #define GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H +#include <map> #include <memory> #include <mutex> +#include <shared_mutex> +#include <stdexcept> +#include <string> #include <easyloggingpp/easylogging++.h> namespace GpgFrontend { -template <typename T> class SingletonFunctionObject { -public: - static T &GetInstance() { - LOG(INFO) << "SingletonFunctionObject GetInstance Calling " - << typeid(T).name(); - std::lock_guard<std::mutex> guard(_instance_mutex); - if (_instance == nullptr) - _instance = std::make_unique<T>(); - return *_instance; + +template <typename T> +class SingletonFunctionObject { + public: + static T& GetInstance(int channel = 0) { + DLOG(INFO) << "SingletonFunctionObject GetInstance Calling " + << typeid(T).name() << " channel " << channel; + 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); + } } - SingletonFunctionObject(T &&) = delete; + static T& CreateInstance(int channel, std::unique_ptr<T> p_obj = nullptr) { + DLOG(INFO) << "SingletonFunctionObject CreateInstance Calling " + << typeid(T).name() << " channel " << channel; + if (!channel) + return *_instance; + + // read _instances_map + 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; + } + } + + static int GetDefaultChannel() { return _default_channel; } + + int GetChannel() const { return channel_; } + + SingletonFunctionObject(T&&) = delete; + + SingletonFunctionObject(const T&) = delete; - SingletonFunctionObject(const T &) = delete; + void operator=(const T&) = delete; - void operator=(const T &) = delete; + protected: + SingletonFunctionObject() {} -protected: - SingletonFunctionObject() = default; + SingletonFunctionObject(int channel) : channel_(channel) {} virtual ~SingletonFunctionObject() = default; -private: + 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; }; -template <typename T> std::mutex SingletonFunctionObject<T>::_instance_mutex; +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> +std::shared_mutex SingletonFunctionObject<T>::_instances_mutex; template <typename T> std::unique_ptr<T> SingletonFunctionObject<T>::_instance = nullptr; -} // namespace GpgFrontend +template <typename T> +std::map<int, std::unique_ptr<T>> SingletonFunctionObject<T>::_instances_map; + +} // namespace GpgFrontend -#endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H +#endif // GPGFRONTEND_ZH_CN_TS_FUNCTIONOBJECT_H diff --git a/src/gpg/function/GpgKeyGetter.cpp b/src/gpg/function/GpgKeyGetter.cpp index 6d80088a..ab907ea7 100644 --- a/src/gpg/function/GpgKeyGetter.cpp +++ b/src/gpg/function/GpgKeyGetter.cpp @@ -32,6 +32,7 @@ GpgFrontend::GpgKey GpgFrontend::GpgKeyGetter::GetKey(const std::string& fpr) { gpgme_get_key(ctx, fpr.c_str(), &_p_key, 1); if (_p_key == nullptr) DLOG(WARNING) << "GpgKeyGetter GetKey _p_key Null"; + assert(_p_key != nullptr); return GpgKey(std::move(_p_key)); } diff --git a/src/gpg/function/GpgKeyGetter.h b/src/gpg/function/GpgKeyGetter.h index 3a291d2d..af22e2f2 100644 --- a/src/gpg/function/GpgKeyGetter.h +++ b/src/gpg/function/GpgKeyGetter.h @@ -32,19 +32,19 @@ namespace GpgFrontend { class GpgKeyGetter : public SingletonFunctionObject<GpgKeyGetter> { + public: + GpgKeyGetter() = default; -public: - GpgKey GetKey(const std::string &fpr); + GpgKey GetKey(const std::string& fpr); - GpgKey GetPubkey(const std::string &fpr); + GpgKey GetPubkey(const std::string& fpr); KeyListPtr FetchKey(); - GpgKeyGetter() = default; - -private: - GpgContext &ctx = GpgContext::GetInstance(); + private: + GpgContext& ctx = + GpgContext::GetInstance(SingletonFunctionObject::GetDefaultChannel()); }; -} // namespace GpgFrontend +} // namespace GpgFrontend -#endif // GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H +#endif // GPGFRONTEND_ZH_CN_TS_GPGKEYGETTER_H diff --git a/src/gpg/function/GpgKeyImportExportor.cpp b/src/gpg/function/GpgKeyImportExportor.cpp index 2ee261b4..7a7af4c7 100644 --- a/src/gpg/function/GpgKeyImportExportor.cpp +++ b/src/gpg/function/GpgKeyImportExportor.cpp @@ -1,32 +1,62 @@ +/** + * 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 "gpg/function/GpgKeyImportExportor.h" + #include "GpgConstants.h" -#include <gpg-error.h> /** * Import key pair * @param inBuffer input byte array * @return Import information */ -GpgFrontend::GpgImportInformation -GpgFrontend::GpgKeyImportExportor::ImportKey(StdBypeArrayPtr in_buffer) { - LOG(INFO) << "ImportKey Called in_buffer Size " << in_buffer->size(); +GpgFrontend::GpgImportInformation GpgFrontend::GpgKeyImportExportor::ImportKey( + StdBypeArrayPtr in_buffer) { + DLOG(INFO) << "ImportKey called in_buffer Size " << in_buffer->size(); + + if (in_buffer->empty()) + return GpgImportInformation(); + GpgData data_in(in_buffer->data(), in_buffer->size()); + DLOG(INFO) << "ImportKey gpgme_op_import"; auto err = check_gpg_error(gpgme_op_import(ctx, data_in)); assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR); gpgme_import_result_t result; - + DLOG(INFO) << "ImportKey gpgme_op_import_result"; result = gpgme_op_import_result(ctx); gpgme_import_status_t status = result->imports; auto import_info = std::make_unique<GpgImportInformation>(result); - LOG(INFO) << "ImportKey import_information " << result->not_imported << " " - << result->imported << " " << result->considered; + DLOG(INFO) << "ImportKey import_information " << result->not_imported << " " + << result->imported << " " << result->considered; while (status != nullptr) { GpgImportedKey key; key.import_status = static_cast<int>(status->status); key.fpr = status->fpr; import_info->importedKeys.emplace_back(key); status = status->next; - LOG(INFO) << "ImportKey Fpr " << key.fpr << " Status " << key.import_status; + DLOG(INFO) << "ImportKey Fpr " << key.fpr << " Status " + << key.import_status; } return *import_info; } @@ -38,7 +68,8 @@ GpgFrontend::GpgKeyImportExportor::ImportKey(StdBypeArrayPtr in_buffer) { * @return if success */ bool GpgFrontend::GpgKeyImportExportor::ExportKeys( - KeyIdArgsListPtr &uid_list, BypeArrayPtr &out_buffer) const { + KeyIdArgsListPtr& uid_list, + BypeArrayPtr& out_buffer) const { if (uid_list->empty()) return false; @@ -49,8 +80,8 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKeys( auto err = gpgme_op_export(ctx, (*uid_list)[i].c_str(), 0, data_out); assert(gpgme_err_code(err) == GPG_ERR_NO_ERROR); - LOG(INFO) << "exportKeys read_bytes" - << gpgme_data_seek(data_out, 0, SEEK_END); + DLOG(INFO) << "exportKeys read_bytes" + << gpgme_data_seek(data_out, 0, SEEK_END); auto temp_out_buffer = data_out.Read2Buffer(); std::swap(out_buffer, temp_out_buffer); @@ -66,9 +97,10 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKeys( * @return if success */ bool GpgFrontend::GpgKeyImportExportor::ExportKeys( - KeyArgsList &keys, BypeArrayPtr &out_buffer) const { + KeyArgsList& keys, + BypeArrayPtr& out_buffer) const { KeyIdArgsListPtr key_ids = std::make_unique<std::vector<std::string>>(); - for (const auto &key : keys) + for (const auto& key : keys) key_ids->push_back(key.id()); return ExportKeys(key_ids, out_buffer); } @@ -80,9 +112,9 @@ bool GpgFrontend::GpgKeyImportExportor::ExportKeys( * @return if successful */ bool GpgFrontend::GpgKeyImportExportor::ExportSecretKey( - const GpgKey &key, BypeArrayPtr out_buffer) const { - - LOG(INFO) << "Export Secret Key" << key.id().c_str(); + const GpgKey& key, + BypeArrayPtr out_buffer) const { + DLOG(INFO) << "Export Secret Key" << key.id().c_str(); gpgme_key_t target_key[2] = {gpgme_key_t(key), nullptr}; diff --git a/src/gpg/function/GpgKeyImportExportor.h b/src/gpg/function/GpgKeyImportExportor.h index 455e59f8..2cdb4e80 100644 --- a/src/gpg/function/GpgKeyImportExportor.h +++ b/src/gpg/function/GpgKeyImportExportor.h @@ -25,6 +25,7 @@ #ifndef _GPGKEYIMPORTEXPORTOR_H #define _GPGKEYIMPORTEXPORTOR_H +#include <string> #include "gpg/GpgConstants.h" #include "gpg/GpgContext.h" #include "gpg/GpgFunctionObject.h" @@ -33,7 +34,7 @@ namespace GpgFrontend { class GpgImportedKey { -public: + public: std::string fpr; int import_status; }; @@ -41,7 +42,7 @@ public: typedef std::list<GpgImportedKey> GpgImportedKeyList; class GpgImportInformation { -public: + public: GpgImportInformation() = default; explicit GpgImportInformation(gpgme_import_result_t result) { @@ -93,19 +94,20 @@ public: class GpgKeyImportExportor : public SingletonFunctionObject<GpgKeyImportExportor> { -public: + public: GpgImportInformation ImportKey(StdBypeArrayPtr inBuffer); - bool ExportKeys(KeyIdArgsListPtr &uid_list, BypeArrayPtr &out_buffer) const; + bool ExportKeys(KeyIdArgsListPtr& uid_list, BypeArrayPtr& out_buffer) const; - bool ExportKeys(KeyArgsList &keys, BypeArrayPtr &outBuffer) const; + bool ExportKeys(KeyArgsList& keys, BypeArrayPtr& outBuffer) const; - bool ExportSecretKey(const GpgKey &key, BypeArrayPtr outBuffer) const; + bool ExportSecretKey(const GpgKey& key, BypeArrayPtr outBuffer) const; -private: - GpgContext &ctx = GpgContext::GetInstance(); + private: + GpgContext& ctx = + GpgContext::GetInstance(SingletonFunctionObject::GetDefaultChannel()); }; -} // namespace GpgFrontend +} // namespace GpgFrontend -#endif // _GPGKEYIMPORTEXPORTOR_H
\ No newline at end of file +#endif // _GPGKEYIMPORTEXPORTOR_H
\ No newline at end of file |