aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/function/gpg/GpgKeyManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/function/gpg/GpgKeyManager.cpp')
-rw-r--r--src/core/function/gpg/GpgKeyManager.cpp152
1 files changed, 152 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