diff options
Diffstat (limited to 'lang/cpp/src/context.cpp')
-rw-r--r-- | lang/cpp/src/context.cpp | 2138 |
1 files changed, 0 insertions, 2138 deletions
diff --git a/lang/cpp/src/context.cpp b/lang/cpp/src/context.cpp deleted file mode 100644 index 7a0fb23f..00000000 --- a/lang/cpp/src/context.cpp +++ /dev/null @@ -1,2138 +0,0 @@ -/* - context.cpp - wraps a gpgme key context - Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB - 2017, 2018 Intevation GmbH - - This file is part of GPGME++. - - GPGME++ is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - GPGME++ is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with GPGME++; see the file COPYING.LIB. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#include <context.h> -#include <eventloopinteractor.h> -#include <trustitem.h> -#include <keylistresult.h> -#include <keygenerationresult.h> -#include <importresult.h> -#include <decryptionresult.h> -#include <verificationresult.h> -#include <signingresult.h> -#include <encryptionresult.h> -#include <engineinfo.h> -#include <editinteractor.h> -#include <vfsmountresult.h> - -#include <interfaces/assuantransaction.h> -#include <defaultassuantransaction.h> - -#include "callbacks.h" -#include "data_p.h" -#include "context_p.h" -#include "util.h" -#include "tofuinfo.h" - -#include <gpgme.h> - -#include <functional> -#include <istream> -#include <numeric> -#ifndef NDEBUG -#include <iostream> -using std::cerr; -using std::endl; -#endif - -#include <cassert> - -namespace GpgME -{ - -static inline unsigned int xtoi_1(const char *str) -{ - const unsigned int ch = *str; - const unsigned int result = - ch <= '9' ? ch - '0' : - ch <= 'F' ? ch - 'A' + 10 : - /* else */ ch - 'a' + 10 ; - return result < 16 ? result : 0 ; -} -static inline int xtoi_2(const char *str) -{ - return xtoi_1(str) * 16U + xtoi_1(str + 1); -} - -static void percent_unescape(std::string &s, bool plus2space) -{ - std::string::iterator src = s.begin(), dest = s.begin(), end = s.end(); - while (src != end) { - if (*src == '%' && end - src > 2) { - *dest++ = xtoi_2(&*++src); - src += 2; - } else if (*src == '+' && plus2space) { - *dest++ = ' '; - ++src; - } else { - *dest++ = *src++; - } - } - s.erase(dest, end); -} - -void initializeLibrary() -{ - gpgme_check_version(nullptr); -} - -Error initializeLibrary(int) -{ - if (gpgme_check_version(GPGME_VERSION)) { - return Error(); - } else { - return Error::fromCode(GPG_ERR_USER_1); - } -} - -static void format_error(gpgme_error_t err, std::string &str) -{ - char buffer[ 1024 ]; - gpgme_strerror_r(err, buffer, sizeof buffer); - buffer[ sizeof buffer - 1 ] = '\0'; - str = buffer; -} - -const char *Error::source() const -{ - return gpgme_strsource((gpgme_error_t)mErr); -} - -const char *Error::asString() const -{ - if (mMessage.empty()) { - format_error(static_cast<gpgme_error_t>(mErr), mMessage); - } - return mMessage.c_str(); -} - -std::string Error::asStdString() const -{ - std::string message; - format_error(static_cast<gpgme_error_t>(mErr), message); - return message; -} - -int Error::code() const -{ - return gpgme_err_code(mErr); -} - -int Error::sourceID() const -{ - return gpgme_err_source(mErr); -} - -bool Error::isCanceled() const -{ - return code() == GPG_ERR_CANCELED || code() == GPG_ERR_FULLY_CANCELED; -} - -int Error::toErrno() const -{ - return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code())); -} - -// static -bool Error::hasSystemError() -{ - return gpgme_err_code_from_syserror() != GPG_ERR_MISSING_ERRNO ; -} - -// static -void Error::setSystemError(gpg_err_code_t err) -{ - setErrno(gpgme_err_code_to_errno(err)); -} - -// static -void Error::setErrno(int err) -{ - gpgme_err_set_errno(err); -} - -// static -Error Error::fromSystemError(unsigned int src) -{ - return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror())); -} - -// static -Error Error::fromErrno(int err, unsigned int src) -{ - return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err))); -} - -// static -Error Error::fromCode(unsigned int err, unsigned int src) -{ - return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err))); -} - -std::ostream &operator<<(std::ostream &os, const Error &err) -{ - return os << "GpgME::Error(" << err.encodedError() << " (" << err.asStdString() << "))"; -} - -Context::KeyListModeSaver::KeyListModeSaver(Context *ctx) - : mCtx{ctx} - , mKeyListMode{ctx ? ctx->keyListMode() : 0} -{ -} - -Context::KeyListModeSaver::~KeyListModeSaver() -{ - if (mCtx) { - mCtx->setKeyListMode(mKeyListMode); - } -} - -Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx)) -{ -} - -Context::~Context() -{ - delete d; -} - -Context *Context::createForProtocol(Protocol proto) -{ - gpgme_ctx_t ctx = nullptr; - if (gpgme_new(&ctx) != 0) { - return nullptr; - } - - switch (proto) { - case OpenPGP: - if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) { - gpgme_release(ctx); - return nullptr; - } - break; - case CMS: - if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) { - gpgme_release(ctx); - return nullptr; - } - break; - default: - return nullptr; - } - - return new Context(ctx); -} - -std::unique_ptr<Context> Context::create(Protocol proto) -{ - return std::unique_ptr <Context> (createForProtocol(proto)); -} - -std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error) -{ - gpgme_ctx_t ctx = nullptr; - if (const gpgme_error_t err = gpgme_new(&ctx)) { - if (error) { - *error = Error(err); - } - return std::unique_ptr<Context>(); - } - - switch (eng) { - case AssuanEngine: - if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) { - gpgme_release(ctx); - if (error) { - *error = Error(err); - } - return std::unique_ptr<Context>(); - } - break; - case G13Engine: - if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) { - gpgme_release(ctx); - if (error) { - *error = Error(err); - } - return std::unique_ptr<Context>(); - } - break; - case SpawnEngine: - if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) { - gpgme_release(ctx); - if (error) { - *error = Error(err); - } - return std::unique_ptr<Context>(); - } - break; - default: - if (error) { - *error = Error::fromCode(GPG_ERR_INV_ARG); - } - return std::unique_ptr<Context>(); - } - - if (error) { - *error = Error(); - } - - return std::unique_ptr<Context>(new Context(ctx)); -} - -void Context::setDecryptionFlags(DecryptionFlags flags) -{ - d->decryptFlags = flags; -} - -// -// -// Context::Private -// -// - -Context::Private::Private(gpgme_ctx_t c) - : ctx(c), - iocbs(nullptr), - lastop(None), - lasterr(GPG_ERR_NO_ERROR), - lastAssuanInquireData(Data::null), - lastAssuanTransaction(), - lastEditInteractor(), - lastCardEditInteractor(), - decryptFlags(DecryptNone) -{ - -} - -Context::Private::~Private() -{ - if (ctx) { - gpgme_release(ctx); - } - ctx = nullptr; - delete iocbs; -} - -// -// -// Context attributes: -// -// - -Protocol Context::protocol() const -{ - gpgme_protocol_t p = gpgme_get_protocol(d->ctx); - switch (p) { - case GPGME_PROTOCOL_OpenPGP: return OpenPGP; - case GPGME_PROTOCOL_CMS: return CMS; - default: return UnknownProtocol; - } -} - -void Context::setArmor(bool useArmor) -{ - gpgme_set_armor(d->ctx, int(useArmor)); -} -bool Context::armor() const -{ - return gpgme_get_armor(d->ctx); -} - -void Context::setTextMode(bool useTextMode) -{ - gpgme_set_textmode(d->ctx, int(useTextMode)); -} -bool Context::textMode() const -{ - return gpgme_get_textmode(d->ctx); -} - -void Context::setOffline(bool useOfflineMode) -{ - gpgme_set_offline(d->ctx, int(useOfflineMode)); -} -bool Context::offline() const -{ - return gpgme_get_offline(d->ctx); -} - -void Context::setIncludeCertificates(int which) -{ - if (which == DefaultCertificates) { - which = GPGME_INCLUDE_CERTS_DEFAULT; - } - gpgme_set_include_certs(d->ctx, which); -} - -int Context::includeCertificates() const -{ - return gpgme_get_include_certs(d->ctx); -} - -void Context::setKeyListMode(unsigned int mode) -{ - gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode)); -} - -void Context::addKeyListMode(unsigned int mode) -{ - const unsigned int cur = gpgme_get_keylist_mode(d->ctx); - gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode)); -} - -unsigned int Context::keyListMode() const -{ - return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx)); -} - -void Context::setProgressProvider(ProgressProvider *provider) -{ - gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : nullptr, provider); -} -ProgressProvider *Context::progressProvider() const -{ - void *pp = nullptr; - gpgme_progress_cb_t pcb = &progress_callback; - gpgme_get_progress_cb(d->ctx, &pcb, &pp); - return static_cast<ProgressProvider *>(pp); -} - -void Context::setPassphraseProvider(PassphraseProvider *provider) -{ - gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : nullptr, provider); -} - -PassphraseProvider *Context::passphraseProvider() const -{ - void *pp = nullptr; - gpgme_passphrase_cb_t pcb = &passphrase_callback; - gpgme_get_passphrase_cb(d->ctx, &pcb, &pp); - return static_cast<PassphraseProvider *>(pp); -} - -void Context::setManagedByEventLoopInteractor(bool manage) -{ - if (!EventLoopInteractor::instance()) { -#ifndef NDEBUG - cerr << "Context::setManagedByEventLoopInteractor(): " - "You must create an instance of EventLoopInteractor " - "before using anything that needs one." << endl; -#endif - return; - } - if (manage) { - EventLoopInteractor::instance()->manage(this); - } else { - EventLoopInteractor::instance()->unmanage(this); - } -} -bool Context::managedByEventLoopInteractor() const -{ - return d->iocbs != nullptr; -} - -void Context::installIOCallbacks(gpgme_io_cbs *iocbs) -{ - if (!iocbs) { - uninstallIOCallbacks(); - return; - } - gpgme_set_io_cbs(d->ctx, iocbs); - delete d->iocbs; d->iocbs = iocbs; -} - -void Context::uninstallIOCallbacks() -{ - static gpgme_io_cbs noiocbs = { nullptr, nullptr, nullptr, nullptr, nullptr }; - // io.add == 0 means disable io callbacks: - gpgme_set_io_cbs(d->ctx, &noiocbs); - delete d->iocbs; d->iocbs = nullptr; -} - -Error Context::setLocale(int cat, const char *val) -{ - return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val)); -} - -static GpgME::EngineInfo get_engine_info(gpgme_engine_info_t engineInfos, gpgme_protocol_t protocol) -{ - if (!engineInfos) { - return EngineInfo{}; - } - - for (gpgme_engine_info_t i = engineInfos ; i ; i = i->next) { - if (i->protocol == protocol) { - return EngineInfo{i}; - } - } - - return EngineInfo{}; -} - -static GpgME::EngineInfo get_static_engine_info(gpgme_protocol_t protocol) -{ - gpgme_engine_info_t ei = nullptr; - if (gpgme_get_engine_info(&ei)) { - return EngineInfo{}; - } - return get_engine_info(ei, protocol); -} - -EngineInfo Context::engineInfo() const -{ - return get_engine_info(gpgme_ctx_get_engine_info(d->ctx), gpgme_get_protocol(d->ctx)); -} - -Error Context::setEngineFileName(const char *filename) -{ - const char *const home_dir = engineInfo().homeDirectory(); - return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir)); -} - -Error Context::setEngineHomeDirectory(const char *home_dir) -{ - const char *const filename = engineInfo().fileName(); - return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir)); -} - -Error Context::setSender (const char *sender) -{ - return Error(gpgme_set_sender(d->ctx, sender)); -} - -const char *Context::getSender () -{ - return gpgme_get_sender(d->ctx); -} - -// -// -// Key Management -// -// - -Error Context::startKeyListing(const char *pattern, bool secretOnly) -{ - d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate) - ? Private::KeyListWithImport - : Private::KeyList); - return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly))); -} - -Error Context::startKeyListing(const char *patterns[], bool secretOnly) -{ - d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate) - ? Private::KeyListWithImport - : Private::KeyList); - return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0)); -} - -Key Context::nextKey(GpgME::Error &e) -{ - d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate) - ? Private::KeyListWithImport - : Private::KeyList); - gpgme_key_t key = nullptr; - e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key)); - return Key(key, false); -} - -KeyListResult Context::endKeyListing() -{ - d->lasterr = gpgme_op_keylist_end(d->ctx); - return keyListResult(); -} - -KeyListResult Context::keyListResult() const -{ - return KeyListResult(d->ctx, Error(d->lasterr)); -} - -Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/) -{ - d->lastop = Private::KeyList; - gpgme_key_t key = nullptr; - e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/)); - return Key(key, false); -} - -KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey) -{ - d->lastop = Private::KeyGen; - Data::Private *const dp = pubKey.impl(); - d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : nullptr, nullptr); - return KeyGenerationResult(d->ctx, Error(d->lasterr)); -} - -Error Context::startKeyGeneration(const char *parameters, Data &pubKey) -{ - d->lastop = Private::KeyGen; - Data::Private *const dp = pubKey.impl(); - return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : nullptr, nullptr)); -} - -KeyGenerationResult Context::keyGenerationResult() const -{ - if (d->lastop & Private::KeyGen) { - return KeyGenerationResult(d->ctx, Error(d->lasterr)); - } else { - return KeyGenerationResult(); - } -} - -Error Context::exportKeys(const char *pattern, Data &keyData, unsigned int mode) -{ - d->lastop = Private::Export; - Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, mode, dp ? dp->data : nullptr)); -} - -Error Context::exportKeys(const char *patterns[], Data &keyData, unsigned int mode) -{ - d->lastop = Private::Export; - Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, mode, dp ? dp->data : nullptr)); -} - -Error Context::startKeyExport(const char *pattern, Data &keyData, unsigned int mode) -{ - d->lastop = Private::Export; - Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, mode, dp ? dp->data : nullptr)); -} - -Error Context::startKeyExport(const char *patterns[], Data &keyData, unsigned int mode) -{ - d->lastop = Private::Export; - Data::Private *const dp = keyData.impl(); - return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, mode, dp ? dp->data : nullptr)); -} - -Error Context::exportPublicKeys(const char *pattern, Data &keyData, unsigned int mode) -{ - if (mode & (ExportSecret | ExportSecretSubkey)) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return exportKeys(pattern, keyData, mode); -} - -Error Context::exportPublicKeys(const char *patterns[], Data &keyData, unsigned int mode) -{ - if (mode & (ExportSecret | ExportSecretSubkey)) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return exportKeys(patterns, keyData, mode); -} - -Error Context::startPublicKeyExport(const char *pattern, Data &keyData, unsigned int mode) -{ - if (mode & (ExportSecret | ExportSecretSubkey)) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return startKeyExport(pattern, keyData, mode); -} - -Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, unsigned int mode) -{ - if (mode & (ExportSecret | ExportSecretSubkey)) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return startKeyExport(patterns, keyData, mode); -} - -/* Same as above but without mode */ -Error Context::exportPublicKeys(const char *pattern, Data &keyData) -{ - return exportPublicKeys(pattern, keyData, 0); -} - -Error Context::exportPublicKeys(const char *patterns[], Data &keyData) -{ - return exportPublicKeys(patterns, keyData, 0); -} - -Error Context::startPublicKeyExport(const char *pattern, Data &keyData) -{ - return startPublicKeyExport(pattern, keyData, 0); -} - -Error Context::startPublicKeyExport(const char *patterns[], Data &keyData) -{ - return startPublicKeyExport(patterns, keyData, 0); -} - -Error Context::exportSecretKeys(const char *pattern, Data &keyData, unsigned int mode) -{ - if (mode & ExportSecretSubkey) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return exportKeys(pattern, keyData, mode|ExportSecret); -} - -Error Context::exportSecretKeys(const char *patterns[], Data &keyData, unsigned int mode) -{ - if (mode & ExportSecretSubkey) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return exportKeys(patterns, keyData, mode|ExportSecret); -} - -Error Context::startSecretKeyExport(const char *pattern, Data &keyData, unsigned int mode) -{ - if (mode & ExportSecretSubkey) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return startKeyExport(pattern, keyData, mode|ExportSecret); -} - -Error Context::startSecretKeyExport(const char *patterns[], Data &keyData, unsigned int mode) -{ - if (mode & ExportSecretSubkey) { - return Error::fromCode(GPG_ERR_INV_FLAG); - } - return startKeyExport(patterns, keyData, mode|ExportSecret); -} - -Error Context::exportSecretSubkeys(const char *pattern, Data &keyData, unsigned int mode) -{ - return exportKeys(pattern, keyData, mode|ExportSecretSubkey); -} - -Error Context::exportSecretSubkeys(const char *patterns[], Data &keyData, unsigned int mode) -{ - return exportKeys(patterns, keyData, mode|ExportSecretSubkey); -} - -Error Context::startSecretSubkeyExport(const char *pattern, Data &keyData, unsigned int mode) -{ - return startKeyExport(pattern, keyData, mode|ExportSecretSubkey); -} - -Error Context::startSecretSubkeyExport(const char *patterns[], Data &keyData, unsigned int mode) -{ - return startKeyExport(patterns, keyData, mode|ExportSecretSubkey); -} - -ImportResult Context::importKeys(const Data &data) -{ - d->lastop = Private::Import; - const Data::Private *const dp = data.impl(); - d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : nullptr); - return ImportResult(d->ctx, Error(d->lasterr)); -} - -ImportResult Context::importKeys(const std::vector<Key> &kk) -{ - d->lastop = Private::Import; - d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED); - - bool shouldHaveResult = false; - gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ]; - gpgme_key_t *keys_it = &keys[0]; - for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) { - if (it->impl()) { - *keys_it++ = it->impl(); - } - } - *keys_it++ = nullptr; - d->lasterr = gpgme_op_import_keys(d->ctx, keys); - shouldHaveResult = true; - if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED || - gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) && - protocol() == CMS) { - // ok, try the workaround (export+import): - std::vector<const char *> fprs; - for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) { - if (const char *fpr = it->primaryFingerprint()) { - if (*fpr) { - fprs.push_back(fpr); - } - } else if (const char *keyid = it->keyID()) { - if (*keyid) { - fprs.push_back(keyid); - } - } - } - fprs.push_back(nullptr); - Data data; - Data::Private *const dp = data.impl(); - const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx); - gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN); - d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : nullptr); - gpgme_set_keylist_mode(d->ctx, oldMode); - if (!d->lasterr) { - data.seek(0, SEEK_SET); - d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : nullptr); - shouldHaveResult = true; - } - } - delete[] keys; - if (shouldHaveResult) { - return ImportResult(d->ctx, Error(d->lasterr)); - } else { - return ImportResult(Error(d->lasterr)); - } -} - -Error Context::startKeyImport(const Data &data) -{ - d->lastop = Private::Import; - const Data::Private *const dp = data.impl(); - return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : nullptr)); -} - -Error Context::startKeyImport(const std::vector<Key> &kk) -{ - d->lastop = Private::Import; - gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ]; - gpgme_key_t *keys_it = &keys[0]; - for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) { - if (it->impl()) { - *keys_it++ = it->impl(); - } - } - *keys_it++ = nullptr; - Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys)); - delete[] keys; - return err; -} - -ImportResult Context::importKeys(const std::vector<std::string> &keyIds) -{ - d->lastop = Private::Import; - const StringsToCStrings keyids{keyIds}; - d->lasterr = gpgme_op_receive_keys(d->ctx, keyids.c_strs()); - return ImportResult(d->ctx, Error(d->lasterr)); -} - -Error Context::startKeyImport(const std::vector<std::string> &keyIds) -{ - d->lastop = Private::Import; - const StringsToCStrings keyids{keyIds}; - d->lasterr = gpgme_op_receive_keys_start(d->ctx, keyids.c_strs()); - return Error(d->lasterr); -} - -ImportResult Context::importResult() const -{ - if (d->lastop & Private::Import) { - return ImportResult(d->ctx, Error(d->lasterr)); - } else { - return ImportResult(); - } -} - -Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion) -{ - d->lastop = Private::Delete; - return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion))); -} - -Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion) -{ - d->lastop = Private::Delete; - return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion))); -} - -Error Context::passwd(const Key &key) -{ - d->lastop = Private::Passwd; - return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U)); -} - -Error Context::startPasswd(const Key &key) -{ - d->lastop = Private::Passwd; - return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U)); -} - - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) -{ - d->lastop = Private::Edit; - d->lastEditInteractor = std::move(func); - Data::Private *const dp = data.impl(); - return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(), - d->lastEditInteractor.get() ? edit_interactor_callback : nullptr, - d->lastEditInteractor.get() ? d->lastEditInteractor->d : nullptr, - dp ? dp->data : nullptr)); -} - - -Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) -{ - d->lastop = Private::Edit; - d->lastEditInteractor = std::move(func); - Data::Private *const dp = data.impl(); - return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(), - d->lastEditInteractor.get() ? edit_interactor_callback : nullptr, - d->lastEditInteractor.get() ? d->lastEditInteractor->d : nullptr, - dp ? dp->data : nullptr)); -} - - -EditInteractor *Context::lastEditInteractor() const -{ - return d->lastEditInteractor.get(); -} - -std::unique_ptr<EditInteractor> Context::takeLastEditInteractor() -{ - return std::move(d->lastEditInteractor); -} - - -Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) -{ - d->lastop = Private::CardEdit; - d->lastCardEditInteractor = std::move(func); - Data::Private *const dp = data.impl(); - return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(), - d->lastCardEditInteractor.get() ? edit_interactor_callback : nullptr, - d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : nullptr, - dp ? dp->data : nullptr)); -} - -Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) -{ - d->lastop = Private::CardEdit; - d->lastCardEditInteractor = std::move(func); - Data::Private *const dp = data.impl(); - return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(), - d->lastCardEditInteractor.get() ? edit_interactor_callback : nullptr, - d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : nullptr, - dp ? dp->data : nullptr)); -} - -#pragma GCC diagnostic pop - -EditInteractor *Context::lastCardEditInteractor() const -{ - return d->lastCardEditInteractor.get(); -} - -std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor() -{ - return std::move(d->lastCardEditInteractor); -} - -Error Context::startTrustItemListing(const char *pattern, int maxLevel) -{ - d->lastop = Private::TrustList; - return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel)); -} - -TrustItem Context::nextTrustItem(Error &e) -{ - gpgme_trust_item_t ti = nullptr; - e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti)); - return TrustItem(ti); -} - -Error Context::endTrustItemListing() -{ - return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx)); -} - -static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen) -{ - assert(opaque); - AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque); - return t->data(static_cast<const char *>(data), datalen).encodedError(); -} - -static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data) -{ - assert(opaque); - Context::Private *p = static_cast<Context::Private *>(opaque); - AssuanTransaction *t = p->lastAssuanTransaction.get(); - assert(t); - Error err; - if (name) { - p->lastAssuanInquireData = t->inquire(name, args, err); - } else { - p->lastAssuanInquireData = Data::null; - } - if (!p->lastAssuanInquireData.isNull()) { - *r_data = p->lastAssuanInquireData.impl()->data; - } - return err.encodedError(); -} - -static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args) -{ - assert(opaque); - AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque); - std::string a = args; - percent_unescape(a, true); // ### why doesn't gpgme do this?? - return t->status(status, a.c_str()).encodedError(); -} - -Error Context::assuanTransact(const char *command) -{ - return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction)); -} - -Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction) -{ - gpgme_error_t err, operr; - - d->lastop = Private::AssuanTransact; - d->lastAssuanTransaction = std::move(transaction); - if (!d->lastAssuanTransaction.get()) { - return Error(d->lasterr = make_error(GPG_ERR_INV_ARG)); - } - err = gpgme_op_assuan_transact_ext - (d->ctx, - command, - assuan_transaction_data_callback, - d->lastAssuanTransaction.get(), - assuan_transaction_inquire_callback, - d, - assuan_transaction_status_callback, - d->lastAssuanTransaction.get(), - &operr); - - if (!err) - err = operr; - d->lasterr = err; - - return Error(d->lasterr); -} - -Error Context::startAssuanTransaction(const char *command) -{ - return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction)); -} - -Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction) -{ - gpgme_error_t err; - - d->lastop = Private::AssuanTransact; - d->lastAssuanTransaction = std::move(transaction); - if (!d->lastAssuanTransaction.get()) { - return Error(d->lasterr = make_error(GPG_ERR_INV_ARG)); - } - err = gpgme_op_assuan_transact_start - (d->ctx, - command, - assuan_transaction_data_callback, - d->lastAssuanTransaction.get(), - assuan_transaction_inquire_callback, - d, - assuan_transaction_status_callback, - d->lastAssuanTransaction.get()); - - d->lasterr = err; - - return Error(d->lasterr); -} - -AssuanTransaction *Context::lastAssuanTransaction() const -{ - return d->lastAssuanTransaction.get(); -} - -std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction() -{ - return std::move(d->lastAssuanTransaction); -} - -DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText, const DecryptionFlags flags) -{ - d->lastop = Private::Decrypt; - const Data::Private *const cdp = cipherText.impl(); - Data::Private *const pdp = plainText.impl(); - d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr); - return decryptionResult(); -} - -DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText) -{ - return decrypt(cipherText, plainText, DecryptNone); -} - -Error Context::startDecryption(const Data &cipherText, Data &plainText, const DecryptionFlags flags) -{ - d->lastop = Private::Decrypt; - const Data::Private *const cdp = cipherText.impl(); - Data::Private *const pdp = plainText.impl(); - return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), - cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr)); -} - -Error Context::startDecryption(const Data &cipherText, Data &plainText) -{ - return startDecryption(cipherText, plainText, DecryptNone); -} - -DecryptionResult Context::decryptionResult() const -{ - if (d->lastop & Private::Decrypt) { - return DecryptionResult(d->ctx, Error(d->lasterr)); - } else { - return DecryptionResult(); - } -} - -VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText) -{ - d->lastop = Private::Verify; - const Data::Private *const sdp = signature.impl(); - const Data::Private *const tdp = signedText.impl(); - d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr); - return verificationResult(); -} - -VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText) -{ - d->lastop = Private::Verify; - const Data::Private *const sdp = signedData.impl(); - Data::Private *const pdp = plainText.impl(); - d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr); - return verificationResult(); -} - -Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText) -{ - d->lastop = Private::Verify; - const Data::Private *const sdp = signature.impl(); - const Data::Private *const tdp = signedText.impl(); - return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr)); -} - -Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText) -{ - d->lastop = Private::Verify; - const Data::Private *const sdp = signedData.impl(); - Data::Private *const pdp = plainText.impl(); - return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr)); -} - -VerificationResult Context::verificationResult() const -{ - if (d->lastop & Private::Verify) { - const auto res = VerificationResult{d->ctx, Error(d->lasterr)}; - if ((d->lastop == Private::DecryptAndVerify) - && (res.error().code() == GPG_ERR_NO_DATA) - && (res.numSignatures() > 0)) { - // ignore "no data" error for verification if there are signatures and - // the operation was a combined (tentative) decryption and verification - // because then "no data" just indicates that there was nothing to decrypt - return VerificationResult{d->ctx, Error{}}; - } - return res; - } else { - return {}; - } -} - -std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText, DecryptionFlags flags) -{ - d->lastop = Private::DecryptAndVerify; - const Data::Private *const cdp = cipherText.impl(); - Data::Private *const pdp = plainText.impl(); - d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify), - cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr); - return std::make_pair(decryptionResult(), verificationResult()); -} - -std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText) -{ - return decryptAndVerify(cipherText, plainText, DecryptNone); -} - -Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText, DecryptionFlags flags) -{ - d->lastop = Private::DecryptAndVerify; - const Data::Private *const cdp = cipherText.impl(); - Data::Private *const pdp = plainText.impl(); - return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify), cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr)); -} - -Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText) -{ - return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone); -} - -namespace { -unsigned int to_auditlog_flags(unsigned int flags) -{ - unsigned int result = 0; - if (flags & Context::HtmlAuditLog) { - result |= GPGME_AUDITLOG_HTML; - } - if (flags & Context::AuditLogWithHelp) { - result |= GPGME_AUDITLOG_WITH_HELP; - } - if (flags & Context::DiagnosticAuditLog) { - result |= GPGME_AUDITLOG_DIAG; - } - return result; -} -} - -Error Context::startGetAuditLog(Data &output, unsigned int flags) -{ - d->lastop = Private::GetAuditLog; - Data::Private *const odp = output.impl(); - return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : nullptr, to_auditlog_flags(flags))); -} - -Error Context::getAuditLog(Data &output, unsigned int flags) -{ - d->lastop = Private::GetAuditLog; - Data::Private *const odp = output.impl(); - return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : nullptr, to_auditlog_flags(flags))); -} - -void Context::clearSigningKeys() -{ - gpgme_signers_clear(d->ctx); -} - -Error Context::addSigningKey(const Key &key) -{ - return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl())); -} - -Key Context::signingKey(unsigned int idx) const -{ - gpgme_key_t key = gpgme_signers_enum(d->ctx, idx); - return Key(key, false); -} - -std::vector<Key> Context::signingKeys() const -{ - std::vector<Key> result; - gpgme_key_t key = nullptr; - for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) { - result.push_back(Key(key, false)); - } - return result; -} - -void Context::clearSignatureNotations() -{ - gpgme_sig_notation_clear(d->ctx); -} - -GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags) -{ - return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags))); -} - -GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical) -{ - return Error(gpgme_sig_notation_add(d->ctx, nullptr, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0)); -} - -const char *Context::signaturePolicyURL() const -{ - for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) { - if (!n->name) { - return n->value; - } - } - return nullptr; -} - -Notation Context::signatureNotation(unsigned int idx) const -{ - for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) { - if (n->name) { - if (idx-- == 0) { - return Notation(n); - } - } - } - return Notation(); -} - -std::vector<Notation> Context::signatureNotations() const -{ - std::vector<Notation> result; - for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) { - if (n->name) { - result.push_back(Notation(n)); - } - } - return result; -} - -static gpgme_sig_mode_t sigflags2sigflags(SignatureMode flags) -{ - unsigned int result = 0; - if (flags & SignatureMode::NormalSignatureMode) { - result |= GPGME_SIG_MODE_NORMAL; - } - if (flags & SignatureMode::Detached) { - result |= GPGME_SIG_MODE_DETACH; - } - if (flags & SignatureMode::Clearsigned) { - result |= GPGME_SIG_MODE_CLEAR; - } - if (flags & SignatureMode::SignArchive) { - result |= GPGME_SIG_MODE_ARCHIVE; - } - if (flags & SignatureMode::SignFile) { - result |= GPGME_SIG_MODE_FILE; - } - return static_cast<gpgme_sig_mode_t>(result); -} - -SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode) -{ - d->lastop = Private::Sign; - const Data::Private *const pdp = plainText.impl(); - Data::Private *const sdp = signature.impl(); - d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode)); - return SigningResult(d->ctx, Error(d->lasterr)); -} - -Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode) -{ - d->lastop = Private::Sign; - const Data::Private *const pdp = plainText.impl(); - Data::Private *const sdp = signature.impl(); - return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode))); -} - -SigningResult Context::signingResult() const -{ - if (d->lastop & Private::Sign) { - return SigningResult(d->ctx, Error(d->lasterr)); - } else { - return SigningResult(); - } -} - -static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags) -{ - unsigned int result = 0; - if (flags & Context::AlwaysTrust) { - result |= GPGME_ENCRYPT_ALWAYS_TRUST; - } - if (flags & Context::NoEncryptTo) { - result |= GPGME_ENCRYPT_NO_ENCRYPT_TO; - } - if (flags & Context::Prepare) { - result |= GPGME_ENCRYPT_PREPARE; - } - if (flags & Context::ExpectSign) { - result |= GPGME_ENCRYPT_EXPECT_SIGN; - } - if (flags & Context::NoCompress) { - result |= GPGME_ENCRYPT_NO_COMPRESS; - } - if (flags & Context::Symmetric) { - result |= GPGME_ENCRYPT_SYMMETRIC; - } - if (flags & Context::ThrowKeyIds) { - result |= GPGME_ENCRYPT_THROW_KEYIDS; - } - if (flags & Context::EncryptWrap) { - result |= GPGME_ENCRYPT_WRAP; - } - if (flags & Context::WantAddress) { - result |= GPGME_ENCRYPT_WANT_ADDRESS; - } - if (flags & Context::EncryptArchive) { - result |= GPGME_ENCRYPT_ARCHIVE; - } - if (flags & Context::EncryptFile) { - result |= GPGME_ENCRYPT_FILE; - } - return static_cast<gpgme_encrypt_flags_t>(result); -} - -gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients) -{ - if (recipients.empty()) { - return nullptr; - } - gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ]; - gpgme_key_t *keys_it = ret; - for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) { - if (it->impl()) { - *keys_it++ = it->impl(); - } - } - *keys_it++ = nullptr; - return ret; -} - -EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) -{ - d->lastop = Private::Encrypt; - if (flags & NoEncryptTo) { - return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED))); - } - const Data::Private *const pdp = plainText.impl(); - Data::Private *const cdp = cipherText.impl(); - gpgme_key_t *const keys = getKeysFromRecipients(recipients); - d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags), - pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr); - if (keys) { - delete[] keys; - } - return EncryptionResult(d->ctx, Error(d->lasterr)); -} - -Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText) -{ - d->lastop = Private::Encrypt; - const Data::Private *const pdp = plainText.impl(); - Data::Private *const cdp = cipherText.impl(); - return Error(d->lasterr = gpgme_op_encrypt(d->ctx, nullptr, (gpgme_encrypt_flags_t)0, - pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr)); -} - -Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) -{ - d->lastop = Private::Encrypt; - if (flags & NoEncryptTo) { - return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)); - } - const Data::Private *const pdp = plainText.impl(); - Data::Private *const cdp = cipherText.impl(); - gpgme_key_t *const keys = getKeysFromRecipients(recipients); - d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags), - pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr); - if (keys) { - delete[] keys; - } - return Error(d->lasterr); -} - -EncryptionResult Context::encryptionResult() const -{ - if (d->lastop & Private::Encrypt) { - return EncryptionResult(d->ctx, Error(d->lasterr)); - } else { - return EncryptionResult(); - } -} - -std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) -{ - d->lastop = Private::SignAndEncrypt; - const Data::Private *const pdp = plainText.impl(); - Data::Private *const cdp = cipherText.impl(); - gpgme_key_t *const keys = getKeysFromRecipients(recipients); - d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags), - pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr); - if (keys) { - delete[] keys; - } - return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)), - EncryptionResult(d->ctx, Error(d->lasterr))); -} - -Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) -{ - d->lastop = Private::SignAndEncrypt; - const Data::Private *const pdp = plainText.impl(); - Data::Private *const cdp = cipherText.impl(); - gpgme_key_t *const keys = getKeysFromRecipients(recipients); - d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags), - pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr); - if (keys) { - delete[] keys; - } - return Error(d->lasterr); -} - -Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients) -{ - d->lastop = Private::CreateVFS; - gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ]; - gpgme_key_t *keys_it = keys; - for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) { - if (it->impl()) { - *keys_it++ = it->impl(); - } - } - *keys_it++ = nullptr; - - gpgme_error_t op_err; - d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err); - delete[] keys; - Error error(d->lasterr); - if (error) { - return error; - } - return Error(d->lasterr = op_err); -} - -VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir) -{ - d->lastop = Private::MountVFS; - gpgme_error_t op_err; - d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err); - return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err)); -} - -Error Context::cancelPendingOperation() -{ - return Error(gpgme_cancel_async(d->ctx)); -} - -Error Context::cancelPendingOperationImmediately() -{ - return Error(gpgme_cancel(d->ctx)); -} - -bool Context::poll() -{ - gpgme_error_t e = GPG_ERR_NO_ERROR; - const bool finished = gpgme_wait(d->ctx, &e, 0); - if (finished) { - d->lasterr = e; - } - return finished; -} - -Error Context::wait() -{ - gpgme_error_t e = GPG_ERR_NO_ERROR; - gpgme_wait(d->ctx, &e, 1); - return Error(d->lasterr = e); -} - -Error Context::lastError() const -{ - return Error(d->lasterr); -} - -Context::PinentryMode Context::pinentryMode() const -{ - switch (gpgme_get_pinentry_mode (d->ctx)) { - case GPGME_PINENTRY_MODE_ASK: - return PinentryAsk; - case GPGME_PINENTRY_MODE_CANCEL: - return PinentryCancel; - case GPGME_PINENTRY_MODE_ERROR: - return PinentryError; - case GPGME_PINENTRY_MODE_LOOPBACK: - return PinentryLoopback; - case GPGME_PINENTRY_MODE_DEFAULT: - default: - return PinentryDefault; - } -} - -Error Context::setPinentryMode(PinentryMode which) -{ - gpgme_pinentry_mode_t mode; - switch (which) { - case PinentryAsk: - mode = GPGME_PINENTRY_MODE_ASK; - break; - case PinentryCancel: - mode = GPGME_PINENTRY_MODE_CANCEL; - break; - case PinentryError: - mode = GPGME_PINENTRY_MODE_ERROR; - break; - case PinentryLoopback: - mode = GPGME_PINENTRY_MODE_LOOPBACK; - break; - case PinentryDefault: - default: - mode = GPGME_PINENTRY_MODE_DEFAULT; - } - return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode)); -} - -static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy) -{ - switch (policy) { - case TofuInfo::PolicyNone: - return GPGME_TOFU_POLICY_NONE; - case TofuInfo::PolicyAuto: - return GPGME_TOFU_POLICY_AUTO; - case TofuInfo::PolicyGood: - return GPGME_TOFU_POLICY_GOOD; - case TofuInfo::PolicyBad: - return GPGME_TOFU_POLICY_BAD; - case TofuInfo::PolicyAsk: - return GPGME_TOFU_POLICY_ASK; - case TofuInfo::PolicyUnknown: - default: - return GPGME_TOFU_POLICY_UNKNOWN; - } -} - -Error Context::setTofuPolicy(const Key &k, unsigned int policy) -{ - return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx, - k.impl(), to_tofu_policy_t(policy))); -} - -Error Context::setTofuPolicyStart(const Key &k, unsigned int policy) -{ - return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx, - k.impl(), to_tofu_policy_t(policy))); -} - -Error Context::startCreateKey (const char *userid, - const char *algo, - unsigned long reserved, - unsigned long expires, - const Key &certkey, - unsigned int flags) -{ - return Error(d->lasterr = gpgme_op_createkey_start(d->ctx, - userid, - algo, - reserved, - expires, - certkey.impl(), - flags)); -} - -Error Context::createKey (const char *userid, - const char *algo, - unsigned long reserved, - unsigned long expires, - const Key &certkey, - unsigned int flags) -{ - return Error(d->lasterr = gpgme_op_createkey(d->ctx, - userid, - algo, - reserved, - expires, - certkey.impl(), - flags)); -} - -KeyGenerationResult Context::createKeyEx (const char *userid, - const char *algo, - unsigned long reserved, - unsigned long expires, - const Key &certkey, - unsigned int flags) -{ - d->lasterr = gpgme_op_createkey(d->ctx, - userid, - algo, - reserved, - expires, - certkey.impl(), - flags); - return KeyGenerationResult(d->ctx, Error(d->lasterr)); -} - -Error Context::addUid(const Key &k, const char *userid) -{ - return Error(d->lasterr = gpgme_op_adduid(d->ctx, - k.impl(), userid, 0)); -} - -Error Context::startAddUid(const Key &k, const char *userid) -{ - return Error(d->lasterr = gpgme_op_adduid_start(d->ctx, - k.impl(), userid, 0)); -} - -Error Context::revUid(const Key &k, const char *userid) -{ - return Error(d->lasterr = gpgme_op_revuid(d->ctx, - k.impl(), userid, 0)); -} - -Error Context::startRevUid(const Key &k, const char *userid) -{ - return Error(d->lasterr = gpgme_op_revuid_start(d->ctx, - k.impl(), userid, 0)); -} - -Error Context::setPrimaryUid(const Key &k, const char *userid) -{ - return Error(d->lasterr = gpgme_op_set_uid_flag(d->ctx, k.impl(), userid, "primary", nullptr)); -} - -Error Context::startSetPrimaryUid(const Key &k, const char *userid) -{ - return Error(d->lasterr = gpgme_op_set_uid_flag_start(d->ctx, k.impl(), userid, "primary", nullptr)); -} - -Error Context::createSubkey(const Key &k, const char *algo, - unsigned long reserved, - unsigned long expires, - unsigned int flags) -{ - return Error(d->lasterr = gpgme_op_createsubkey(d->ctx, - k.impl(), algo, reserved, expires, flags)); -} - -Error Context::startCreateSubkey(const Key &k, const char *algo, - unsigned long reserved, - unsigned long expires, - unsigned int flags) -{ - return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx, - k.impl(), algo, reserved, expires, flags)); -} - -static std::string getLFSeparatedListOfStrings(const std::vector<std::string> &strings) -{ - if (strings.empty()) { - return std::string(); - } - - return std::accumulate( - std::next(strings.begin()), - strings.end(), - strings[0], - [](const std::string &a, const std::string &b) { - return a + '\n' + b; - } - ); -} - -static std::string getLFSeparatedListOfFingerprintsFromSubkeys(const std::vector<Subkey> &subkeys) -{ - if (subkeys.empty()) { - return std::string(); - } - - std::vector<std::string> fprs; - fprs.reserve(subkeys.size()); - for (auto &it : subkeys) { - if (it.fingerprint()) { - fprs.push_back(std::string(it.fingerprint())); - } - } - - return getLFSeparatedListOfStrings(fprs); -} - -Error Context::setExpire(const Key &k, unsigned long expires, - const std::vector<Subkey> &subkeys, - const Context::SetExpireFlags flags) -{ - std::string subfprs; - if (flags & Context::SetExpireAllSubkeys) { - subfprs = "*"; - } else { - subfprs = getLFSeparatedListOfFingerprintsFromSubkeys(subkeys); - } - return Error(d->lasterr = gpgme_op_setexpire(d->ctx, - k.impl(), expires, subfprs.c_str(), 0)); -} - -Error Context::startSetExpire(const Key &k, unsigned long expires, - const std::vector<Subkey> &subkeys, - const Context::SetExpireFlags flags) -{ - std::string subfprs; - if (flags & Context::SetExpireAllSubkeys) { - subfprs = "*"; - } else { - subfprs = getLFSeparatedListOfFingerprintsFromSubkeys(subkeys); - } - return Error(d->lasterr = gpgme_op_setexpire_start(d->ctx, - k.impl(), expires, subfprs.c_str(), 0)); -} - -static const char *owner_trust_to_string(Key::OwnerTrust trust) -{ - static const char *const owner_trust_strings[] = { - "undefined", // --quick-set-ownertrust wants "undefined" for Unknown - "undefined", // Undefined is never used for key->owner_trust - "never", - "marginal", - "full", - "ultimate", - }; - - if (Key::OwnerTrust::Unknown <= trust && trust <= Key::OwnerTrust::Ultimate) { - return owner_trust_strings[trust]; - } - return nullptr; -} - -Error Context::setOwnerTrust(const Key &key, Key::OwnerTrust trust) -{ - d->lasterr = gpgme_op_setownertrust(d->ctx, key.impl(), - owner_trust_to_string(trust)); - return Error(d->lasterr); -} - -Error Context::startSetOwnerTrust(const Key &key, Key::OwnerTrust trust) -{ - d->lasterr = gpgme_op_setownertrust_start(d->ctx, key.impl(), - owner_trust_to_string(trust)); - return Error(d->lasterr); -} - -Error Context::setKeyEnabled(const Key &key, bool enabled) -{ - d->lasterr = gpgme_op_setownertrust(d->ctx, key.impl(), - enabled ? "enable" : "disable"); - return Error(d->lasterr); -} - -Error Context::startSetKeyEnabled(const Key &key, bool enabled) -{ - d->lasterr = gpgme_op_setownertrust_start(d->ctx, key.impl(), - enabled ? "enable" : "disable"); - return Error(d->lasterr); -} - -static std::string getLFSeparatedListOfUserIds(const std::vector<UserID> &userIds) -{ - if (userIds.empty()) { - return std::string(); - } - - std::vector<std::string> uids; - uids.reserve(userIds.size()); - for (auto &userId : userIds) { - if (userId.id()) { - uids.push_back(std::string(userId.id())); - } - } - - return getLFSeparatedListOfStrings(uids); -} - -Error Context::revokeSignature(const Key &key, const Key &signingKey, - const std::vector<UserID> &userIds) -{ - const unsigned int flags = userIds.size() > 1 ? GPGME_REVSIG_LFSEP : 0; - const std::string uids = getLFSeparatedListOfUserIds(userIds); - return Error(d->lasterr = gpgme_op_revsig(d->ctx, - key.impl(), signingKey.impl(), uids.c_str(), flags)); -} - -Error Context::startRevokeSignature(const Key &key, const Key &signingKey, - const std::vector<UserID> &userIds) -{ - const unsigned int flags = userIds.size() > 1 ? GPGME_REVSIG_LFSEP : 0; - const std::string uids = getLFSeparatedListOfUserIds(userIds); - return Error(d->lasterr = gpgme_op_revsig_start(d->ctx, - key.impl(), signingKey.impl(), uids.c_str(), flags)); -} - -Error Context::addAdsk(const Key &k, const char *adsk) -{ - return Error(d->lasterr = gpgme_op_createsubkey(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK)); -} - -Error Context::startAddAdsk(const Key &k, const char *adsk) -{ - return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK)); -} - -Error Context::setFlag(const char *name, const char *value) -{ - return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value)); -} - -const char *Context::getFlag(const char *name) const -{ - return gpgme_get_ctx_flag(d->ctx, name); -} - -// Engine Spawn stuff -Error Context::spawn(const char *file, const char *argv[], - Data &input, Data &output, Data &err, - SpawnFlags flags) -{ - return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv, - input.impl() ? input.impl()->data : nullptr, - output.impl() ? output.impl()->data : nullptr, - err.impl() ? err.impl()->data : nullptr, - static_cast<int>(flags))); -} - -Error Context::spawnAsync(const char *file, const char *argv[], - Data &input, Data &output, Data &err, - SpawnFlags flags) -{ - return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv, - input.impl() ? input.impl()->data : nullptr, - output.impl() ? output.impl()->data : nullptr, - err.impl() ? err.impl()->data : nullptr, - static_cast<int>(flags))); -} - -std::ostream &operator<<(std::ostream &os, Protocol proto) -{ - os << "GpgME::Protocol("; - switch (proto) { - case OpenPGP: - os << "OpenPGP"; - break; - case CMS: - os << "CMS"; - break; - default: - case UnknownProtocol: - os << "UnknownProtocol"; - break; - } - return os << ')'; -} - -std::ostream &operator<<(std::ostream &os, Engine eng) -{ - os << "GpgME::Engine("; - switch (eng) { - case GpgEngine: - os << "GpgEngine"; - break; - case GpgSMEngine: - os << "GpgSMEngine"; - break; - case GpgConfEngine: - os << "GpgConfEngine"; - break; - case AssuanEngine: - os << "AssuanEngine"; - break; - case SpawnEngine: - os << "SpawnEngine"; - break; - default: - case UnknownEngine: - os << "UnknownEngine"; - break; - } - return os << ')'; -} - -std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl) -{ - os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl); - switch (incl) { - case Context::DefaultCertificates: - os << "(DefaultCertificates)"; - break; - case Context::AllCertificatesExceptRoot: - os << "(AllCertificatesExceptRoot)"; - break; - case Context::AllCertificates: - os << "(AllCertificates)"; - break; - case Context::NoCertificates: - os << "(NoCertificates)"; - break; - case Context::OnlySenderCertificate: - os << "(OnlySenderCertificate)"; - break; - } - return os << ')'; -} - -std::ostream &operator<<(std::ostream &os, KeyListMode mode) -{ - os << "GpgME::KeyListMode("; -#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0) - CHECK(Local); - CHECK(Extern); - CHECK(Signatures); - CHECK(Validate); - CHECK(Ephemeral); - CHECK(WithTofu); - CHECK(WithKeygrip); - CHECK(WithSecret); - CHECK(ForceExtern); -#undef CHECK - return os << ')'; -} - -std::ostream &operator<<(std::ostream &os, SignatureMode mode) -{ - os << "GpgME::SignatureMode("; -#undef CHECK - switch (mode & (NormalSignatureMode|Detached|Clearsigned)) { -#define CHECK( x ) case x: os << #x; break - CHECK(NormalSignatureMode); - CHECK(Detached); - CHECK(Clearsigned); -#undef CHECK - default: - os << "???" "(" << static_cast<int>(mode) << ')'; - break; - } -#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0) - CHECK(SignArchive); - CHECK(SignFile); -#undef CHECK - return os << ')'; -} - -std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags) -{ - os << "GpgME::Context::EncryptionFlags("; -#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) - CHECK(AlwaysTrust); - CHECK(NoEncryptTo); - CHECK(Prepare); - CHECK(ExpectSign); - CHECK(NoCompress); - CHECK(Symmetric); - CHECK(ThrowKeyIds); - CHECK(EncryptWrap); - CHECK(WantAddress); - CHECK(EncryptArchive); - CHECK(EncryptFile); -#undef CHECK - return os << ')'; -} - -std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags) -{ - os << "GpgME::Context::AuditLogFlags("; -#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) - CHECK(HtmlAuditLog); - CHECK(AuditLogWithHelp); -#undef CHECK - return os << ')'; -} - -} // namespace GpgME - -GpgME::Error GpgME::setDefaultLocale(int cat, const char *val) -{ - return Error(gpgme_set_locale(nullptr, cat, val)); -} - -GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto) -{ - return get_static_engine_info(proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP); -} - -const char *GpgME::dirInfo(const char *what) -{ - return gpgme_get_dirinfo(what); -} - -GpgME::Error GpgME::checkEngine(GpgME::Protocol proto) -{ - const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; - - return Error(gpgme_engine_check_version(p)); -} - -static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255); - -static gpgme_protocol_t engine2protocol(const GpgME::Engine engine) -{ - switch (engine) { - case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP; - case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS; - case GpgME::GpgConfEngine: - return GPGME_PROTOCOL_GPGCONF; - case GpgME::AssuanEngine: - return GPGME_PROTOCOL_ASSUAN; - case GpgME::G13Engine: - return GPGME_PROTOCOL_G13; - case GpgME::SpawnEngine: - return GPGME_PROTOCOL_SPAWN; - case GpgME::UnknownEngine: - ; - } - return UNKNOWN_PROTOCOL; -} - -GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine) -{ - return get_static_engine_info(engine2protocol(engine)); -} - -GpgME::Error GpgME::checkEngine(GpgME::Engine engine) -{ - const gpgme_protocol_t p = engine2protocol(engine); - - return Error(gpgme_engine_check_version(p)); -} - -static const unsigned long supported_features = 0 - | GpgME::ValidatingKeylistModeFeature - | GpgME::CancelOperationFeature - | GpgME::WrongKeyUsageFeature - | GpgME::DefaultCertificateInclusionFeature - | GpgME::GetSetEngineInfoFeature - | GpgME::ClearAddGetSignatureNotationsFeature - | GpgME::SetDataFileNameFeeature - | GpgME::SignatureNotationsKeylistModeFeature - | GpgME::KeySignatureNotationsFeature - | GpgME::KeyIsQualifiedFeature - | GpgME::SignatureNotationsCriticalFlagFeature - | GpgME::SignatureNotationsFlagsFeature - | GpgME::SignatureNotationsHumanReadableFlagFeature - | GpgME::SubkeyIsQualifiedFeature - | GpgME::EngineInfoHomeDirFeature - | GpgME::DecryptionResultFileNameFeature - | GpgME::DecryptionResultRecipientsFeature - | GpgME::VerificationResultFileNameFeature - | GpgME::SignaturePkaFieldsFeature - | GpgME::SignatureAlgorithmFieldsFeature - | GpgME::FdPointerFeature - | GpgME::AuditLogFeature - | GpgME::GpgConfEngineFeature - | GpgME::CancelOperationAsyncFeature - | GpgME::NoEncryptToEncryptionFlagFeature - | GpgME::CardKeyFeature - | GpgME::AssuanEngineFeature - | GpgME::EphemeralKeylistModeFeature - | GpgME::ImportFromKeyserverFeature - | GpgME::G13VFSFeature - | GpgME::PasswdFeature - ; - -static const unsigned long supported_features2 = 0 - | GpgME::BinaryAndFineGrainedIdentify - ; - -bool GpgME::hasFeature(unsigned long features) -{ - return features == (features & supported_features); -} - -bool GpgME::hasFeature(unsigned long features, unsigned long features2) -{ - return features == (features & supported_features) - && features2 == (features2 & supported_features2) - ; -} - -int GpgME::setGlobalFlag(const char *name, const char *value) -{ - return gpgme_set_global_flag(name, value); -} |