diff options
Diffstat (limited to 'src/core/function/gpg/GpgKeyManager.cpp')
-rw-r--r-- | src/core/function/gpg/GpgKeyManager.cpp | 152 |
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 |