aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/function/gpg/GpgKeyOpera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/function/gpg/GpgKeyOpera.cpp')
-rw-r--r--src/core/function/gpg/GpgKeyOpera.cpp439
1 files changed, 253 insertions, 186 deletions
diff --git a/src/core/function/gpg/GpgKeyOpera.cpp b/src/core/function/gpg/GpgKeyOpera.cpp
index d5919cff..d9133905 100644
--- a/src/core/function/gpg/GpgKeyOpera.cpp
+++ b/src/core/function/gpg/GpgKeyOpera.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2021 Saturneric
+ * Copyright (C) 2021 Saturneric <[email protected]>
*
* This file is part of GpgFrontend.
*
@@ -20,7 +20,7 @@
* 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.
+ * Saturneric <[email protected]> starting on May 12, 2021.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
@@ -28,38 +28,42 @@
#include "GpgKeyOpera.h"
-#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>
-#include <vector>
+#include <gpg-error.h>
-#include "GpgCommandExecutor.h"
-#include "GpgKeyGetter.h"
-#include "core/GpgConstants.h"
-#include "core/GpgGenKeyInfo.h"
+#include <memory>
-GpgFrontend::GpgKeyOpera::GpgKeyOpera(int channel)
+#include "core/GpgModel.h"
+#include "core/function/gpg/GpgCommandExecutor.h"
+#include "core/function/gpg/GpgKeyGetter.h"
+#include "core/model/DataObject.h"
+#include "core/model/GpgGenKeyInfo.h"
+#include "core/model/GpgGenerateKeyResult.h"
+#include "core/module/ModuleManager.h"
+#include "core/typedef/GpgTypedef.h"
+#include "core/utils/AsyncUtils.h"
+#include "core/utils/CommonUtils.h"
+#include "core/utils/GpgUtils.h"
+
+namespace GpgFrontend {
+
+GpgKeyOpera::GpgKeyOpera(int channel)
: SingletonFunctionObject<GpgKeyOpera>(channel) {}
/**
* Delete keys
* @param uidList key ids
*/
-void GpgFrontend::GpgKeyOpera::DeleteKeys(
- GpgFrontend::KeyIdArgsListPtr key_ids) {
+void GpgKeyOpera::DeleteKeys(GpgFrontend::KeyIdArgsListPtr key_ids) {
GpgError err;
for (const auto& tmp : *key_ids) {
auto key = GpgKeyGetter::GetInstance().GetKey(tmp);
if (key.IsGood()) {
- err = check_gpg_error(
- gpgme_op_delete_ext(ctx_, gpgme_key_t(key),
- GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE));
+ err = CheckGpgError(gpgme_op_delete_ext(
+ ctx_.DefaultContext(), static_cast<gpgme_key_t>(key),
+ GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE));
assert(gpg_err_code(err) == GPG_ERR_NO_ERROR);
} else {
- SPDLOG_WARN("GpgKeyOpera DeleteKeys get key failed", tmp);
+ GF_CORE_LOG_WARN("GpgKeyOpera DeleteKeys get key failed", tmp);
}
}
}
@@ -72,26 +76,24 @@ void GpgFrontend::GpgKeyOpera::DeleteKeys(
* @param expires date and time
* @return if successful
*/
-GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::SetExpire(
- const GpgKey& key, const SubkeyId& subkey_fpr,
- std::unique_ptr<boost::posix_time::ptime>& expires) {
+auto GpgKeyOpera::SetExpire(const GpgKey& key, const SubkeyId& subkey_fpr,
+ std::unique_ptr<QDateTime>& expires) -> GpgError {
unsigned long expires_time = 0;
if (expires != nullptr) {
- using namespace boost::posix_time;
- using namespace std::chrono;
- expires_time =
- to_time_t(*expires) - system_clock::to_time_t(system_clock::now());
+ expires_time = QDateTime::currentDateTime().secsTo(*expires);
}
- SPDLOG_DEBUG(key.GetId(), subkey_fpr, expires_time);
-
GpgError err;
- if (key.GetFingerprint() == subkey_fpr || subkey_fpr.empty())
- err = gpgme_op_setexpire(ctx_, gpgme_key_t(key), expires_time, nullptr, 0);
- else
- err = gpgme_op_setexpire(ctx_, gpgme_key_t(key), expires_time,
- subkey_fpr.c_str(), 0);
+ if (key.GetFingerprint() == subkey_fpr || subkey_fpr.isEmpty()) {
+ err =
+ gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key),
+ expires_time, nullptr, 0);
+ } else {
+ err =
+ gpgme_op_setexpire(ctx_.DefaultContext(), static_cast<gpgme_key_t>(key),
+ expires_time, subkey_fpr.toUtf8(), 0);
+ }
return err;
}
@@ -102,48 +104,52 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::SetExpire(
* @param outputFileName out file name(path)
* @return the process doing this job
*/
-void GpgFrontend::GpgKeyOpera::GenerateRevokeCert(
- const GpgKey& key, const std::string& output_file_path) {
+void GpgKeyOpera::GenerateRevokeCert(const GpgKey& key,
+ const QString& output_path) {
+ const auto app_path = Module::RetrieveRTValueTypedOrDefault<>(
+ "core", "gpgme.ctx.app_path", QString{});
// get all components
- GpgCommandExecutor::GetInstance().Execute(
- ctx_.GetInfo().AppPath,
- {"--command-fd", "0", "--status-fd", "1", "--no-tty", "-o",
- output_file_path, "--gen-revoke", key.GetFingerprint().c_str()},
- [=](int exit_code, const std::string& p_out, const std::string& p_err) {
- if (exit_code != 0) {
- SPDLOG_ERROR(
- "gnupg gen revoke execute error, process stderr: {}, process "
- "stdout: {}",
- p_err, p_out);
- } else {
- SPDLOG_DEBUG(
- "gnupg gen revoke exit_code: {}, process stdout size: {}",
- exit_code, p_out.size());
- }
- },
- [](QProcess* proc) -> void {
- // Code From Gpg4Win
- while (proc->canReadLine()) {
- const QString line = QString::fromUtf8(proc->readLine()).trimmed();
- SPDLOG_DEBUG("line: {}", line.toStdString());
- if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) {
- proc->write("y\n");
- } else if (line == QLatin1String("[GNUPG:] GET_LINE "
- "ask_revocation_reason.code")) {
- proc->write("0\n");
- } else if (line == QLatin1String("[GNUPG:] GET_LINE "
- "ask_revocation_reason.text")) {
- proc->write("\n");
- } else if (line == QLatin1String(
- "[GNUPG:] GET_BOOL openfile.overwrite.okay")) {
- // We asked before
- proc->write("y\n");
- } else if (line == QLatin1String("[GNUPG:] GET_BOOL "
- "ask_revocation_reason.okay")) {
- proc->write("y\n");
- }
- }
- });
+ GpgCommandExecutor::ExecuteSync(
+ {app_path,
+ {"--command-fd", "0", "--status-fd", "1", "--no-tty", "-o", output_path,
+ "--gen-revoke", key.GetFingerprint()},
+ [=](int exit_code, const QString& p_out, const QString& p_err) {
+ if (exit_code != 0) {
+ GF_CORE_LOG_ERROR(
+ "gnupg gen revoke execute error, process stderr: {}, process "
+ "stdout: {}",
+ p_err, p_out);
+ } else {
+ GF_CORE_LOG_DEBUG(
+ "gnupg gen revoke exit_code: {}, process stdout size: {}",
+ exit_code, p_out.size());
+ }
+ },
+ nullptr,
+ [](QProcess* proc) -> void {
+ // Code From Gpg4Win
+ while (proc->canReadLine()) {
+ const QString line = QString::fromUtf8(proc->readLine()).trimmed();
+ GF_CORE_LOG_DEBUG("line: {}", line.toStdString());
+ if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) {
+ proc->write("y\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_LINE "
+ "ask_revocation_reason.code")) {
+ proc->write("0\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_LINE "
+ "ask_revocation_reason.text")) {
+ proc->write("\n");
+ } else if (line ==
+ QLatin1String(
+ "[GNUPG:] GET_BOOL openfile.overwrite.okay")) {
+ // We asked before
+ proc->write("y\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_BOOL "
+ "ask_revocation_reason.okay")) {
+ proc->write("y\n");
+ }
+ }
+ }});
}
/**
@@ -151,138 +157,199 @@ void GpgFrontend::GpgKeyOpera::GenerateRevokeCert(
* @param params key generation args
* @return error information
*/
-GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey(
- 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();
-
- SPDLOG_DEBUG("params: {} {}", params->GetAlgo(), params->GetKeySizeStr());
-
- const char* algo = algo_utf8.c_str();
- unsigned long expires = 0;
- {
- using namespace boost::posix_time;
- using namespace std::chrono;
- expires = to_time_t(ptime(params->GetExpireTime())) -
- system_clock::to_time_t(system_clock::now());
- }
+void GpgKeyOpera::GenerateKey(const std::shared_ptr<GenKeyInfo>& params,
+ const GpgOperationCallback& callback) {
+ RunGpgOperaAsync(
+ [&ctx = ctx_, params](const DataObjectPtr& data_object) -> GpgError {
+ auto userid_utf8 = params->GetUserid();
+ const char* userid = userid_utf8.toUtf8();
+ auto algo_utf8 = params->GetAlgo() + params->GetKeySizeStr();
+
+ GF_CORE_LOG_DEBUG("params: {} {}", params->GetAlgo(),
+ params->GetKeySizeStr());
+
+ auto algo = algo_utf8.toUtf8();
+ unsigned long expires =
+ QDateTime::currentDateTime().secsTo(params->GetExpireTime());
+
+ GpgError err;
+ 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;
+
+ GF_CORE_LOG_DEBUG("key generation args: {}", userid, algo, expires,
+ flags);
+ err = gpgme_op_createkey(ctx.DefaultContext(), userid, algo, 0, expires,
+ nullptr, flags);
+
+ if (CheckGpgError(err) == GPG_ERR_NO_ERROR) {
+ data_object->Swap({GpgGenerateKeyResult{
+ gpgme_op_genkey_result(ctx.DefaultContext())}});
+ } else {
+ data_object->Swap({GpgGenerateKeyResult{}});
+ }
- GpgError err;
+ return CheckGpgError(err);
+ },
+ callback, "gpgme_op_createkey", "2.1.0");
+}
- SPDLOG_DEBUG("ctx version, {}", ctx_.GetInfo(false).GnupgVersion);
+/**
+ * Generate a new subkey of a certain key pair
+ * @param key target key pair
+ * @param params opera args
+ * @return error info
+ */
+void GpgKeyOpera::GenerateSubkey(const GpgKey& key,
+ const std::shared_ptr<GenKeyInfo>& params,
+ const GpgOperationCallback& callback) {
+ RunGpgOperaAsync(
+ [key, &ctx = ctx_, params](const DataObjectPtr&) -> GpgError {
+ if (!params->IsSubKey()) return GPG_ERR_CANCELED;
+
+ GF_CORE_LOG_DEBUG("generate subkey algo {} key size {}",
+ params->GetAlgo(), params->GetKeySizeStr());
+
+ auto algo = (params->GetAlgo() + params->GetKeySizeStr()).toUtf8();
+ unsigned long expires =
+ QDateTime::currentDateTime().secsTo(params->GetExpireTime());
+ 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;
+
+ GF_CORE_LOG_DEBUG("args: {} {} {} {}", key.GetId(), algo, expires,
+ flags);
+
+ auto err = gpgme_op_createsubkey(ctx.DefaultContext(),
+ static_cast<gpgme_key_t>(key), algo, 0,
+ expires, flags);
+ return CheckGpgError(err);
+ },
+ callback, "gpgme_op_createsubkey", "2.1.13");
+}
- if (ctx_.GetInfo(false).GnupgVersion >= "2.1.0") {
- unsigned int flags = 0;
+void GpgKeyOpera::GenerateKeyWithSubkey(
+ const std::shared_ptr<GenKeyInfo>& params,
+ const std::shared_ptr<GenKeyInfo>& subkey_params,
+ const GpgOperationCallback& callback) {
+ RunGpgOperaAsync(
+ [&ctx = ctx_, params,
+ subkey_params](const DataObjectPtr& data_object) -> GpgError {
+ auto userid = params->GetUserid().toUtf8();
+ auto algo = (params->GetAlgo() + params->GetKeySizeStr()).toUtf8();
+ unsigned long expires = expires =
+ QDateTime::currentDateTime().secsTo(params->GetExpireTime());
+
+ GpgError err;
+ 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;
+
+ GF_CORE_LOG_DEBUG("key generation args: {}", userid, algo, expires,
+ flags);
+ err = gpgme_op_createkey(ctx.DefaultContext(), userid, algo, 0, expires,
+ nullptr, flags);
+
+ if (CheckGpgError(err) != GPG_ERR_NO_ERROR) {
+ data_object->Swap({GpgGenerateKeyResult{}});
+ return 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;
+ auto genkey_result =
+ GpgGenerateKeyResult{gpgme_op_genkey_result(ctx.DefaultContext())};
- SPDLOG_DEBUG("args: {}", userid, algo, expires, flags);
+ auto key =
+ GpgKeyGetter::GetInstance().GetKey(genkey_result.GetFingerprint());
+ if (!key.IsGood()) {
+ GF_CORE_LOG_ERROR("cannot get key which has been generate, fpr: {}",
+ genkey_result.GetFingerprint());
+ return err;
+ }
- err = gpgme_op_createkey(ctx_, userid, algo, 0, expires, nullptr, flags);
+ if (subkey_params == nullptr || !subkey_params->IsSubKey()) return err;
- } else {
- std::stringstream ss;
- auto param_format =
- boost::format{
- "<GnupgKeyParms format=\"internal\">\n"
- "Key-Type: %1%\n"
- "Key-Usage: sign\n"
- "Key-Length: %2%\n"
- "Name-Real: %3%\n"
- "Name-Comment: %4%\n"
- "Name-Email: %5%\n"} %
- params->GetAlgo() % params->GetKeyLength() % params->GetName() %
- params->GetComment() % params->GetEmail();
- ss << param_format;
-
- if (!params->IsNonExpired()) {
- auto date = params->GetExpireTime().date();
- ss << boost::format{"Expire-Date: %1%\n"} % to_iso_string(date);
- } else
- ss << boost::format{"Expire-Date: 0\n"};
- if (!params->IsNoPassPhrase())
- ss << boost::format{"Passphrase: %1%\n"} % params->GetPassPhrase();
-
- ss << "</GnupgKeyParms>";
-
- SPDLOG_DEBUG("params: {}", ss.str());
-
- err = gpgme_op_genkey(ctx_, ss.str().c_str(), nullptr, nullptr);
- }
+ GF_CORE_LOG_DEBUG(
+ "try to generate subkey of key: {}, algo {} key size {}",
+ key.GetId(), subkey_params->GetAlgo(),
+ subkey_params->GetKeySizeStr());
- 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);
- }
+ algo = (subkey_params->GetAlgo() + subkey_params->GetKeySizeStr())
+ .toUtf8();
+ expires =
+ QDateTime::currentDateTime().secsTo(subkey_params->GetExpireTime());
- return check_gpg_error(err);
-}
+ flags = 0;
+ if (subkey_params->IsAllowEncryption()) flags |= GPGME_CREATE_ENCR;
+ if (subkey_params->IsAllowSigning()) flags |= GPGME_CREATE_SIGN;
+ if (subkey_params->IsAllowAuthentication()) flags |= GPGME_CREATE_AUTH;
+ if (subkey_params->IsNonExpired()) flags |= GPGME_CREATE_NOEXPIRE;
+ if (subkey_params->IsNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD;
-/**
- * Generate a new subkey of a certain key pair
- * @param key target key pair
- * @param params opera args
- * @return error info
- */
-GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateSubkey(
- const GpgKey& key, const std::unique_ptr<GenKeyInfo>& params) {
- if (!params->IsSubKey()) return GPG_ERR_CANCELED;
-
- SPDLOG_DEBUG("generate subkey algo {} key size {}", params->GetAlgo(),
- params->GetKeySizeStr());
-
- auto algo_utf8 = (params->GetAlgo() + params->GetKeySizeStr());
- const char* algo = algo_utf8.c_str();
- unsigned long expires = 0;
- {
- using namespace boost::posix_time;
- using namespace std::chrono;
- expires = to_time_t(ptime(params->GetExpireTime())) -
- system_clock::to_time_t(system_clock::now());
- }
- unsigned int flags = 0;
+ GF_CORE_LOG_DEBUG("subkey generation args: {} {} {} {}", key.GetId(),
+ algo, expires, flags);
- 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;
+ err = gpgme_op_createsubkey(ctx.DefaultContext(),
+ static_cast<gpgme_key_t>(key), algo, 0,
+ expires, flags);
- SPDLOG_DEBUG("args: {} {} {} {}", key.GetId(), algo, expires, flags);
+ if (CheckGpgError(err) == GPG_ERR_NO_ERROR) {
+ data_object->Swap(
+ {genkey_result, GpgGenerateKeyResult{gpgme_op_genkey_result(
+ ctx.DefaultContext())}});
+ } else {
+ data_object->Swap({genkey_result, GpgGenerateKeyResult{}});
+ }
- auto err =
- gpgme_op_createsubkey(ctx_, gpgme_key_t(key), algo, 0, expires, flags);
- return check_gpg_error(err);
+ return CheckGpgError(err);
+ },
+ callback, "gpgme_op_createkey&gpgme_op_createsubkey", "2.1.0");
}
-GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::ModifyPassword(
- const GpgFrontend::GpgKey& key) {
- if (ctx_.GetInfo(false).GnupgVersion < "2.0.15") {
- SPDLOG_ERROR("operator not support");
- return GPG_ERR_NOT_SUPPORTED;
- }
- auto err = gpgme_op_passwd(ctx_, gpgme_key_t(key), 0);
- return check_gpg_error(err);
+void GpgKeyOpera::ModifyPassword(const GpgKey& key,
+ const GpgOperationCallback& callback) {
+ RunGpgOperaAsync(
+ [&key, &ctx = ctx_](const DataObjectPtr&) -> GpgError {
+ return gpgme_op_passwd(ctx.DefaultContext(),
+ static_cast<gpgme_key_t>(key), 0);
+ },
+ callback, "gpgme_op_passwd", "2.0.15");
}
-GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::ModifyTOFUPolicy(
- const GpgFrontend::GpgKey& key, gpgme_tofu_policy_t tofu_policy) {
- if (ctx_.GetInfo(false).GnupgVersion < "2.1.10") {
- SPDLOG_ERROR("operator not support");
+
+auto GpgKeyOpera::ModifyTOFUPolicy(const GpgKey& key,
+ gpgme_tofu_policy_t tofu_policy)
+ -> GpgError {
+ const auto gnupg_version = Module::RetrieveRTValueTypedOrDefault<>(
+ "core", "gpgme.ctx.gnupg_version", QString{"2.0.0"});
+ GF_CORE_LOG_DEBUG("got gnupg version from rt: {}", gnupg_version);
+
+ if (CompareSoftwareVersion(gnupg_version, "2.1.10") < 0) {
+ GF_CORE_LOG_ERROR("operator not support");
return GPG_ERR_NOT_SUPPORTED;
}
- auto err = gpgme_op_tofu_policy(ctx_, gpgme_key_t(key), tofu_policy);
- return check_gpg_error(err);
+
+ auto err = gpgme_op_tofu_policy(ctx_.DefaultContext(),
+ static_cast<gpgme_key_t>(key), tofu_policy);
+ return CheckGpgError(err);
}
-void GpgFrontend::GpgKeyOpera::DeleteKey(const GpgFrontend::KeyId& key_id) {
+void GpgKeyOpera::DeleteKey(const GpgFrontend::KeyId& key_id) {
auto keys = std::make_unique<KeyIdArgsList>();
keys->push_back(key_id);
DeleteKeys(std::move(keys));
}
+} // namespace GpgFrontend