diff options
Diffstat (limited to 'src/core/function/gpg')
24 files changed, 999 insertions, 217 deletions
diff --git a/src/core/function/gpg/GpgAbstractKeyGetter.cpp b/src/core/function/gpg/GpgAbstractKeyGetter.cpp new file mode 100644 index 00000000..0b544469 --- /dev/null +++ b/src/core/function/gpg/GpgAbstractKeyGetter.cpp @@ -0,0 +1,85 @@ +/** + * Copyright (C) 2021-2024 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GpgAbstractKeyGetter.h" + +#include "core/model/GpgKeyTableModel.h" +#include "core/utils/GpgUtils.h" + +namespace GpgFrontend { + +GpgAbstractKeyGetter::GpgAbstractKeyGetter(int channel) + : SingletonFunctionObject<GpgAbstractKeyGetter>(channel){}; + +auto GpgAbstractKeyGetter::Fetch() -> GpgAbstractKeyPtrList { + auto ret = GpgAbstractKeyPtrList{}; + + auto keys = key_.Fetch(); + for (const auto& key : keys) { + ret.push_back(qSharedPointerCast<GpgAbstractKey>(key)); + } + + auto kgs = kg_.Fetch(); + for (const auto& kg : kgs) { + ret.push_back(qSharedPointerCast<GpgAbstractKey>(kg)); + } + + return ret; +} + +auto GpgAbstractKeyGetter::GetGpgKeyTableModel() + -> QSharedPointer<GpgKeyTableModel> { + return SecureCreateQSharedObject<GpgKeyTableModel>( + SingletonFunctionObject::GetChannel(), Fetch(), nullptr); +} + +auto GpgAbstractKeyGetter::FlushCache() -> bool { + return key_.FlushKeyCache() && kg_.FlushCache(); +} + +auto GpgAbstractKeyGetter::GetKey(const QString& key_id) -> GpgAbstractKeyPtr { + if (IsKeyGroupID(key_id)) { + return kg_.KeyGroup(key_id); + } + return key_.GetKeyPtr(key_id); +} + +auto GpgAbstractKeyGetter::GetKeys(const QStringList& key_ids) + -> GpgAbstractKeyPtrList { + auto ret = GpgAbstractKeyPtrList{}; + for (const auto& key_id : key_ids) { + auto key = GetKey(key_id); + if (key == nullptr) continue; + + ret.push_back(key); + } + return ret; +} + +GpgAbstractKeyGetter::~GpgAbstractKeyGetter() = default; +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgAbstractKeyGetter.h b/src/core/function/gpg/GpgAbstractKeyGetter.h new file mode 100644 index 00000000..571121a9 --- /dev/null +++ b/src/core/function/gpg/GpgAbstractKeyGetter.h @@ -0,0 +1,102 @@ +/** + * Copyright (C) 2021-2024 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/function/basic/GpgFunctionObject.h" +#include "core/function/gpg/GpgKeyGetter.h" +#include "core/function/gpg/GpgKeyGroupGetter.h" +#include "core/typedef/GpgTypedef.h" + +namespace GpgFrontend { + +class GpgKeyTableModel; + +/** + * @brief + * + */ +class GPGFRONTEND_CORE_EXPORT GpgAbstractKeyGetter + : public SingletonFunctionObject<GpgAbstractKeyGetter> { + public: + /** + * @brief Construct a new Gpg Key Getter object + * + * @param channel + */ + explicit GpgAbstractKeyGetter(int channel = kGpgFrontendDefaultChannel); + + /** + * @brief Destroy the Gpg Key Getter object + * + */ + ~GpgAbstractKeyGetter(); + + /** + * @brief Get the Key object + * + * @param fpr + * @return GpgKey + */ + auto GetKey(const QString& key_id) -> GpgAbstractKeyPtr; + + /** + * @brief Get the Keys object + * + * @param key_ids + * @return auto + */ + auto GetKeys(const QStringList& key_ids) -> GpgAbstractKeyPtrList; + + /** + * @brief Get all the keys by receiving a linked list + * + * @return KeyLinkListPtr + */ + auto Fetch() -> GpgAbstractKeyPtrList; + + /** + * @brief flush the keys in the cache + * + */ + auto FlushCache() -> bool; + + /** + * @brief + * + * @return GpgKeyTableModel + */ + auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel>; + + private: + GpgKeyGetter& key_ = + GpgKeyGetter::GetInstance(SingletonFunctionObject::GetChannel()); + GpgKeyGroupGetter& kg_ = + GpgKeyGroupGetter::GetInstance(SingletonFunctionObject::GetChannel()); +}; +} // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgAdvancedOperator.h b/src/core/function/gpg/GpgAdvancedOperator.h index cfd5fbcf..57279adb 100644 --- a/src/core/function/gpg/GpgAdvancedOperator.h +++ b/src/core/function/gpg/GpgAdvancedOperator.h @@ -32,7 +32,7 @@ #pragma once -#include "core/typedef/CoreTypedef.h" +#include "core/model/DataObject.h" namespace GpgFrontend { diff --git a/src/core/function/gpg/GpgAssuanHelper.h b/src/core/function/gpg/GpgAssuanHelper.h index 6e58e27c..a0c45d7a 100644 --- a/src/core/function/gpg/GpgAssuanHelper.h +++ b/src/core/function/gpg/GpgAssuanHelper.h @@ -113,6 +113,10 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); QMap<GpgComponentType, assuan_context_t> assuan_ctx_; + QByteArray temp_data_; + QString temp_status_; + QString gpgconf_path_; + /** * @brief * @@ -169,10 +173,6 @@ class GPGFRONTEND_CORE_EXPORT GpgAssuanHelper */ static auto default_inquery_callback(void* opaque, const char* inquery) -> gpgme_error_t; - - QByteArray temp_data_; - QString temp_status_; - QString gpgconf_path_; }; }; // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgAutomatonHandler.cpp b/src/core/function/gpg/GpgAutomatonHandler.cpp index af2f0cba..b2d9d562 100644 --- a/src/core/function/gpg/GpgAutomatonHandler.cpp +++ b/src/core/function/gpg/GpgAutomatonHandler.cpp @@ -97,13 +97,13 @@ auto GpgAutomatonHandler::interator_cb_func(void* handle, const char* status, } auto GpgAutomatonHandler::DoInteract( - const GpgKey& key, AutomatonNextStateHandler next_state_handler, + const GpgKeyPtr& key, AutomatonNextStateHandler next_state_handler, AutomatonActionHandler action_handler, int flags) -> bool { gpgme_key_t p_key = - flags == GPGME_INTERACT_CARD ? nullptr : static_cast<gpgme_key_t>(key); + flags == GPGME_INTERACT_CARD ? nullptr : static_cast<gpgme_key_t>(*key); AutomatonHandelStruct handel_struct( - flags == GPGME_INTERACT_CARD ? "" : key.Fingerprint()); + flags == GPGME_INTERACT_CARD ? "" : key->Fingerprint()); handel_struct.SetHandler(std::move(next_state_handler), std::move(action_handler)); diff --git a/src/core/function/gpg/GpgAutomatonHandler.h b/src/core/function/gpg/GpgAutomatonHandler.h index f86299e8..cdf96060 100644 --- a/src/core/function/gpg/GpgAutomatonHandler.h +++ b/src/core/function/gpg/GpgAutomatonHandler.h @@ -97,7 +97,7 @@ class GpgAutomatonHandler * @return true * @return false */ - auto DoInteract(const GpgKey& key, + auto DoInteract(const GpgKeyPtr& key, AutomatonNextStateHandler next_state_handler, AutomatonActionHandler action_handler, int flags = 0) -> bool; diff --git a/src/core/function/gpg/GpgBasicOperator.cpp b/src/core/function/gpg/GpgBasicOperator.cpp index 2548409e..43917db3 100644 --- a/src/core/function/gpg/GpgBasicOperator.cpp +++ b/src/core/function/gpg/GpgBasicOperator.cpp @@ -43,15 +43,17 @@ namespace GpgFrontend { GpgBasicOperator::GpgBasicOperator(int channel) : SingletonFunctionObject<GpgBasicOperator>(channel) {} -void SetSignersImpl(GpgContext& ctx_, const KeyArgsList& signers, bool ascii) { +void SetSignersImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& signers, + bool ascii) { auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); gpgme_signers_clear(ctx); - for (const GpgKey& key : signers) { - LOG_D() << "signer's key fpr: " << key.Fingerprint(); - if (key.IsHasActualSignCap()) { - auto error = gpgme_signers_add(ctx, gpgme_key_t(key)); + auto keys = ConvertKey2GpgKeyList(ctx_.GetChannel(), signers); + for (const auto& key : keys) { + LOG_D() << "signer's key fpr: " << key->Fingerprint(); + if (key->IsHasSignCap()) { + auto error = gpgme_signers_add(ctx, static_cast<gpgme_key_t>(*key)); CheckGpgError(error); } } @@ -62,10 +64,10 @@ void SetSignersImpl(GpgContext& ctx_, const KeyArgsList& signers, bool ascii) { } } -auto EncryptImpl(GpgContext& ctx_, const KeyArgsList& keys, +auto EncryptImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys, const GFBuffer& in_buffer, bool ascii, const DataObjectPtr& data_object) -> GpgError { - auto recipients = Convert2RawGpgMEKeyList(keys); + auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys); GpgData data_in(in_buffer); GpgData data_out; @@ -82,7 +84,7 @@ auto EncryptImpl(GpgContext& ctx_, const KeyArgsList& keys, return err; } -void GpgBasicOperator::Encrypt(const KeyArgsList& keys, +void GpgBasicOperator::Encrypt(const GpgAbstractKeyPtrList& keys, const GFBuffer& in_buffer, bool ascii, const GpgOperationCallback& cb) { RunGpgOperaAsync( @@ -92,7 +94,7 @@ void GpgBasicOperator::Encrypt(const KeyArgsList& keys, cb, "gpgme_op_encrypt", "2.1.0"); } -auto GpgBasicOperator::EncryptSync(const KeyArgsList& keys, +auto GpgBasicOperator::EncryptSync(const GpgAbstractKeyPtrList& keys, const GFBuffer& in_buffer, bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( @@ -199,7 +201,7 @@ auto GpgBasicOperator::VerifySync(const GFBuffer& in_buffer, "gpgme_op_verify", "2.1.0"); } -auto SignImpl(GpgContext& ctx_, const KeyArgsList& signers, +auto SignImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, GpgSignMode mode, bool ascii, const DataObjectPtr& data_object) -> GpgError { if (signers.empty()) return GPG_ERR_CANCELED; @@ -222,7 +224,7 @@ auto SignImpl(GpgContext& ctx_, const KeyArgsList& signers, return err; } -void GpgBasicOperator::Sign(const KeyArgsList& signers, +void GpgBasicOperator::Sign(const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, GpgSignMode mode, bool ascii, const GpgOperationCallback& cb) { RunGpgOperaAsync( @@ -233,8 +235,8 @@ void GpgBasicOperator::Sign(const KeyArgsList& signers, } auto GpgBasicOperator::SignSync( - const KeyArgsList& signers, const GFBuffer& in_buffer, GpgSignMode mode, - bool ascii) -> std::tuple<GpgError, DataObjectPtr> { + const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, + GpgSignMode mode, bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) { return SignImpl(ctx_, signers, in_buffer, mode, ascii, data_object); @@ -279,13 +281,14 @@ auto GpgBasicOperator::DecryptVerifySync(const GFBuffer& in_buffer) "gpgme_op_decrypt_verify", "2.1.0"); } -auto EncryptSignImpl(GpgContext& ctx_, const KeyArgsList& keys, - const KeyArgsList& signers, const GFBuffer& in_buffer, - bool ascii, const DataObjectPtr& data_object) -> GpgError { +auto EncryptSignImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signers, + const GFBuffer& in_buffer, bool ascii, + const DataObjectPtr& data_object) -> GpgError { if (keys.empty() || signers.empty()) return GPG_ERR_CANCELED; GpgError err; - QContainer<gpgme_key_t> recipients(keys.begin(), keys.end()); + auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys); // Last entry data_in array has to be nullptr recipients.push_back(nullptr); @@ -307,8 +310,8 @@ auto EncryptSignImpl(GpgContext& ctx_, const KeyArgsList& keys, return err; } -void GpgBasicOperator::EncryptSign(const KeyArgsList& keys, - const KeyArgsList& signers, +void GpgBasicOperator::EncryptSign(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, bool ascii, const GpgOperationCallback& cb) { RunGpgOperaAsync( @@ -319,8 +322,8 @@ void GpgBasicOperator::EncryptSign(const KeyArgsList& keys, cb, "gpgme_op_encrypt_sign", "2.1.0"); } -auto GpgBasicOperator::EncryptSignSync(const KeyArgsList& keys, - const KeyArgsList& signers, +auto GpgBasicOperator::EncryptSignSync(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, bool ascii) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( @@ -331,7 +334,8 @@ auto GpgBasicOperator::EncryptSignSync(const KeyArgsList& keys, "gpgme_op_encrypt_sign", "2.1.0"); } -void GpgBasicOperator::SetSigners(const KeyArgsList& signers, bool ascii) { +void GpgBasicOperator::SetSigners(const GpgAbstractKeyPtrList& signers, + bool ascii) { SetSignersImpl(ctx_, signers, ascii); } diff --git a/src/core/function/gpg/GpgBasicOperator.h b/src/core/function/gpg/GpgBasicOperator.h index 990d7af5..ac6908f4 100644 --- a/src/core/function/gpg/GpgBasicOperator.h +++ b/src/core/function/gpg/GpgBasicOperator.h @@ -56,14 +56,14 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator * @brief * */ - void Encrypt(const KeyArgsList&, const GFBuffer&, bool, + void Encrypt(const GpgAbstractKeyPtrList&, const GFBuffer&, bool, const GpgOperationCallback&); /** * @brief * */ - auto EncryptSync(const KeyArgsList&, const GFBuffer&, + auto EncryptSync(const GpgAbstractKeyPtrList&, const GFBuffer&, bool) -> std::tuple<GpgError, DataObjectPtr>; /** @@ -99,7 +99,8 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator * @param ascii ascii mode * @return */ - void EncryptSign(const KeyArgsList& keys, const KeyArgsList& signers, + void EncryptSign(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, bool ascii, const GpgOperationCallback& cb); @@ -112,7 +113,8 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator * @param ascii * @param cb */ - auto EncryptSignSync(const KeyArgsList& keys, const KeyArgsList& signers, + auto EncryptSignSync(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, bool ascii) -> std::tuple<GpgError, DataObjectPtr>; @@ -196,7 +198,7 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator * @param result the result of the operation * @return error code */ - void Sign(const KeyArgsList& signers, const GFBuffer& in_buffer, + void Sign(const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, GpgSignMode mode, bool ascii, const GpgOperationCallback& cb); /** @@ -209,7 +211,7 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator * @param cb * @return std::tuple<GpgError, DataObjectPtr> */ - auto SignSync(const KeyArgsList& signers, const GFBuffer& in_buffer, + auto SignSync(const GpgAbstractKeyPtrList& signers, const GFBuffer& in_buffer, GpgSignMode mode, bool ascii) -> std::tuple<GpgError, DataObjectPtr>; @@ -219,7 +221,7 @@ class GPGFRONTEND_CORE_EXPORT GpgBasicOperator * * @param keys */ - void SetSigners(const KeyArgsList& signers, bool ascii); + void SetSigners(const GpgAbstractKeyPtrList& signers, bool ascii); /** * @brief Get a global signature private keys that has been set. diff --git a/src/core/function/gpg/GpgContext.cpp b/src/core/function/gpg/GpgContext.cpp index 88eb3c1b..de450356 100644 --- a/src/core/function/gpg/GpgContext.cpp +++ b/src/core/function/gpg/GpgContext.cpp @@ -189,6 +189,8 @@ class GpgContext::Impl { return component_dirs_.value(component_type_to_q_string(type), ""); } + [[nodiscard]] auto KeyDBName() const -> QString { return db_name_; } + private: GpgContext *parent_; GpgContextInitArgs args_{}; ///< @@ -199,6 +201,7 @@ class GpgContext::Impl { std::mutex ctx_ref_lock_; std::mutex binary_ctx_ref_lock_; + QString db_name_; QString gpgconf_path_; QString database_path_; QMap<QString, QString> component_dirs_; @@ -250,6 +253,7 @@ class GpgContext::Impl { // set custom gpg key db path if (!args_.db_path.isEmpty()) { database_path_ = args_.db_path; + db_name_ = args_.db_name; } LOG_D() << "ctx set engine info, channel: " << parent_->GetChannel() @@ -445,4 +449,5 @@ auto GpgContext::ComponentDirectory(GpgComponentType type) const -> QString { return p_->ComponentDirectories(type); } +auto GpgContext::KeyDBName() const -> QString { return p_->KeyDBName(); } } // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgContext.h b/src/core/function/gpg/GpgContext.h index 4c683c0b..350c153e 100644 --- a/src/core/function/gpg/GpgContext.h +++ b/src/core/function/gpg/GpgContext.h @@ -71,6 +71,8 @@ class GPGFRONTEND_CORE_EXPORT GpgContext auto DefaultContext() -> gpgme_ctx_t; + [[nodiscard]] auto KeyDBName() const -> QString; + [[nodiscard]] auto HomeDirectory() const -> QString; [[nodiscard]] auto ComponentDirectory(GpgComponentType) const -> QString; diff --git a/src/core/function/gpg/GpgFileOpera.cpp b/src/core/function/gpg/GpgFileOpera.cpp index a3ad1ac5..334aae6f 100644 --- a/src/core/function/gpg/GpgFileOpera.cpp +++ b/src/core/function/gpg/GpgFileOpera.cpp @@ -66,10 +66,10 @@ void CreateArchiveHelper(const QString& in_path, GpgFileOpera::GpgFileOpera(int channel) : SingletonFunctionObject<GpgFileOpera>(channel) {} -auto EncryptFileGpgDataImpl(GpgContext& ctx_, const KeyArgsList& keys, +auto EncryptFileGpgDataImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys, GpgData& data_in, bool ascii, GpgData& data_out, const DataObjectPtr& data_object) -> GpgError { - auto recipients = Convert2RawGpgMEKeyList(keys); + auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys); auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); auto err = CheckGpgError( @@ -79,7 +79,7 @@ auto EncryptFileGpgDataImpl(GpgContext& ctx_, const KeyArgsList& keys, return err; } -auto EncryptFileImpl(GpgContext& ctx_, const KeyArgsList& keys, +auto EncryptFileImpl(GpgContext& ctx_, const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii, const QString& out_path, const DataObjectPtr& data_object) -> GpgError { @@ -90,8 +90,9 @@ auto EncryptFileImpl(GpgContext& ctx_, const KeyArgsList& keys, data_object); } -void GpgFileOpera::EncryptFile(const KeyArgsList& keys, const QString& in_path, - bool ascii, const QString& out_path, +void GpgFileOpera::EncryptFile(const GpgAbstractKeyPtrList& keys, + const QString& in_path, bool ascii, + const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( [=](const DataObjectPtr& data_object) { @@ -102,7 +103,7 @@ void GpgFileOpera::EncryptFile(const KeyArgsList& keys, const QString& in_path, } auto GpgFileOpera::EncryptFileSync( - const KeyArgsList& keys, const QString& in_path, bool ascii, + const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) { @@ -112,7 +113,7 @@ auto GpgFileOpera::EncryptFileSync( "gpgme_op_encrypt", "2.1.0"); } -void GpgFileOpera::EncryptDirectory(const KeyArgsList& keys, +void GpgFileOpera::EncryptDirectory(const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii, const QString& out_path, const GpgOperationCallback& cb) { @@ -186,8 +187,8 @@ void GpgFileOpera::DecryptArchive(const QString& in_path, } auto SignFileGpgDataImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, - const KeyArgsList& keys, GpgData& data_in, bool ascii, - GpgData& data_out, + const GpgAbstractKeyPtrList& keys, GpgData& data_in, + bool ascii, GpgData& data_out, const DataObjectPtr& data_object) -> GpgError { GpgError err; @@ -205,8 +206,8 @@ auto SignFileGpgDataImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, } auto SignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, - const KeyArgsList& keys, const QString& in_path, bool ascii, - const QString& out_path, + const GpgAbstractKeyPtrList& keys, const QString& in_path, + bool ascii, const QString& out_path, const DataObjectPtr& data_object) -> GpgError { GpgData data_in(in_path, true); GpgData data_out(out_path, false); @@ -215,8 +216,9 @@ auto SignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, data_object); } -void GpgFileOpera::SignFile(const KeyArgsList& keys, const QString& in_path, - bool ascii, const QString& out_path, +void GpgFileOpera::SignFile(const GpgAbstractKeyPtrList& keys, + const QString& in_path, bool ascii, + const QString& out_path, const GpgOperationCallback& cb) { RunGpgOperaAsync( [=](const DataObjectPtr& data_object) { @@ -226,9 +228,9 @@ void GpgFileOpera::SignFile(const KeyArgsList& keys, const QString& in_path, cb, "gpgme_op_sign", "2.1.0"); } -auto GpgFileOpera::SignFileSync(const KeyArgsList& keys, const QString& in_path, - bool ascii, const QString& out_path) - -> std::tuple<GpgError, DataObjectPtr> { +auto GpgFileOpera::SignFileSync( + const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii, + const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) { return SignFileImpl(ctx_, basic_opera_, keys, in_path, ascii, out_path, @@ -282,12 +284,12 @@ auto GpgFileOpera::VerifyFileSync(const QString& data_path, auto EncryptSignFileGpgDataImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, - const KeyArgsList& keys, - const KeyArgsList& signer_keys, + const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signer_keys, GpgData& data_in, bool ascii, GpgData& data_out, const DataObjectPtr& data_object) -> GpgError { GpgError err; - auto recipients = Convert2RawGpgMEKeyList(keys); + auto recipients = Convert2RawGpgMEKeyList(ctx_.GetChannel(), keys); basic_opera_.SetSigners(signer_keys, ascii); @@ -304,9 +306,10 @@ auto EncryptSignFileGpgDataImpl(GpgContext& ctx_, } auto EncryptSignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, - const KeyArgsList& keys, - const KeyArgsList& signer_keys, const QString& in_path, - bool ascii, const QString& out_path, + const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signer_keys, + const QString& in_path, bool ascii, + const QString& out_path, const DataObjectPtr& data_object) -> GpgError { GpgData data_in(in_path, true); GpgData data_out(out_path, false); @@ -315,8 +318,8 @@ auto EncryptSignFileImpl(GpgContext& ctx_, GpgBasicOperator& basic_opera_, data_in, ascii, data_out, data_object); } -void GpgFileOpera::EncryptSignFile(const KeyArgsList& keys, - const KeyArgsList& signer_keys, +void GpgFileOpera::EncryptSignFile(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signer_keys, const QString& in_path, bool ascii, const QString& out_path, const GpgOperationCallback& cb) { @@ -329,7 +332,7 @@ void GpgFileOpera::EncryptSignFile(const KeyArgsList& keys, } auto GpgFileOpera::EncryptSignFileSync( - const KeyArgsList& keys, const KeyArgsList& signer_keys, + const GpgAbstractKeyPtrList& keys, const GpgAbstractKeyPtrList& signer_keys, const QString& in_path, bool ascii, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( @@ -340,11 +343,10 @@ auto GpgFileOpera::EncryptSignFileSync( "gpgme_op_encrypt_sign", "2.1.0"); } -void GpgFileOpera::EncryptSignDirectory(const KeyArgsList& keys, - const KeyArgsList& signer_keys, - const QString& in_path, bool ascii, - const QString& out_path, - const GpgOperationCallback& cb) { +void GpgFileOpera::EncryptSignDirectory( + const GpgAbstractKeyPtrList& keys, const GpgAbstractKeyPtrList& signer_keys, + const QString& in_path, bool ascii, const QString& out_path, + const GpgOperationCallback& cb) { auto ex = CreateStandardGFDataExchanger(); RunGpgOperaAsync( diff --git a/src/core/function/gpg/GpgFileOpera.h b/src/core/function/gpg/GpgFileOpera.h index 5119bb36..4cbe70d2 100644 --- a/src/core/function/gpg/GpgFileOpera.h +++ b/src/core/function/gpg/GpgFileOpera.h @@ -61,8 +61,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param channel Channel in context * @return unsigned int error code */ - void EncryptFile(const KeyArgsList& keys, const QString& in_path, bool ascii, - const QString& out_path, const GpgOperationCallback& cb); + void EncryptFile(const GpgAbstractKeyPtrList& keys, const QString& in_path, + bool ascii, const QString& out_path, + const GpgOperationCallback& cb); /** * @brief @@ -73,9 +74,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param out_path * @return std::tuple<GpgError, DataObjectPtr> */ - auto EncryptFileSync(const KeyArgsList& keys, const QString& in_path, - bool ascii, const QString& out_path) - -> std::tuple<GpgError, DataObjectPtr>; + auto EncryptFileSync( + const GpgAbstractKeyPtrList& keys, const QString& in_path, bool ascii, + const QString& out_path) -> std::tuple<GpgError, DataObjectPtr>; /** * @brief @@ -86,8 +87,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param out_path * @param cb */ - void EncryptDirectory(const KeyArgsList& keys, const QString& in_path, - bool ascii, const QString& out_path, + void EncryptDirectory(const GpgAbstractKeyPtrList& keys, + const QString& in_path, bool ascii, + const QString& out_path, const GpgOperationCallback& cb); /** @@ -180,8 +182,9 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param channel * @return GpgError */ - void SignFile(const KeyArgsList& keys, const QString& in_path, bool ascii, - const QString& out_path, const GpgOperationCallback& cb); + void SignFile(const GpgAbstractKeyPtrList& keys, const QString& in_path, + bool ascii, const QString& out_path, + const GpgOperationCallback& cb); /** * @brief @@ -192,8 +195,8 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param out_path * @return std::tuple<GpgError, DataObjectPtr> */ - auto SignFileSync(const KeyArgsList& keys, const QString& in_path, bool ascii, - const QString& out_path) + auto SignFileSync(const GpgAbstractKeyPtrList& keys, const QString& in_path, + bool ascii, const QString& out_path) -> std::tuple<GpgError, DataObjectPtr>; /** @@ -228,7 +231,8 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param out_path * @param cb */ - void EncryptSignFile(const KeyArgsList& keys, const KeyArgsList& signer_keys, + void EncryptSignFile(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signer_keys, const QString& in_path, bool ascii, const QString& out_path, const GpgOperationCallback& cb); @@ -241,10 +245,11 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param ascii * @param out_path */ - auto EncryptSignFileSync( - const KeyArgsList& keys, const KeyArgsList& signer_keys, - const QString& in_path, bool ascii, - const QString& out_path) -> std::tuple<GpgError, DataObjectPtr>; + auto EncryptSignFileSync(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signer_keys, + const QString& in_path, bool ascii, + const QString& out_path) + -> std::tuple<GpgError, DataObjectPtr>; /** * @brief @@ -256,8 +261,8 @@ class GPGFRONTEND_CORE_EXPORT GpgFileOpera * @param out_path * @param cb */ - void EncryptSignDirectory(const KeyArgsList& keys, - const KeyArgsList& signer_keys, + void EncryptSignDirectory(const GpgAbstractKeyPtrList& keys, + const GpgAbstractKeyPtrList& signer_keys, const QString& in_path, bool ascii, const QString& out_path, const GpgOperationCallback& cb); diff --git a/src/core/function/gpg/GpgKeyGetter.cpp b/src/core/function/gpg/GpgKeyGetter.cpp index 14145f7f..86218a94 100644 --- a/src/core/function/gpg/GpgKeyGetter.cpp +++ b/src/core/function/gpg/GpgKeyGetter.cpp @@ -34,6 +34,7 @@ #include "core/GpgModel.h" #include "core/function/gpg/GpgContext.h" +#include "core/function/gpg/GpgKeyGroupGetter.h" #include "core/utils/GpgUtils.h" namespace GpgFrontend { @@ -70,7 +71,13 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { gpgme_get_key(ctx_.DefaultContext(), fpr.toUtf8(), &p_key, 0); if (p_key == nullptr) LOG_W() << "GpgKeyGetter GetKey _p_key Null, fpr: " << fpr; - return GpgKey(std::move(p_key)); + return GpgKey(p_key); + } + + auto GetPubkeyPtr(const QString& fpr, bool use_cache) -> GpgKeyPtr { + auto key = GetPubkey(fpr, use_cache); + if (!key.IsGood()) return nullptr; + return QSharedPointer<GpgKey>::create(key); } auto FetchKey() -> GpgKeyList { @@ -89,19 +96,20 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { return keys_list; } - auto FetchGpgKeyList() -> GpgKeyList { + auto FetchGpgKeyList() -> GpgAbstractKeyPtrList { if (keys_search_cache_.empty()) { FlushKeyCache(); } - auto keys_list = GpgKeyList{}; + auto keys_list = GpgAbstractKeyPtrList{}; { // get the lock std::lock_guard<std::mutex> lock(keys_cache_mutex_); for (const auto& key : keys_cache_) { - keys_list.push_back(key); + keys_list.push_back(QSharedPointer<GpgKey>::create(key)); } } + return keys_list; } @@ -163,9 +171,21 @@ class GpgKeyGetter::Impl : public SingletonFunctionObject<GpgKeyGetter::Impl> { return keys_copy; } - auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> { - return SecureCreateQSharedObject<GpgKeyTableModel>( - SingletonFunctionObject::GetChannel(), FetchGpgKeyList(), nullptr); + auto Fetch() -> QContainer<QSharedPointer<GpgKey>> { + auto keys = FetchKey(); + + auto ret = QContainer<QSharedPointer<GpgKey>>(); + for (const auto& key : keys) { + ret.append(QSharedPointer<GpgKey>::create(key)); + } + return ret; + } + + auto GetKeyPtr(const QString& key_id, + bool use_cache) -> QSharedPointer<GpgKey> { + auto key = GetKey(key_id, use_cache); + if (!key.IsGood()) return nullptr; + return QSharedPointer<GpgKey>::create(key); } private: @@ -229,10 +249,20 @@ auto GpgKeyGetter::GetKey(const QString& key_id, bool use_cache) -> GpgKey { return p_->GetKey(key_id, use_cache); } +auto GpgKeyGetter::GetKeyPtr(const QString& key_id, + bool use_cache) -> QSharedPointer<GpgKey> { + return p_->GetKeyPtr(key_id, use_cache); +} + auto GpgKeyGetter::GetPubkey(const QString& key_id, bool use_cache) -> GpgKey { return p_->GetPubkey(key_id, use_cache); } +auto GpgKeyGetter::GetPubkeyPtr(const QString& key_id, + bool use_cache) -> GpgKeyPtr { + return p_->GetPubkeyPtr(key_id, use_cache); +} + auto GpgKeyGetter::FlushKeyCache() -> bool { return p_->FlushKeyCache(); } auto GpgKeyGetter::GetKeys(const KeyIdArgsList& ids) -> GpgKeyList { @@ -245,8 +275,7 @@ auto GpgKeyGetter::GetKeysCopy(const GpgKeyList& keys) -> GpgKeyList { auto GpgKeyGetter::FetchKey() -> GpgKeyList { return p_->FetchKey(); } -auto GpgKeyGetter::GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel> { - return p_->GetGpgKeyTableModel(); +auto GpgKeyGetter::Fetch() -> QContainer<QSharedPointer<GpgKey>> { + return p_->Fetch(); } - } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgKeyGetter.h b/src/core/function/gpg/GpgKeyGetter.h index 2ed34531..b266bf17 100644 --- a/src/core/function/gpg/GpgKeyGetter.h +++ b/src/core/function/gpg/GpgKeyGetter.h @@ -63,12 +63,14 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter auto GetKey(const QString& key_id, bool use_cache = true) -> GpgKey; /** - * @brief Get the Keys object + * @brief Get the Key Ptr object * - * @param ids - * @return KeyListPtr + * @param key_id + * @param use_cache + * @return QSharedPointer<GpgKey> */ - auto GetKeys(const KeyIdArgsList& key_ids) -> GpgKeyList; + auto GetKeyPtr(const QString& key_id, + bool use_cache = true) -> QSharedPointer<GpgKey>; /** * @brief Get the Pubkey object @@ -79,6 +81,15 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter auto GetPubkey(const QString& key_id, bool use_cache = true) -> GpgKey; /** + * @brief Get the Pubkey Ptr object + * + * @param key_id + * @param use_cache + * @return GpgKeyPtr + */ + auto GetPubkeyPtr(const QString& key_id, bool use_cache = true) -> GpgKeyPtr; + + /** * @brief Get all the keys by receiving a linked list * * @return KeyLinkListPtr @@ -86,25 +97,33 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyGetter auto FetchKey() -> GpgKeyList; /** + * @brief + * + * @return QContainer<QSharedPointer<GpgKey>> + */ + auto Fetch() -> QContainer<QSharedPointer<GpgKey>>; + + /** * @brief flush the keys in the cache * */ auto FlushKeyCache() -> bool; /** - * @brief Get the Keys Copy object + * @brief Get the Keys object * - * @param keys + * @param ids * @return KeyListPtr */ - auto GetKeysCopy(const GpgKeyList& keys) -> GpgKeyList; + auto GetKeys(const KeyIdArgsList& key_ids) -> GpgKeyList; /** - * @brief + * @brief Get the Keys Copy object * - * @return GpgKeyTableModel + * @param keys + * @return KeyListPtr */ - auto GetGpgKeyTableModel() -> QSharedPointer<GpgKeyTableModel>; + auto GetKeysCopy(const GpgKeyList& keys) -> GpgKeyList; private: class Impl; diff --git a/src/core/function/gpg/GpgKeyGroupGetter.cpp b/src/core/function/gpg/GpgKeyGroupGetter.cpp new file mode 100644 index 00000000..47878414 --- /dev/null +++ b/src/core/function/gpg/GpgKeyGroupGetter.cpp @@ -0,0 +1,311 @@ +/** + * Copyright (C) 2021-2024 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GpgKeyGroupGetter.h" + +#include "core/function/CacheManager.h" +#include "core/function/gpg/GpgAbstractKeyGetter.h" +#include "core/struct/cache_object/KeyGroupsCO.h" +#include "utils/GpgUtils.h" + +namespace GpgFrontend { + +GpgKeyGroupGetter::GpgKeyGroupGetter(int channel) + : SingletonFunctionObject<GpgKeyGroupGetter>(channel) { + fetch_key_groups(); +} + +auto GpgKeyGroupGetter::Fetch() -> QContainer<QSharedPointer<GpgKeyGroup>> { + QContainer<QSharedPointer<GpgKeyGroup>> ret; + for (const auto& node : key_groups_forest_) { + ret.push_back(node->key_group); + } + return ret; +} + +void GpgKeyGroupGetter::Remove(const QString& id) { + if (id.isEmpty() || !key_groups_forest_.contains(id)) return; + + auto target_node = key_groups_forest_.value(id); + + for (const auto& node : key_groups_forest_) { + if (target_node == node) continue; + node->RemoveChildren(target_node.get()); + } + + key_groups_forest_.remove(id); + FlushCache(); +} + +void GpgKeyGroupGetter::fetch_key_groups() { + key_groups_forest_.clear(); + auto key = QString("kgs:%1").arg(ctx_.KeyDBName()); + auto json = cm_.LoadDurableCache(key); + + auto key_groups = KeyGroupsCO(json.object()); + if (key_groups.key_db_name != ctx_.KeyDBName()) return; + + for (const auto& key_group : key_groups.key_groups) { + if (key_group.id.isEmpty()) continue; + + LOG_D() << "load raw key group:" << key_group.id + << "key ids: " << key_group.key_ids; + + key_groups_forest_.insert( + key_group.id, + QSharedPointer<GpgKeyGroupTreeNode>::create(GpgKeyGroup{key_group})); + } + + build_gpg_key_group_tree(); + check_all_key_groups(); +} + +void GpgKeyGroupGetter::persist_key_groups() { + auto key = QString("kgs:%1").arg(ctx_.KeyDBName()); + + KeyGroupsCO key_groups; + key_groups.key_db_name = ctx_.KeyDBName(); + + for (const auto& node : key_groups_forest_) { + if (node->key_group == nullptr) continue; + LOG_D() << "persist key group: " << node->key_group->ID() + << "key ids:" << node->key_group->KeyIds(); + key_groups.key_groups.push_back(node->key_group->ToCacheObject()); + } + + cm_.SaveDurableCache(key, QJsonDocument{key_groups.ToJson()}, true); +} + +auto GpgKeyGroupGetter::KeyGroup(const QString& id) + -> QSharedPointer<GpgKeyGroup> { + if (!key_groups_forest_.contains(id)) return nullptr; + return key_groups_forest_.value(id)->key_group; +} + +void GpgKeyGroupGetter::check_key_group( + const QSharedPointer<GpgKeyGroup>& key_group) { + if (key_group == nullptr || key_group->IsDisabled()) return; + + for (const auto& key_id : key_group->KeyIds()) { + LOG_D() << "check" << key_id << "of" << key_group->UID(); + + if (IsKeyGroupID(key_id) || key_id == key_group->ID()) { + if (!key_groups_forest_.contains(key_id)) { + key_group->SetDisabled(true); + return; + } + + auto s_node = key_groups_forest_.value(key_id, nullptr); + check_key_group(s_node->key_group); + + if (s_node->key_group->IsDisabled()) { + key_group->SetDisabled(true); + return; + } + + } else { + auto key = GpgKeyGetter::GetInstance(GetChannel()).GetKeyPtr(key_id); + if (key == nullptr || !key->IsHasEncrCap()) { + key_group->SetDisabled(true); + return; + } + } + } +} + +void GpgKeyGroupGetter::check_all_key_groups() { + for (const auto& node : key_groups_forest_) { + node->key_group->SetDisabled(false); + } + + for (const auto& node : key_groups_forest_) { + auto key_group = node->key_group; + check_key_group(key_group); + + LOG_D() << "key group" << key_group->ID() << "ids: " << key_group->KeyIds() + << "status: " << key_group->IsDisabled(); + } +} + +auto GpgKeyGroupGetter::FlushCache() -> bool { + check_all_key_groups(); + persist_key_groups(); + return true; +} + +void GpgKeyGroupGetter::build_gpg_key_group_tree() { + for (const auto& node : key_groups_forest_) { + LOG_D() << "load key group: " << node->key_group->ID() + << "ids: " << node->key_group->KeyIds(); + for (const auto& key_id : node->key_group->KeyIds()) { + if (!IsKeyGroupID(key_id) || !key_groups_forest_.contains(key_id)) { + continue; + } + + auto target = key_groups_forest_.value(key_id); + if (!node->AddChildren(target.get())) { + LOG_E() << "found ring in key groups relations, key group:" + << node->key_group->ID() << "child: " << key_id; + continue; + } + } + node->Apply(); + } +} + +void GpgKeyGroupGetter::AddKeyGroup(const GpgKeyGroup& key_group) { + auto node = QSharedPointer<GpgKeyGroupTreeNode>::create(key_group); + + key_groups_forest_.insert(node->key_group->ID(), node); + LOG_D() << "add new key group" << key_group.ID() + << "key ids:" << key_group.KeyIds(); + + for (const auto& key_id : node->key_group->KeyIds()) { + if (!IsKeyGroupID(key_id) || !key_groups_forest_.contains(key_id)) continue; + + auto target = key_groups_forest_.value(key_id); + node->AddChildren(target.get()); + } + node->Apply(); + FlushCache(); +} + +auto GpgKeyGroupGetter::AddKey2KeyGroup(const QString& id, + const GpgAbstractKeyPtr& key) -> bool { + if (!key_groups_forest_.contains(id)) return false; + auto key_group = key_groups_forest_.value(id); + + if (key->KeyType() != GpgAbstractKeyType::kGPG_KEYGROUP) { + auto ret = key_group->AddNonKeyGroupKey(key); + FlushCache(); + return ret; + } + + if (!key_groups_forest_.contains(key->ID())) { + LOG_E() << "try adding invalid key group id:" << key->ID(); + return false; + } + + auto s_key_group = key_groups_forest_.value(key->ID()); + auto ret = key_group->AddChildren(s_key_group.get()); + FlushCache(); + return ret; +} + +auto GpgKeyGroupGetter::RemoveKeyFromKeyGroup(const QString& id, + const QString& key_id) -> bool { + if (!key_groups_forest_.contains(id)) return false; + auto key_group = key_groups_forest_.value(id); + + if (!IsKeyGroupID(key_id)) { + LOG_D() << "removing non key group id" << key_id << "form key group" << id; + key_group->RemoveNonKeyGroupKey(key_id); + FlushCache(); + return true; + } + + if (!key_groups_forest_.contains(key_id)) { + LOG_E() << "try remove invalid key group id:" << key_id; + return false; + } + + auto s_key_group = key_groups_forest_.value(key_id); + auto ret = key_group->RemoveChildren(s_key_group.get()); + FlushCache(); + return ret; +} + +GpgKeyGroupTreeNode::GpgKeyGroupTreeNode(GpgKeyGroup kg) + : key_group(QSharedPointer<GpgKeyGroup>::create(kg)) { + for (const auto& key_id : key_group->KeyIds()) { + if (!IsKeyGroupID(key_id)) { + non_key_group_ids.push_back(key_id); + } + } +} + +void GpgKeyGroupTreeNode::Apply() { + QStringList key_ids; + for (const auto& child : children) { + key_ids.push_back(child->key_group->ID()); + } + + for (const auto& key_id : non_key_group_ids) { + key_ids.push_back(key_id); + } + + key_group->SetKeyIds(key_ids); +} + +auto GpgKeyGroupTreeNode::AddNonKeyGroupKey(const GpgAbstractKeyPtr& key) + -> bool { + if (key->KeyType() == GpgAbstractKeyType::kGPG_KEYGROUP || + non_key_group_ids.contains(key->ID())) { + return false; + } + non_key_group_ids.push_back(key->ID()); + non_key_group_ids.removeDuplicates(); + Apply(); + return true; +} + +auto GpgKeyGroupTreeNode::HasAncestor(GpgKeyGroupTreeNode* target) -> bool { + for (const auto& parent : parents) { + if (parent == target || parent->HasAncestor(target)) { + return true; + } + } + return false; +} + +auto GpgKeyGroupTreeNode::AddChildren(GpgKeyGroupTreeNode* target) -> bool { + if (target == this || children.contains(target) || HasAncestor(target)) { + return false; + } + + children.push_back(target); + target->parents.push_back(this); + Apply(); + return true; +} + +auto GpgKeyGroupTreeNode::RemoveChildren(GpgKeyGroupTreeNode* target) -> bool { + if (!children.contains(target)) return false; + children.removeAll(target); + target->parents.removeAll(this); + Apply(); + return true; +} + +auto GpgKeyGroupTreeNode::RemoveNonKeyGroupKey(const QString& key) -> bool { + if (!non_key_group_ids.contains(key)) return false; + non_key_group_ids.removeAll(key); + Apply(); + return true; +} +} // namespace GpgFrontend
\ No newline at end of file diff --git a/src/core/function/gpg/GpgKeyGroupGetter.h b/src/core/function/gpg/GpgKeyGroupGetter.h new file mode 100644 index 00000000..9eabccde --- /dev/null +++ b/src/core/function/gpg/GpgKeyGroupGetter.h @@ -0,0 +1,215 @@ +/** + * Copyright (C) 2021-2024 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include "core/function/CacheManager.h" +#include "core/function/basic/GpgFunctionObject.h" +#include "core/function/gpg/GpgContext.h" +#include "core/model/GpgKeyGroup.h" + +namespace GpgFrontend { + +struct GpgKeyGroupTreeNode { + QContainer<GpgKeyGroupTreeNode*> parents; + QContainer<GpgKeyGroupTreeNode*> children; + QSharedPointer<GpgKeyGroup> key_group; + + // over take + QStringList non_key_group_ids; + + /** + * @brief Construct a new Gpg Key Group Tree Node object + * + */ + GpgKeyGroupTreeNode() = default; + + /** + * @brief Construct a new Gpg Key Group Tree Node object + * + * @param kg + */ + explicit GpgKeyGroupTreeNode(GpgKeyGroup kg); + + /** + * @brief + * + */ + void Apply(); + + /** + * @brief + * + * @param key + * @return true + * @return false + */ + auto AddNonKeyGroupKey(const GpgAbstractKeyPtr& key) -> bool; + + /** + * @brief + * + * @param target + * @return true + * @return false + */ + auto HasAncestor(GpgKeyGroupTreeNode* target) -> bool; + + /** + * @brief + * + * @param target + * @return true + * @return false + */ + auto AddChildren(GpgKeyGroupTreeNode* target) -> bool; + + /** + * @brief + * + * @param target + * @return true + * @return false + */ + auto RemoveChildren(GpgKeyGroupTreeNode* target) -> bool; + + /** + * @brief + * + * @param key + * @return true + * @return false + */ + auto RemoveNonKeyGroupKey(const QString& key) -> bool; +}; + +class GPGFRONTEND_CORE_EXPORT GpgKeyGroupGetter + : public SingletonFunctionObject<GpgKeyGroupGetter> { + public: + /** + * @brief GpgKeyGroupGetter constructor + * + * @param channel channel + */ + explicit GpgKeyGroupGetter( + int channel = SingletonFunctionObject::GetDefaultChannel()); + + /** + * @brief + * + * @return QContainer<GpgKeyGroup> + */ + auto Fetch() -> QContainer<QSharedPointer<GpgKeyGroup>>; + + /** + * @brief + * + * @return QContainer<GpgKeyGroup> + */ + auto FlushCache() -> bool; + + /** + * @brief + * + */ + void AddKeyGroup(const GpgKeyGroup&); + + /** + * @brief + * + * @param id + * @param key + * @return true + * @return false + */ + auto AddKey2KeyGroup(const QString& id, const GpgAbstractKeyPtr& key) -> bool; + + /** + * @brief + * + * @param id + * @param key + * @return true + * @return false + */ + auto RemoveKeyFromKeyGroup(const QString& id, const QString& key_id) -> bool; + + /** + * @brief + * + * @param id + */ + void Remove(const QString& id); + + /** + * @brief + * + * @param id + */ + auto KeyGroup(const QString& id) -> QSharedPointer<GpgKeyGroup>; + + private: + GpgContext& ctx_ = + GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); + CacheManager& cm_ = + CacheManager::GetInstance(SingletonFunctionObject::GetChannel()); + + QMap<QString, QSharedPointer<GpgKeyGroupTreeNode>> key_groups_forest_; + + /** + * @brief + * + */ + void fetch_key_groups(); + + /** + * @brief + * + */ + void persist_key_groups(); + + /** + * @brief + * + */ + void check_all_key_groups(); + + /** + * @brief + * + */ + void check_key_group(const QSharedPointer<GpgKeyGroup>&); + + /** + * @brief + * + */ + void build_gpg_key_group_tree(); +}; + +} // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgKeyImportExporter.cpp b/src/core/function/gpg/GpgKeyImportExporter.cpp index 60c06995..08e67748 100644 --- a/src/core/function/gpg/GpgKeyImportExporter.cpp +++ b/src/core/function/gpg/GpgKeyImportExporter.cpp @@ -72,21 +72,18 @@ auto GpgKeyImportExporter::ImportKey(const GFBuffer& in_buffer) * @param outBuffer output byte array * @return if success */ -auto GpgKeyImportExporter::ExportKey(const GpgKey& key, bool secret, bool ascii, - bool shortest, bool ssh_mode) const - -> std::tuple<GpgError, GFBuffer> { - if (!key.IsGood()) return {GPG_ERR_CANCELED, {}}; +auto GpgKeyImportExporter::ExportKey( + const GpgAbstractKeyPtr& key, bool secret, bool ascii, bool shortest, + bool ssh_mode) const -> std::tuple<GpgError, GFBuffer> { + if (key == nullptr) return {GPG_ERR_CANCELED, {}}; int mode = 0; if (secret) mode |= GPGME_EXPORT_MODE_SECRET; if (shortest) mode |= GPGME_EXPORT_MODE_MINIMAL; if (ssh_mode) mode |= GPGME_EXPORT_MODE_SSH; - QContainer<gpgme_key_t> keys_array; - - // Last entry data_in array has to be nullptr - keys_array.push_back(static_cast<gpgme_key_t>(key)); - keys_array.push_back(nullptr); + QContainer<gpgme_key_t> keys_array = + Convert2RawGpgMEKeyList(GetChannel(), {key}); GpgData data_out; auto* ctx = ascii ? ctx_.DefaultContext() : ctx_.BinaryContext(); @@ -102,8 +99,9 @@ auto GpgKeyImportExporter::ExportKey(const GpgKey& key, bool secret, bool ascii, * @param outBuffer output byte array * @return if success */ -void GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys, bool secret, - bool ascii, bool shortest, bool ssh_mode, +void GpgKeyImportExporter::ExportKeys(const GpgAbstractKeyPtrList& keys, + bool secret, bool ascii, bool shortest, + bool ssh_mode, const GpgOperationCallback& cb) const { RunGpgOperaAsync( [=](const DataObjectPtr& data_object) -> GpgError { @@ -114,7 +112,7 @@ void GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys, bool secret, if (shortest) mode |= GPGME_EXPORT_MODE_MINIMAL; if (ssh_mode) mode |= GPGME_EXPORT_MODE_SSH; - QContainer<gpgme_key_t> keys_array(keys.begin(), keys.end()); + auto keys_array = Convert2RawGpgMEKeyList(GetChannel(), keys); // Last entry data_in array has to be nullptr keys_array.push_back(nullptr); @@ -136,15 +134,15 @@ void GpgKeyImportExporter::ExportKeys(const KeyArgsList& keys, bool secret, * @param outBuffer output byte array * @return if success */ -void GpgKeyImportExporter::ExportAllKeys(const KeyArgsList& keys, bool secret, - bool ascii, +void GpgKeyImportExporter::ExportAllKeys(const GpgAbstractKeyPtrList& keys, + bool secret, bool ascii, const GpgOperationCallback& cb) const { RunGpgOperaAsync( [=](const DataObjectPtr& data_object) -> GpgError { if (keys.empty()) return GPG_ERR_CANCELED; int mode = 0; - QContainer<gpgme_key_t> keys_array(keys.begin(), keys.end()); + auto keys_array = Convert2RawGpgMEKeyList(GetChannel(), keys); // Last entry data_in array has to be nullptr keys_array.push_back(nullptr); diff --git a/src/core/function/gpg/GpgKeyImportExporter.h b/src/core/function/gpg/GpgKeyImportExporter.h index cc7b3f6f..4f938cb7 100644 --- a/src/core/function/gpg/GpgKeyImportExporter.h +++ b/src/core/function/gpg/GpgKeyImportExporter.h @@ -68,9 +68,9 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyImportExporter * @param ascii * @return std::tuple<GpgError, GFBuffer> */ - [[nodiscard]] auto ExportKey(const GpgKey& key, bool secret, bool ascii, - bool shortest, bool ssh_mode = false) const - -> std::tuple<GpgError, GFBuffer>; + [[nodiscard]] auto ExportKey( + const GpgAbstractKeyPtr& key, bool secret, bool ascii, bool shortest, + bool ssh_mode = false) const -> std::tuple<GpgError, GFBuffer>; /** * @brief @@ -91,7 +91,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyImportExporter * @return true * @return false */ - void ExportKeys(const KeyArgsList& keys, bool secret, bool ascii, + void ExportKeys(const GpgAbstractKeyPtrList& keys, bool secret, bool ascii, bool shortest, bool ssh_mode, const GpgOperationCallback& cb) const; @@ -103,7 +103,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyImportExporter * @param ascii * @param cb */ - void ExportAllKeys(const KeyArgsList& keys, bool secret, bool ascii, + void ExportAllKeys(const GpgAbstractKeyPtrList& keys, bool secret, bool ascii, const GpgOperationCallback& cb) const; private: diff --git a/src/core/function/gpg/GpgKeyManager.cpp b/src/core/function/gpg/GpgKeyManager.cpp index bd514cf3..a2c53975 100644 --- a/src/core/function/gpg/GpgKeyManager.cpp +++ b/src/core/function/gpg/GpgKeyManager.cpp @@ -39,7 +39,8 @@ namespace GpgFrontend { GpgKeyManager::GpgKeyManager(int channel) : SingletonFunctionObject<GpgKeyManager>(channel) {} -auto GpgKeyManager::SignKey(const GpgKey& target, KeyArgsList& keys, +auto GpgKeyManager::SignKey(const GpgKeyPtr& key, + const GpgAbstractKeyPtrList& keys, const QString& uid, const std::unique_ptr<QDateTime>& expires) -> bool { GpgBasicOperator::GetInstance(GetChannel()).SetSigners(keys, true); @@ -54,13 +55,13 @@ auto GpgKeyManager::SignKey(const GpgKey& target, KeyArgsList& keys, } auto err = CheckGpgError( - gpgme_op_keysign(ctx_.DefaultContext(), static_cast<gpgme_key_t>(target), + gpgme_op_keysign(ctx_.DefaultContext(), static_cast<gpgme_key_t>(*key), uid.toUtf8(), expires_time_t, flags)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } -auto GpgKeyManager::RevSign(const GpgKey& key, +auto GpgKeyManager::RevSign(const GpgKeyPtr& key, const SignIdArgsList& signature_id) -> bool { auto& key_getter = GpgKeyGetter::GetInstance(GetChannel()); @@ -69,14 +70,14 @@ auto GpgKeyManager::RevSign(const GpgKey& key, assert(signing_key.IsGood()); auto err = CheckGpgError( - gpgme_op_revsig(ctx_.DefaultContext(), gpgme_key_t(key), + gpgme_op_revsig(ctx_.DefaultContext(), gpgme_key_t(*key), gpgme_key_t(signing_key), sign_id.second.toUtf8(), 0)); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) return false; } return true; } -auto GpgKeyManager::SetExpire(const GpgKey& key, +auto GpgKeyManager::SetExpire(const GpgKeyPtr& key, std::unique_ptr<GpgSubKey>& subkey, std::unique_ptr<QDateTime>& expires) -> bool { unsigned long expires_time = 0; @@ -88,13 +89,13 @@ auto GpgKeyManager::SetExpire(const GpgKey& key, if (subkey != nullptr) sub_fprs = subkey->Fingerprint().toUtf8(); auto err = CheckGpgError(gpgme_op_setexpire(ctx_.DefaultContext(), - static_cast<gpgme_key_t>(key), + static_cast<gpgme_key_t>(*key), expires_time, sub_fprs, 0)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } -auto GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key, +auto GpgKeyManager::SetOwnerTrustLevel(const GpgKeyPtr& key, int trust_level) -> bool { if (trust_level < 1 || trust_level > 5) { FLOG_W("illegal owner trust level: %d", trust_level); @@ -172,9 +173,10 @@ auto GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key, .DoInteract(key, next_state_handler, action_handler); } -auto GpgKeyManager::DeleteSubkey(const GpgKey& key, int subkey_index) -> bool { +auto GpgKeyManager::DeleteSubkey(const GpgKeyPtr& key, + int subkey_index) -> bool { if (subkey_index < 0 || - subkey_index >= static_cast<int>(key.SubKeys().size())) { + subkey_index >= static_cast<int>(key->SubKeys().size())) { LOG_W() << "illegal subkey index: " << subkey_index; return false; } @@ -246,7 +248,7 @@ auto GpgKeyManager::DeleteSubkey(const GpgKey& key, int subkey_index) -> bool { return QString(""); }; - auto key_fpr = key.Fingerprint(); + auto key_fpr = key->Fingerprint(); AutomatonHandelStruct handel_struct(key_fpr); handel_struct.SetHandler(next_state_handler, action_handler); @@ -256,11 +258,11 @@ auto GpgKeyManager::DeleteSubkey(const GpgKey& key, int subkey_index) -> bool { .DoInteract(key, next_state_handler, action_handler); } -auto GpgKeyManager::RevokeSubkey(const GpgKey& key, int subkey_index, +auto GpgKeyManager::RevokeSubkey(const GpgKeyPtr& key, int subkey_index, int reason_code, const QString& reason_text) -> bool { if (subkey_index < 0 || - subkey_index >= static_cast<int>(key.SubKeys().size())) { + subkey_index >= static_cast<int>(key->SubKeys().size())) { LOG_W() << "illegal subkey index: " << subkey_index; return false; } @@ -369,7 +371,7 @@ auto GpgKeyManager::RevokeSubkey(const GpgKey& key, int subkey_index, return QString(""); }; - auto key_fpr = key.Fingerprint(); + auto key_fpr = key->Fingerprint(); AutomatonHandelStruct handel_struct(key_fpr); handel_struct.SetHandler(next_state_handler, action_handler); diff --git a/src/core/function/gpg/GpgKeyManager.h b/src/core/function/gpg/GpgKeyManager.h index 817179e1..ccf69b53 100644 --- a/src/core/function/gpg/GpgKeyManager.h +++ b/src/core/function/gpg/GpgKeyManager.h @@ -51,12 +51,13 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager /** * @brief Sign a key pair(actually a certain uid) - * @param target target key pair + * @param key target key pair * @param uid target * @param expires expire date and time of the signature * @return if successful */ - auto SignKey(const GpgKey& target, KeyArgsList& keys, const QString& uid, + auto SignKey(const GpgKeyPtr& key, const GpgAbstractKeyPtrList& keys, + const QString& uid, const std::unique_ptr<QDateTime>& expires) -> bool; /** @@ -67,8 +68,8 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager * @return true * @return false */ - auto RevSign(const GpgFrontend::GpgKey& key, - const GpgFrontend::SignIdArgsList& signature_id) -> bool; + auto RevSign(const GpgKeyPtr& key, + const SignIdArgsList& signature_id) -> bool; /** * @brief Set the Expire object @@ -79,7 +80,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager * @return true * @return false */ - auto SetExpire(const GpgKey& key, std::unique_ptr<GpgSubKey>& subkey, + auto SetExpire(const GpgKeyPtr& key, std::unique_ptr<GpgSubKey>& subkey, std::unique_ptr<QDateTime>& expires) -> bool; /** @@ -87,7 +88,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager * * @return */ - auto SetOwnerTrustLevel(const GpgKey& key, int trust_level) -> bool; + auto SetOwnerTrustLevel(const GpgKeyPtr& key, int trust_level) -> bool; /** * @brief @@ -97,7 +98,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager * @return true * @return false */ - auto DeleteSubkey(const GpgKey& key, int subkey_index) -> bool; + auto DeleteSubkey(const GpgKeyPtr& key, int subkey_index) -> bool; /** * @brief @@ -107,7 +108,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager * @return true * @return false */ - auto RevokeSubkey(const GpgKey& key, int subkey_index, int reason_code, + auto RevokeSubkey(const GpgKeyPtr& key, int subkey_index, int reason_code, const QString& reason_text) -> bool; private: diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp index 3d9b8eda..3e4fe6d4 100644 --- a/src/core/function/gpg/GpgKeyOpera.cpp +++ b/src/core/function/gpg/GpgKeyOpera.cpp @@ -28,9 +28,8 @@ #include "GpgKeyOpera.h" -#include "core/GpgModel.h" #include "core/function/gpg/GpgCommandExecutor.h" -#include "core/function/gpg/GpgKeyGetter.h" +#include "core/function/gpg/GpgKeyGroupGetter.h" #include "core/model/DataObject.h" #include "core/model/GpgGenerateKeyResult.h" #include "core/model/GpgKeyGenerateInfo.h" @@ -49,17 +48,21 @@ GpgKeyOpera::GpgKeyOpera(int channel) * Delete keys * @param uidList key ids */ -void GpgKeyOpera::DeleteKeys(KeyIdArgsList key_ids) { +void GpgKeyOpera::DeleteKeys(const GpgAbstractKeyPtrList& keys) { GpgError err; - for (const auto& tmp : key_ids) { - auto key = GpgKeyGetter::GetInstance(GetChannel()).GetKey(tmp); - if (key.IsGood()) { + for (const auto& key : keys) { + if (key->KeyType() == GpgAbstractKeyType::kGPG_KEY && key->IsGood()) { + auto k = qSharedPointerDynamicCast<GpgKey>(key); err = CheckGpgError(gpgme_op_delete_ext( - ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), + ctx_.DefaultContext(), static_cast<gpgme_key_t>(*k), GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE)); assert(gpg_err_code(err) == GPG_ERR_NO_ERROR); } else { - LOG_W() << "GpgKeyOpera DeleteKeys get key failed: " << tmp; + LOG_W() << "GpgKeyOpera DeleteKeys get key failed: " << key->ID(); + } + + if (key->KeyType() == GpgAbstractKeyType::kGPG_KEYGROUP) { + GpgKeyGroupGetter::GetInstance(GetChannel()).Remove(key->ID()); } } } @@ -72,7 +75,7 @@ void GpgKeyOpera::DeleteKeys(KeyIdArgsList key_ids) { * @param expires date and time * @return if successful */ -auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr, +auto GpgKeyOpera::SetExpire(const GpgKeyPtr& key, const SubkeyId& subkey_fpr, std::unique_ptr<QDateTime>& expires) -> GpgError { unsigned long expires_time = 0; @@ -81,15 +84,15 @@ auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr, } GpgError err; - if (key.Fingerprint() == subkey_fpr || subkey_fpr.isEmpty()) { - err = - gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), - expires_time, nullptr, 0); + if (key->Fingerprint() == subkey_fpr || subkey_fpr.isEmpty()) { + err = gpgme_op_setexpire(ctx_.DefaultContext(), + static_cast<gpgme_key_t>(*key), expires_time, + nullptr, 0); assert(gpg_err_code(err) == GPG_ERR_NO_ERROR); } else { - err = - gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), - expires_time, subkey_fpr.toUtf8(), 0); + err = gpgme_op_setexpire(ctx_.DefaultContext(), + static_cast<gpgme_key_t>(*key), expires_time, + subkey_fpr.toUtf8(), 0); assert(gpg_err_code(err) == GPG_ERR_NO_ERROR); } @@ -102,7 +105,7 @@ auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr, * @param outputFileName out file name(path) * @return the process doing this job */ -void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key, +void GpgKeyOpera::GenerateRevokeCert(const GpgKeyPtr& key, const QString& output_path, int revocation_reason_code, const QString& revocation_reason_text) { @@ -119,7 +122,7 @@ void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key, GpgCommandExecutor::ExecuteSync( {app_path, QStringList{"--command-fd", "0", "--status-fd", "1", "--no-tty", "-o", - output_path, "--gen-revoke", key.Fingerprint()}, + output_path, "--gen-revoke", key->Fingerprint()}, [=](int exit_code, const QString& p_out, const QString& p_err) { if (exit_code != 0) { LOG_W() << "gnupg gen revoke execute error, process stderr: " @@ -226,7 +229,7 @@ auto GpgKeyOpera::GenerateKeySync(const QSharedPointer<KeyGenerateInfo>& params) "gpgme_op_createkey", "2.1.0"); } -auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKey& key, +auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params, const DataObjectPtr& data_object) -> GpgError { if (params == nullptr || params->GetAlgo() == KeyGenerateInfo::kNoneAlgo || @@ -246,11 +249,12 @@ auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKey& key, if (params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - LOG_D() << "subkey generation args: " << key.ID() << algo << expires << flags; + LOG_D() << "subkey generation args: " << key->ID() << algo << expires + << flags; - auto err = - gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key), - algo.toLatin1(), 0, expires, flags); + auto err = gpgme_op_createsubkey(ctx.DefaultContext(), + static_cast<gpgme_key_t>(*key), + algo.toLatin1(), 0, expires, flags); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { data_object->Swap({GpgGenerateKeyResult{}}); return err; @@ -261,7 +265,7 @@ auto GenerateSubKeyImpl(GpgContext& ctx, const GpgKey& key, return CheckGpgError(err); } -void GpgKeyOpera::GenerateSubkey(const GpgKey& key, +void GpgKeyOpera::GenerateSubkey(const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params, const GpgOperationCallback& callback) { RunGpgOperaAsync( @@ -272,7 +276,7 @@ void GpgKeyOpera::GenerateSubkey(const GpgKey& key, } auto GpgKeyOpera::GenerateSubkeySync( - const GpgKey& key, const QSharedPointer<KeyGenerateInfo>& params) + const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) -> GpgError { @@ -291,8 +295,8 @@ auto GenerateKeyWithSubkeyImpl(GpgContext& ctx, GpgKeyGetter& key_getter, if (!data_object->Check<GpgGenerateKeyResult>()) return GPG_ERR_CANCELED; auto result = ExtractParams<GpgGenerateKeyResult>(data_object, 0); - auto key = key_getter.GetKey(result.GetFingerprint()); - if (!key.IsGood()) { + auto key = key_getter.GetKeyPtr(result.GetFingerprint()); + if (key == nullptr) { LOG_W() << "cannot get key which has been generated, fpr: " << result.GetFingerprint(); return GPG_ERR_CANCELED; @@ -332,18 +336,18 @@ auto GpgKeyOpera::GenerateKeyWithSubkeySync( "gpgme_op_createkey&gpgme_op_createsubkey", "2.1.0"); } -void GpgKeyOpera::ModifyPassword(const GpgKey& key, +void GpgKeyOpera::ModifyPassword(const GpgKeyPtr& key, const GpgOperationCallback& callback) { RunGpgOperaAsync( [&key, &ctx = ctx_](const DataObjectPtr&) -> GpgError { return gpgme_op_passwd(ctx.DefaultContext(), - static_cast<gpgme_key_t>(key), 0); + static_cast<gpgme_key_t>(*key), 0); }, callback, "gpgme_op_passwd", "2.0.15"); } auto GpgKeyOpera::ModifyTOFUPolicy( - const GpgKey& key, gpgme_tofu_policy_t tofu_policy) -> GpgError { + const GpgKeyPtr& key, gpgme_tofu_policy_t tofu_policy) -> GpgError { const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>( "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"}); LOG_D() << "got gnupg version from rt: " << gnupg_version; @@ -354,26 +358,22 @@ auto GpgKeyOpera::ModifyTOFUPolicy( } auto err = gpgme_op_tofu_policy(ctx_.DefaultContext(), - static_cast<gpgme_key_t>(key), tofu_policy); + static_cast<gpgme_key_t>(*key), tofu_policy); return CheckGpgError(err); } -void GpgKeyOpera::DeleteKey(const KeyId& key_id) { - auto keys = KeyIdArgsList{}; - keys.push_back(key_id); - DeleteKeys(keys); -} +void GpgKeyOpera::DeleteKey(const GpgAbstractKeyPtr& key) { DeleteKeys({key}); } -auto AddADSKImpl(GpgContext& ctx, const GpgKey& key, const GpgSubKey& adsk, +auto AddADSKImpl(GpgContext& ctx, const GpgKeyPtr& key, const GpgSubKey& adsk, const DataObjectPtr& data_object) -> GpgError { auto algo = adsk.Fingerprint(); unsigned int flags = GPGME_CREATE_ADSK; - LOG_D() << "add adsk args: " << key.ID() << algo; + LOG_D() << "add adsk args: " << key->ID() << algo; - auto err = - gpgme_op_createsubkey(ctx.DefaultContext(), static_cast<gpgme_key_t>(key), - algo.toLatin1(), 0, 0, flags); + auto err = gpgme_op_createsubkey(ctx.DefaultContext(), + static_cast<gpgme_key_t>(*key), + algo.toLatin1(), 0, 0, flags); if (CheckGpgError(err) != GPG_ERR_NO_ERROR) { data_object->Swap({GpgGenerateKeyResult{}}); return err; @@ -384,7 +384,7 @@ auto AddADSKImpl(GpgContext& ctx, const GpgKey& key, const GpgSubKey& adsk, return CheckGpgError(err); } -void GpgKeyOpera::AddADSK(const GpgKey& key, const GpgSubKey& adsk, +void GpgKeyOpera::AddADSK(const GpgKeyPtr& key, const GpgSubKey& adsk, const GpgOperationCallback& callback) { RunGpgOperaAsync( [=](const DataObjectPtr& data_object) -> GpgError { @@ -393,7 +393,7 @@ void GpgKeyOpera::AddADSK(const GpgKey& key, const GpgSubKey& adsk, callback, "gpgme_op_createsubkey", "2.4.1"); } -auto GpgKeyOpera::AddADSKSync(const GpgKey& key, const GpgSubKey& adsk) +auto GpgKeyOpera::AddADSKSync(const GpgKeyPtr& key, const GpgSubKey& adsk) -> std::tuple<GpgError, DataObjectPtr> { return RunGpgOperaSync( [=](const DataObjectPtr& data_object) -> GpgError { diff --git a/src/core/function/gpg/GpgKeyOpera.h b/src/core/function/gpg/GpgKeyOpera.h index 4728992d..0b91f88a 100644 --- a/src/core/function/gpg/GpgKeyOpera.h +++ b/src/core/function/gpg/GpgKeyOpera.h @@ -61,14 +61,14 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * * @param key_ids */ - void DeleteKeys(KeyIdArgsList key_ids); + void DeleteKeys(const GpgAbstractKeyPtrList& keys); /** * @brief * * @param key_id */ - void DeleteKey(const KeyId& key_id); + void DeleteKey(const GpgAbstractKeyPtr& key_id); /** * @brief Set the Expire object @@ -78,7 +78,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param expires * @return GpgError */ - auto SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr, + auto SetExpire(const GpgKeyPtr& key, const SubkeyId& subkey_fpr, std::unique_ptr<QDateTime>& expires) -> GpgError; /** @@ -87,7 +87,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param key * @param output_file_name */ - void GenerateRevokeCert(const GpgKey& key, const QString& output_path, + void GenerateRevokeCert(const GpgKeyPtr& key, const QString& output_path, int revocation_reason_code, const QString& revocation_reason_text); @@ -97,7 +97,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param key * @return GpgFrontend::GpgError */ - void ModifyPassword(const GpgKey& key, const GpgOperationCallback&); + void ModifyPassword(const GpgKeyPtr& key, const GpgOperationCallback&); /** * @brief @@ -106,8 +106,8 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param tofu_policy * @return GpgFrontend::GpgError */ - auto ModifyTOFUPolicy(const GpgKey& key, gpgme_tofu_policy_t tofu_policy) - -> GpgFrontend::GpgError; + auto ModifyTOFUPolicy(const GpgKeyPtr& key, + gpgme_tofu_policy_t tofu_policy) -> GpgError; /** * @brief * @@ -133,7 +133,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param params * @return GpgFrontend::GpgError */ - void GenerateSubkey(const GpgKey& key, + void GenerateSubkey(const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params, const GpgOperationCallback&); @@ -143,7 +143,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param key * @param params */ - auto GenerateSubkeySync(const GpgKey& key, + auto GenerateSubkeySync(const GpgKeyPtr& key, const QSharedPointer<KeyGenerateInfo>& params) -> std::tuple<GpgError, DataObjectPtr>; @@ -176,7 +176,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param key * @param adsk */ - void AddADSK(const GpgKey& key, const GpgSubKey& adsk, + void AddADSK(const GpgKeyPtr& key, const GpgSubKey& adsk, const GpgOperationCallback&); /** @@ -186,7 +186,7 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyOpera * @param adsk * @return GpgError */ - auto AddADSKSync(const GpgKey& key, const GpgSubKey& adsk) + auto AddADSKSync(const GpgKeyPtr& key, const GpgSubKey& adsk) -> std::tuple<GpgError, DataObjectPtr>; private: diff --git a/src/core/function/gpg/GpgUIDOperator.cpp b/src/core/function/gpg/GpgUIDOperator.cpp index f3e4fcc2..a951fa6f 100644 --- a/src/core/function/gpg/GpgUIDOperator.cpp +++ b/src/core/function/gpg/GpgUIDOperator.cpp @@ -37,29 +37,29 @@ namespace GpgFrontend { GpgUIDOperator::GpgUIDOperator(int channel) : SingletonFunctionObject<GpgUIDOperator>(channel) {} -auto GpgUIDOperator::AddUID(const GpgKey& key, const QString& uid) -> bool { +auto GpgUIDOperator::AddUID(const GpgKeyPtr& key, const QString& uid) -> bool { auto err = gpgme_op_adduid(ctx_.DefaultContext(), - static_cast<gpgme_key_t>(key), uid.toUtf8(), 0); + static_cast<gpgme_key_t>(*key), uid.toUtf8(), 0); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } -auto GpgUIDOperator::SetPrimaryUID(const GpgKey& key, +auto GpgUIDOperator::SetPrimaryUID(const GpgKeyPtr& key, const QString& uid) -> bool { auto err = CheckGpgError(gpgme_op_set_uid_flag( - ctx_.DefaultContext(), static_cast<gpgme_key_t>(key), uid.toUtf8(), + ctx_.DefaultContext(), static_cast<gpgme_key_t>(*key), uid.toUtf8(), "primary", nullptr)); return CheckGpgError(err) == GPG_ERR_NO_ERROR; } -auto GpgUIDOperator::AddUID(const GpgKey& key, const QString& name, +auto GpgUIDOperator::AddUID(const GpgKeyPtr& key, const QString& name, const QString& comment, const QString& email) -> bool { LOG_D() << "new uuid:" << name << comment << email; return AddUID(key, QString("%1(%2)<%3>").arg(name).arg(comment).arg(email)); } -auto GpgUIDOperator::DeleteUID(const GpgKey& key, int uid_index) -> bool { - if (uid_index < 2 || uid_index > static_cast<int>(key.UIDs().size())) { +auto GpgUIDOperator::DeleteUID(const GpgKeyPtr& key, int uid_index) -> bool { + if (uid_index < 2 || uid_index > static_cast<int>(key->UIDs().size())) { LOG_W() << "illegal uid_index index: " << uid_index; return false; } @@ -131,7 +131,7 @@ auto GpgUIDOperator::DeleteUID(const GpgKey& key, int uid_index) -> bool { return QString(""); }; - auto key_fpr = key.Fingerprint(); + auto key_fpr = key->Fingerprint(); AutomatonHandelStruct handel_struct(key_fpr); handel_struct.SetHandler(next_state_handler, action_handler); @@ -141,10 +141,10 @@ auto GpgUIDOperator::DeleteUID(const GpgKey& key, int uid_index) -> bool { .DoInteract(key, next_state_handler, action_handler); } -auto GpgUIDOperator::RevokeUID(const GpgKey& key, int uid_index, +auto GpgUIDOperator::RevokeUID(const GpgKeyPtr& key, int uid_index, int reason_code, const QString& reason_text) -> bool { - if (uid_index < 2 || uid_index > static_cast<int>(key.UIDs().size())) { + if (uid_index < 2 || uid_index > static_cast<int>(key->UIDs().size())) { LOG_W() << "illegal uid index: " << uid_index; return false; } @@ -253,7 +253,7 @@ auto GpgUIDOperator::RevokeUID(const GpgKey& key, int uid_index, return QString(""); }; - auto key_fpr = key.Fingerprint(); + auto key_fpr = key->Fingerprint(); AutomatonHandelStruct handel_struct(key_fpr); handel_struct.SetHandler(next_state_handler, action_handler); diff --git a/src/core/function/gpg/GpgUIDOperator.h b/src/core/function/gpg/GpgUIDOperator.h index f0e925ed..e5e2f190 100644 --- a/src/core/function/gpg/GpgUIDOperator.h +++ b/src/core/function/gpg/GpgUIDOperator.h @@ -53,7 +53,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator * @param uid uid args(combine name&comment&email) * @return if successful */ - auto AddUID(const GpgKey& key, const QString& uid) -> bool; + auto AddUID(const GpgKeyPtr& key, const QString& uid) -> bool; /** * create a new uid in certain key pair @@ -63,7 +63,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator * @param email * @return */ - auto AddUID(const GpgKey& key, const QString& name, const QString& comment, + auto AddUID(const GpgKeyPtr& key, const QString& name, const QString& comment, const QString& email) -> bool; /** @@ -74,7 +74,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator * @return true * @return false */ - auto DeleteUID(const GpgKey& key, int uid_index) -> bool; + auto DeleteUID(const GpgKeyPtr& key, int uid_index) -> bool; /** * @brief @@ -86,7 +86,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator * @return true * @return false */ - auto RevokeUID(const GpgKey& key, int uid_index, int reason_code, + auto RevokeUID(const GpgKeyPtr& key, int uid_index, int reason_code, const QString& reason_text) -> bool; /** @@ -95,7 +95,7 @@ class GPGFRONTEND_CORE_EXPORT GpgUIDOperator * @param uid target uid * @return if successful */ - auto SetPrimaryUID(const GpgKey& key, const QString& uid) -> bool; + auto SetPrimaryUID(const GpgKeyPtr& key, const QString& uid) -> bool; private: GpgContext& ctx_ = |