diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gpg/GpgContext.cpp | 189 | ||||
-rw-r--r-- | src/gpg/GpgContext.h | 35 | ||||
-rw-r--r-- | src/gpg/GpgInfo.h | 4 | ||||
-rw-r--r-- | src/gpg/function/BasicOperator.cpp | 6 | ||||
-rw-r--r-- | src/gpg/function/GpgKeyOpera.cpp | 19 |
5 files changed, 153 insertions, 100 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 diff --git a/src/gpg/GpgContext.h b/src/gpg/GpgContext.h index 887bb7a6..753e1090 100644 --- a/src/gpg/GpgContext.h +++ b/src/gpg/GpgContext.h @@ -33,10 +33,12 @@ namespace GpgFrontend { struct GpgContextInitArgs { + // make no sense for gpg2 bool independent_database = false; std::string db_path = {}; bool gpg_alone = false; std::string gpg_path = {}; + bool test_mode = false; GpgContextInitArgs() = default; }; @@ -55,14 +57,15 @@ class GpgContext : public SingletonFunctionObject<GpgContext> { [[nodiscard]] bool good() const; - [[nodiscard]] const GpgInfo& GetInfo() const { return info; } - - static std::string getGpgmeVersion(); + [[nodiscard]] const GpgInfo& GetInfo() const { return info_; } operator gpgme_ctx_t() const { return _ctx_ref.get(); } private: - GpgInfo info; + GpgInfo info_; + GpgContextInitArgs args_; + + void init_ctx(); struct _ctx_ref_deleter { void operator()(gpgme_ctx_t _ctx) { @@ -78,28 +81,12 @@ class GpgContext : public SingletonFunctionObject<GpgContext> { public: static gpgme_error_t test_passphrase_cb(void* opaque, const char* uid_hint, const char* passphrase_info, - int last_was_bad, int fd) { - LOG(INFO) << "test_passphrase_cb Called"; - size_t res; - std::string pass = "abcdefg\n"; - auto pass_len = pass.size(); - - size_t off = 0; - - (void)opaque; - (void)uid_hint; - (void)passphrase_info; - (void)last_was_bad; - - do { - res = gpgme_io_write(fd, &pass[off], pass_len - off); - if (res > 0) off += res; - } while (res > 0 && off != pass_len); + int last_was_bad, int fd); - return off == pass_len ? 0 : gpgme_error_from_errno(errno); - } + static gpgme_error_t test_status_cb(void* hook, const char* keyword, + const char* args); - void SetPassphraseCb(decltype(test_passphrase_cb) func) const; + void SetPassphraseCb(gpgme_passphrase_cb_t func) const; }; } // namespace GpgFrontend diff --git a/src/gpg/GpgInfo.h b/src/gpg/GpgInfo.h index 6ecb9b92..d651b2f6 100644 --- a/src/gpg/GpgInfo.h +++ b/src/gpg/GpgInfo.h @@ -40,6 +40,10 @@ class GpgInfo { std::string DatabasePath; std::string GnupgVersion; + + std::string GpgConfPath; + + std::string CMSPath; }; #endif // GPGFRONTEND_ZH_CN_TS_GPGINFO_H diff --git a/src/gpg/function/BasicOperator.cpp b/src/gpg/function/BasicOperator.cpp index 56b7ca54..e52c091c 100644 --- a/src/gpg/function/BasicOperator.cpp +++ b/src/gpg/function/BasicOperator.cpp @@ -187,9 +187,11 @@ gpgme_error_t GpgFrontend::BasicOperator::EncryptSign( void GpgFrontend::BasicOperator::SetSigners(KeyArgsList& keys) { gpgme_signers_clear(ctx); for (const GpgKey& key : keys) { + DLOG(INFO) << "key" << key.fpr(); if (key.CanSignActual()) { - auto gpgmeError = gpgme_signers_add(ctx, gpgme_key_t(key)); - check_gpg_error(gpgmeError); + DLOG(INFO) << "signer"; + auto error = gpgme_signers_add(ctx, gpgme_key_t(key)); + check_gpg_error(error); } } if (keys.size() != gpgme_signers_count(ctx)) diff --git a/src/gpg/function/GpgKeyOpera.cpp b/src/gpg/function/GpgKeyOpera.cpp index 4df06875..4cbc1d0a 100644 --- a/src/gpg/function/GpgKeyOpera.cpp +++ b/src/gpg/function/GpgKeyOpera.cpp @@ -47,11 +47,13 @@ void GpgFrontend::GpgKeyOpera::DeleteKeys( for (const auto& tmp : *key_ids) { auto key = GpgKeyGetter::GetInstance().GetKey(tmp); if (key.good()) { - LOG(INFO) << "GpgKeyOpera DeleteKeys Get Key Good"; - err = check_gpg_error(gpgme_op_delete(ctx, gpgme_key_t(key), 1)); + err = check_gpg_error( + gpgme_op_delete_ext(ctx, gpgme_key_t(key), + GPGME_DELETE_ALLOW_SECRET | GPGME_DELETE_FORCE)); assert(gpg_err_code(err) == GPG_ERR_NO_ERROR); - } else - LOG(WARNING) << "GpgKeyOpera DeleteKeys get key failed" << key.fpr(); + } else { + LOG(WARNING) << "GpgKeyOpera DeleteKeys get key failed" << tmp; + } } } @@ -152,8 +154,7 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey( const char* userid = userid_utf8.c_str(); auto algo_utf8 = params->getAlgo() + params->getKeySizeStr(); - LOG(INFO) << "GpgFrontend::GpgKeyOpera::GenerateKey Params" - << params->getAlgo() << params->getKeySizeStr(); + LOG(INFO) << "params" << params->getAlgo() << params->getKeySizeStr(); const char* algo = algo_utf8.c_str(); unsigned long expires = 0; @@ -176,14 +177,12 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey( if (params->isNonExpired()) flags |= GPGME_CREATE_NOEXPIRE; if (params->isNoPassPhrase()) flags |= GPGME_CREATE_NOPASSWD; - LOG(INFO) << "GpgFrontend::GpgKeyOpera::GenerateKey Args: " << userid - << algo << expires << flags; + LOG(INFO) << "args: " << userid << algo << expires << flags; err = gpgme_op_createkey(ctx, userid, algo, 0, expires, nullptr, flags); } else { std::stringstream ss; - auto param_format = boost::format{ "<GnupgKeyParms format=\"internal\">\n" @@ -203,6 +202,8 @@ GpgFrontend::GpgError GpgFrontend::GpgKeyOpera::GenerateKey( ss << "</GnupgKeyParms>"; + DLOG(INFO) << "params" << std::endl << ss.str(); + err = gpgme_op_genkey(ctx, ss.str().c_str(), nullptr, nullptr); } |