diff options
author | Saturneric <[email protected]> | 2021-12-31 01:50:20 +0000 |
---|---|---|
committer | Saturneric <[email protected]> | 2021-12-31 01:50:20 +0000 |
commit | cb10cffa20702ec3dac50adb5aeeebd6138279b0 (patch) | |
tree | c614cfb31b30d2c7f3a8175c8309ab2f738953d0 /src/gpg/GpgContext.cpp | |
parent | <refactor, test>(core, test): core improved and test gpg alone mode (diff) | |
download | GpgFrontend-cb10cffa20702ec3dac50adb5aeeebd6138279b0.tar.gz GpgFrontend-cb10cffa20702ec3dac50adb5aeeebd6138279b0.zip |
<refactor, test>(core, test): core improved and test gpg key generation
1. Refactor the initialization code of Context.
2. Improve some callback function support.
3. Improve the key deletion function.
4. Modify the key output of some functions.
5. Add test for key generation.
6. Delete all imported keys at the end of the test case.
7. Add setup mode initialization parameters for Context.
Diffstat (limited to '')
-rw-r--r-- | src/gpg/GpgContext.cpp | 189 |
1 files changed, 124 insertions, 65 deletions
diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index a39918e2..ff483637 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -43,7 +43,7 @@ namespace GpgFrontend { * Constructor * Set up gpgme-context, set paths to app-run path */ -GpgContext::GpgContext(const GpgContextInitArgs& args) { +GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) { static bool _first = true; if (_first) { @@ -62,94 +62,153 @@ GpgContext::GpgContext(const GpgContextInitArgs& args) { _ctx_ref = CtxRefHandler(_p_ctx); if (args.gpg_alone) { - info.AppPath = args.gpg_path; + info_.AppPath = args.gpg_path; auto err = gpgme_ctx_set_engine_info(_ctx_ref.get(), GPGME_PROTOCOL_OpenPGP, - info.AppPath.c_str(), - info.DatabasePath.c_str()); + info_.AppPath.c_str(), + info_.DatabasePath.c_str()); assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); } auto engine_info = gpgme_ctx_get_engine_info(*this); - // Check ENV before running - bool check_pass = false, find_openpgp = false, find_gpgconf = false, - find_assuan = false, find_cms = false; + bool check_passed = false, find_openpgp = false, find_gpgconf = false, + find_cms = false; + while (engine_info != nullptr) { - if (engine_info->protocol == GPGME_PROTOCOL_GPGCONF && - strcmp(engine_info->version, "1.0.0") != 0) - find_gpgconf = true; - if (engine_info->protocol == GPGME_PROTOCOL_OpenPGP && - strcmp(engine_info->version, "1.0.0") != 0) { - find_openpgp = true; - info.AppPath = engine_info->file_name; - info.DatabasePath = "default", info.GnupgVersion = engine_info->version; - DLOG(INFO) << "OpenPGP" - << std::string(engine_info->file_name == nullptr - ? "null" - : engine_info->file_name) - << std::string(engine_info->home_dir == nullptr - ? "null" - : engine_info->home_dir); + if (!strcmp(engine_info->version, "1.0.0")) { + engine_info = engine_info->next; + continue; } - if (engine_info->protocol == GPGME_PROTOCOL_CMS && - strcmp(engine_info->version, "1.0.0") != 0) - find_cms = true; - if (engine_info->protocol == GPGME_PROTOCOL_ASSUAN) find_assuan = true; + DLOG(INFO) << gpgme_get_protocol_name(engine_info->protocol) + << std::string(engine_info->file_name == nullptr + ? "null" + : engine_info->file_name) + << std::string(engine_info->home_dir == nullptr + ? "null" + : engine_info->home_dir); + + switch (engine_info->protocol) { + case GPGME_PROTOCOL_OpenPGP: + find_openpgp = true; + info_.AppPath = engine_info->file_name; + info_.GnupgVersion = engine_info->version; + break; + case GPGME_PROTOCOL_CMS: + find_cms = true; + info_.CMSPath = engine_info->file_name; + break; + case GPGME_PROTOCOL_GPGCONF: + find_gpgconf = true; + info_.GpgConfPath = engine_info->file_name; + break; + case GPGME_PROTOCOL_ASSUAN: + break; + case GPGME_PROTOCOL_G13: + break; + case GPGME_PROTOCOL_UISERVER: + break; + case GPGME_PROTOCOL_SPAWN: + break; + case GPGME_PROTOCOL_DEFAULT: + break; + case GPGME_PROTOCOL_UNKNOWN: + break; + } engine_info = engine_info->next; } - if (find_gpgconf && find_openpgp && find_cms && find_assuan) - check_pass = true; + // conditional check + if ((info_.GnupgVersion >= "2.0.0" && find_gpgconf && find_openpgp && + find_cms) || + (info_.GnupgVersion > "1.0.0" && find_gpgconf)) + check_passed = true; - if (!check_pass) { + if (!check_passed) { this->good_ = false; + LOG(ERROR) << "Env check failed"; return; } else { - LOG(INFO) << "GnuPG version" << info.GnupgVersion; - - // Set Independent Database - if (args.independent_database) { - info.DatabasePath = args.db_path; - LOG(INFO) << "gpg custom database path" << info.DatabasePath; - auto err = gpgme_ctx_set_engine_info( - _ctx_ref.get(), GPGME_PROTOCOL_OpenPGP, info.AppPath.c_str(), - info.DatabasePath.c_str()); - assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); - } - - /** Setting the output type must be done at the beginning */ - /** think this means ascii-armor --> ? */ - gpgme_set_armor(*this, 1); - // Speed up loading process - gpgme_set_offline(*this, 1); - - if (info.GnupgVersion >= "2.0.0") { - LOG(INFO) << "Using GnuPG 2.x"; - check_gpg_error(gpgme_set_keylist_mode( - *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | - GPGME_KEYLIST_MODE_SIGS | - GPGME_KEYLIST_MODE_SIG_NOTATIONS | - GPGME_KEYLIST_MODE_WITH_TOFU)); - } else { - LOG(INFO) << "Using GnuPG 1.x"; - check_gpg_error(gpgme_set_keylist_mode( - *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS | - GPGME_KEYLIST_MODE_SIG_NOTATIONS | - GPGME_KEYLIST_MODE_WITH_TOFU)); - } + DLOG(INFO) << "gnupg version" << info_.GnupgVersion; + init_ctx(); good_ = true; } } +void GpgContext::init_ctx() { + // Set Independent Database + if (info_.GnupgVersion <= "2.0.0" && args_.independent_database) { + info_.DatabasePath = args_.db_path; + DLOG(INFO) << "custom key db path" << info_.DatabasePath; + auto err = gpgme_ctx_set_engine_info(_ctx_ref.get(), GPGME_PROTOCOL_OpenPGP, + info_.AppPath.c_str(), + info_.DatabasePath.c_str()); + assert(check_gpg_error_2_err_code(err) == GPG_ERR_NO_ERROR); + } else { + info_.DatabasePath = "default"; + } + + /** Setting the output type must be done at the beginning */ + /** think this means ascii-armor --> ? */ + gpgme_set_armor(*this, 1); + // Speed up loading process + gpgme_set_offline(*this, 1); + + if (info_.GnupgVersion >= "2.0.0") { + check_gpg_error(gpgme_set_keylist_mode( + *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_WITH_SECRET | + GPGME_KEYLIST_MODE_SIGS | GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_WITH_TOFU)); + } else { + check_gpg_error(gpgme_set_keylist_mode( + *this, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS | + GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_WITH_TOFU)); + } + + // for unit test + if (args_.test_mode) { + LOG(INFO) << "test mode"; + if (info_.GnupgVersion >= "2.1.0") SetPassphraseCb(test_passphrase_cb); + gpgme_set_status_cb(*this, test_status_cb, nullptr); + } +} + bool GpgContext::good() const { return good_; } -void GpgContext::SetPassphraseCb(decltype(test_passphrase_cb) cb) const { - gpgme_set_passphrase_cb(*this, cb, nullptr); +void GpgContext::SetPassphraseCb(gpgme_passphrase_cb_t cb) const { + if (info_.GnupgVersion >= "2.1.0") { + if (gpgme_get_pinentry_mode(*this) != GPGME_PINENTRY_MODE_LOOPBACK) { + gpgme_set_pinentry_mode(*this, GPGME_PINENTRY_MODE_LOOPBACK); + } + gpgme_set_passphrase_cb(*this, cb, nullptr); + } else { + LOG(ERROR) << "Not supported for gnupg version" << info_.GnupgVersion; + } +} + +gpgme_error_t GpgContext::test_passphrase_cb(void *opaque, const char *uid_hint, + const char *passphrase_info, + int last_was_bad, int fd) { + size_t res; + std::string pass = "abcdefg\n"; + auto pass_len = pass.size(); + + size_t off = 0; + + do { + res = gpgme_io_write(fd, &pass[off], pass_len - off); + if (res > 0) off += res; + } while (res > 0 && off != pass_len); + + return off == pass_len ? 0 : gpgme_error_from_errno(errno); + return 0; } -std::string GpgContext::getGpgmeVersion() { - return {gpgme_check_version(nullptr)}; +gpgme_error_t GpgContext::test_status_cb(void *hook, const char *keyword, + const char *args) { + LOG(INFO) << "keyword" << keyword; + return 0; } } // namespace GpgFrontend
\ No newline at end of file |