aboutsummaryrefslogtreecommitdiffstats
path: root/src/gpg/GpgContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/gpg/GpgContext.cpp189
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