aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/function/gpg
diff options
context:
space:
mode:
authorSaturneric <[email protected]>2023-07-12 15:46:44 +0000
committerSaturneric <[email protected]>2023-07-12 15:46:44 +0000
commitcee9909c2b705e20564d529792055d070167c0a7 (patch)
tree70f489024e62c6aacb1c1cc51f59f110e9dcb6f5 /src/core/function/gpg
parentfix: modify the ui file of FilePage (diff)
downloadGpgFrontend-cee9909c2b705e20564d529792055d070167c0a7.tar.gz
GpgFrontend-cee9909c2b705e20564d529792055d070167c0a7.zip
feat: support owner trust level settings of gpg key
Diffstat (limited to 'src/core/function/gpg')
-rw-r--r--src/core/function/gpg/GpgKeyManager.cpp152
-rw-r--r--src/core/function/gpg/GpgKeyManager.h60
2 files changed, 212 insertions, 0 deletions
diff --git a/src/core/function/gpg/GpgKeyManager.cpp b/src/core/function/gpg/GpgKeyManager.cpp
index 050a8238..3e87f0dd 100644
--- a/src/core/function/gpg/GpgKeyManager.cpp
+++ b/src/core/function/gpg/GpgKeyManager.cpp
@@ -28,11 +28,14 @@
#include "GpgKeyManager.h"
+#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
+#include <memory>
#include <string>
#include "GpgBasicOperator.h"
#include "GpgKeyGetter.h"
+#include "spdlog/spdlog.h"
GpgFrontend::GpgKeyManager::GpgKeyManager(int channel)
: SingletonFunctionObject<GpgKeyManager>(channel) {}
@@ -93,3 +96,152 @@ bool GpgFrontend::GpgKeyManager::SetExpire(
return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR;
}
+
+bool GpgFrontend::GpgKeyManager::SetOwnerTrustLevel(const GpgKey& key,
+ int trust_level) {
+ if (trust_level < 0 || trust_level > 5) {
+ SPDLOG_ERROR("illegal owner trust level: {}", trust_level);
+ }
+
+ AutomatonNextStateHandler next_state_handler =
+ [](AutomatonState state, std::string status, std::string args) {
+ SPDLOG_DEBUG("next_state_handler state: {}, gpg_status: {}, args: {}",
+ state, status, args);
+ std::vector<std::string> tokens;
+ boost::split(tokens, args, boost::is_any_of(" "));
+
+ switch (state) {
+ case START:
+ if (status == "GET_LINE" && args == "keyedit.prompt")
+ return COMMAND;
+ return ERROR;
+ case COMMAND:
+ if (status == "GET_LINE" && args == "edit_ownertrust.value") {
+ return VALUE;
+ }
+ return ERROR;
+ case VALUE:
+ if (status == "GET_LINE" && args == "keyedit.prompt") {
+ return QUIT;
+ } else if (status == "GET_BOOL" &&
+ args == "edit_ownertrust.set_ultimate.okay") {
+ return REALLY_ULTIMATE;
+ }
+ return ERROR;
+ case REALLY_ULTIMATE:
+ if (status == "GET_LINE" && args == "keyedit.prompt") {
+ return QUIT;
+ }
+ return ERROR;
+ case QUIT:
+ if (status == "GET_LINE" && args == "keyedit.save.okay") {
+ return SAVE;
+ }
+ return ERROR;
+ case ERROR:
+ if (status == "GET_LINE" && args == "keyedit.prompt") {
+ return QUIT;
+ }
+ return ERROR;
+ default:
+ return ERROR;
+ };
+ };
+
+ AutomatonActionHandler action_handler =
+ [trust_level](AutomatonHandelStruct& handler, AutomatonState state) {
+ SPDLOG_DEBUG("action_handler state: {}", state);
+ switch (state) {
+ case COMMAND:
+ return std::string("trust");
+ case VALUE:
+ handler.SetSuccess(true);
+ return std::to_string(trust_level);
+ case REALLY_ULTIMATE:
+ handler.SetSuccess(true);
+ return std::string("Y");
+ case QUIT:
+ return std::string("quit");
+ case SAVE:
+ handler.SetSuccess(true);
+ return std::string("Y");
+ case START:
+ case ERROR:
+ return std::string("");
+ default:
+ return std::string("");
+ }
+ return std::string("");
+ };
+
+ auto key_fpr = key.GetFingerprint();
+ AutomatonHandelStruct handel_struct(key_fpr);
+ handel_struct.SetHandler(next_state_handler, action_handler);
+
+ GpgData data_out;
+
+ auto err = gpgme_op_interact(ctx_, gpgme_key_t(key), 0,
+ GpgKeyManager::interactor_cb_fnc,
+ (void*)&handel_struct, data_out);
+ if (err != GPG_ERR_NO_ERROR) {
+ SPDLOG_ERROR("fail to set owner trust level {} to key {}, err: {}",
+ trust_level, key.GetId(), gpgme_strerror(err));
+ }
+
+ return check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR &&
+ handel_struct.Success();
+}
+
+gpgme_error_t GpgFrontend::GpgKeyManager::interactor_cb_fnc(void* handle,
+ const char* status,
+ const char* args,
+ int fd) {
+ auto handle_struct = static_cast<AutomatonHandelStruct*>(handle);
+ std::string status_s = status;
+ std::string args_s = args;
+ SPDLOG_DEBUG("cb start status: {}, args: {}, fd: {}, handle struct state: {}",
+ status_s, args_s, fd, handle_struct->CuurentStatus());
+
+ if (status_s == "KEY_CONSIDERED") {
+ std::vector<std::string> tokens;
+ boost::split(tokens, args, boost::is_any_of(" "));
+
+ if (tokens.empty() || tokens[0] != handle_struct->KeyFpr()) {
+ SPDLOG_ERROR("handle struct key fpr {} mismatch token: {}, exit...",
+ handle_struct->KeyFpr(), tokens[0]);
+ return -1;
+ }
+
+ return 0;
+ }
+
+ if (status_s == "GOT_IT" || status_s.empty()) {
+ SPDLOG_DEBUG("status GOT_IT, continue...");
+ return 0;
+ }
+
+ AutomatonState next_state = handle_struct->NextState(status_s, args_s);
+ if (next_state == ERROR) {
+ SPDLOG_DEBUG("handle struct next state caught error, skipping...");
+ return GPG_ERR_FALSE;
+ }
+
+ if (next_state == SAVE) {
+ handle_struct->SetSuccess(true);
+ }
+
+ // set state and preform action
+ handle_struct->SetStatus(next_state);
+ Command cmd = handle_struct->Action();
+ SPDLOG_DEBUG("handle struct action done, next state: {}, action cmd: {}",
+ next_state, cmd);
+ if (!cmd.empty()) {
+ gpgme_io_write(fd, cmd.c_str(), cmd.size());
+ gpgme_io_write(fd, "\n", 1);
+ } else if (status_s == "GET_LINE") {
+ // avoid trapping in this state
+ return GPG_ERR_FALSE;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/src/core/function/gpg/GpgKeyManager.h b/src/core/function/gpg/GpgKeyManager.h
index 22738594..f967dee7 100644
--- a/src/core/function/gpg/GpgKeyManager.h
+++ b/src/core/function/gpg/GpgKeyManager.h
@@ -29,6 +29,9 @@
#ifndef GPGFRONTEND_ZH_CN_TS_GPGKEYMANAGER_H
#define GPGFRONTEND_ZH_CN_TS_GPGKEYMANAGER_H
+#include <functional>
+#include <string>
+
#include "core/GpgContext.h"
#include "core/GpgFunctionObject.h"
#include "core/GpgModel.h"
@@ -83,7 +86,64 @@ class GPGFRONTEND_CORE_EXPORT GpgKeyManager
bool SetExpire(const GpgKey& key, std::unique_ptr<GpgSubKey>& subkey,
std::unique_ptr<boost::posix_time::ptime>& expires);
+ /**
+ * @brief
+ *
+ * @return
+ */
+ bool SetOwnerTrustLevel(const GpgKey& key, int trust_level);
+
private:
+ static gpgme_error_t interactor_cb_fnc(void* handle, const char* status,
+ const char* args, int fd);
+
+ using Command = std::string;
+ using AutomatonState = enum {
+ START,
+ COMMAND,
+ VALUE,
+ REALLY_ULTIMATE,
+ SAVE,
+ ERROR,
+ QUIT,
+ };
+
+ struct AutomatonHandelStruct;
+
+ using AutomatonActionHandler =
+ std::function<Command(AutomatonHandelStruct&, AutomatonState)>;
+ using AutomatonNextStateHandler =
+ std::function<AutomatonState(AutomatonState, std::string, std::string)>;
+
+ struct AutomatonHandelStruct {
+ void SetStatus(AutomatonState next_state) { current_state_ = next_state; }
+ AutomatonState CuurentStatus() { return current_state_; }
+ void SetHandler(AutomatonNextStateHandler next_state_handler,
+ AutomatonActionHandler action_handler) {
+ next_state_handler_ = next_state_handler;
+ action_handler_ = action_handler;
+ }
+ AutomatonState NextState(std::string gpg_status, std::string args) {
+ return next_state_handler_(current_state_, gpg_status, args);
+ }
+ Command Action() { return action_handler_(*this, current_state_); }
+
+ void SetSuccess(bool success) { success_ = success; }
+
+ bool Success() { return success_; }
+
+ std::string KeyFpr() { return key_fpr_; }
+
+ AutomatonHandelStruct(std::string key_fpr) : key_fpr_(key_fpr) {}
+
+ private:
+ AutomatonState current_state_ = START;
+ AutomatonNextStateHandler next_state_handler_;
+ AutomatonActionHandler action_handler_;
+ bool success_ = false;
+ std::string key_fpr_;
+ };
+
GpgContext& ctx_ =
GpgContext::GetInstance(SingletonFunctionObject::GetChannel()); ///<
};