aboutsummaryrefslogtreecommitdiffstats
path: root/lang/cpp/src/editinteractor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lang/cpp/src/editinteractor.cpp')
-rw-r--r--lang/cpp/src/editinteractor.cpp436
1 files changed, 0 insertions, 436 deletions
diff --git a/lang/cpp/src/editinteractor.cpp b/lang/cpp/src/editinteractor.cpp
deleted file mode 100644
index 5f9236cb..00000000
--- a/lang/cpp/src/editinteractor.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- editinteractor.cpp - Interface for edit interactors
- Copyright (C) 2007 Klarälvdalens Datakonsult AB
- 2016 Bundesamt für Sicherheit in der Informationstechnik
- Software engineering by 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 "editinteractor.h"
-#include "callbacks.h"
-#include "error.h"
-#include "util.h"
-
-#include <gpgme.h>
-
-#ifdef _WIN32
-# include <io.h>
-#include <windows.h>
-#else
-# include <unistd.h>
-#endif
-
-#include <cerrno>
-#include <cstring>
-#include <cstdlib>
-
-#ifndef GPG_ERR_ALREADY_SIGNED
-# define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1
-#endif
-
-using namespace GpgME;
-
-static const char *status_to_string(unsigned int status);
-static Error status_to_error(unsigned int status);
-static Error parse_sc_op_failure(const char *args);
-
-class EditInteractor::Private
-{
- friend class ::GpgME::EditInteractor;
- friend class ::GpgME::CallbackHelper;
- EditInteractor *const q;
-public:
- explicit Private(EditInteractor *qq);
- ~Private();
-
-private:
- unsigned int state = StartState;
- Error error;
- std::FILE *debug = nullptr;
- bool debugNeedsClosing = false;
-};
-
-class GpgME::CallbackHelper
-{
-private:
- static int writeAll(int fd, const void *buf, size_t count)
- {
- size_t toWrite = count;
- while (toWrite > 0) {
- const int n = gpgme_io_write(fd, buf, toWrite);
- if (n < 0) {
- return n;
- }
- toWrite -= n;
- }
- return count;
- }
-
-public:
- static int edit_interactor_callback_impl(void *opaque, gpgme_status_code_t status, const char *args, int fd)
- {
- EditInteractor::Private *ei = (EditInteractor::Private *)opaque;
-
- Error err = status_to_error(status);
-
- if (!err) {
-
- // advance to next state based on input:
- const unsigned int oldState = ei->state;
-
- if (ei->q->needsNoResponse(status)) {
- // keep state
- } else if (status == GPGME_STATUS_ERROR) {
- err = ei->q->parseStatusError(args);
- ei->state = EditInteractor::ErrorState;
- } else if (status == GPGME_STATUS_SC_OP_FAILURE) {
- err = parse_sc_op_failure(args);
- ei->state = EditInteractor::ErrorState;
- } else {
- ei->state = ei->q->nextState(status, args, err);
- }
-
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n",
- oldState, status_to_string(status), args ? args : "<null>", ei->state);
- }
- if (err || err.isCanceled()) {
- ei->state = oldState;
- goto error;
- }
-
- if (ei->state != oldState &&
- // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
- ei->error.code() == GPG_ERR_NO_ERROR) {
-
- // successful state change -> call action
- if (const char *const result = ei->q->action(err)) {
- if (err) {
- goto error;
- }
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: action result \"%s\"\n", result);
- }
- // if there's a result, write it:
- if (*result) {
- gpgme_err_set_errno(0);
- const ssize_t len = std::strlen(result);
- if (writeAll(fd, result, len) != len) {
- err = Error::fromSystemError();
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asStdString().c_str());
- }
- goto error;
- }
- }
- gpgme_err_set_errno(0);
- if (writeAll(fd, "\n", 1) != 1) {
- err = Error::fromSystemError();
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asStdString().c_str());
- }
- goto error;
- }
- } else {
- if (err) {
- goto error;
- }
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: no action result\n");
- }
- }
- } else {
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: no action executed\n");
- }
- }
- }
-
- error:
- if (err.code() == GPG_ERR_GENERAL) {
- // gpg may have asked an unknown question; try to use the default answer
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: action result \"%s\" (go with the default answer)\n", "");
- }
- if (writeAll(fd, "\n", 1) != 1) {
- err = Error::fromSystemError();
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asStdString().c_str());
- }
- } else {
- err = Error();
- }
- }
- if (err || err.isCanceled()) {
- ei->error = err;
- ei->state = EditInteractor::ErrorState;
- }
-
- if (ei->debug) {
- std::fprintf(ei->debug, "EditInteractor: error now %u (%s)\n",
- ei->error.encodedError(), gpgme_strerror(ei->error.encodedError()));
- }
-
- return ei->error.encodedError();
- }
-};
-
-static gpgme_error_t edit_interactor_callback(void *opaque, gpgme_status_code_t status, const char *args, int fd)
-{
- return CallbackHelper::edit_interactor_callback_impl(opaque, status, args, fd);
-}
-
-const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;
-
-EditInteractor::Private::Private(EditInteractor *qq)
- : q(qq)
-{
- const char *debug_env = std::getenv("GPGMEPP_INTERACTOR_DEBUG");
- if (!debug_env) {
- return;
- }
- if (!strcmp(debug_env, "stdout")) {
- debug = stdout;
- } else if (!strcmp(debug_env, "stderr")) {
- debug = stderr;
- } else if (debug_env) {
- debug = std::fopen(debug_env, "a+");
- debugNeedsClosing = true;
- }
-}
-
-EditInteractor::Private::~Private()
-{
- if (debug && debugNeedsClosing) {
- std::fclose(debug);
- }
-}
-
-EditInteractor::EditInteractor()
- : d(new Private(this))
-{
-
-}
-
-EditInteractor::~EditInteractor()
-{
- delete d;
-}
-
-unsigned int EditInteractor::state() const
-{
- return d->state;
-}
-
-Error EditInteractor::lastError() const
-{
- return d->error;
-}
-
-bool EditInteractor::needsNoResponse(unsigned int status) const
-{
- switch (status) {
- case GPGME_STATUS_ALREADY_SIGNED:
- case GPGME_STATUS_ERROR:
- case GPGME_STATUS_GET_BOOL:
- case GPGME_STATUS_GET_LINE:
- case GPGME_STATUS_KEY_CREATED:
- case GPGME_STATUS_NEED_PASSPHRASE_SYM:
- case GPGME_STATUS_SC_OP_FAILURE:
- case GPGME_STATUS_CARDCTRL:
- case GPGME_STATUS_BACKUP_KEY_CREATED:
- return false;
- default:
- return true;
- }
-}
-
-// static
-Error status_to_error(unsigned int status)
-{
- switch (status) {
- case GPGME_STATUS_MISSING_PASSPHRASE:
- return Error::fromCode(GPG_ERR_NO_PASSPHRASE);
- case GPGME_STATUS_ALREADY_SIGNED:
- return Error::fromCode(GPG_ERR_ALREADY_SIGNED);
- case GPGME_STATUS_SIGEXPIRED:
- return Error::fromCode(GPG_ERR_SIG_EXPIRED);
- }
- return Error();
-}
-
-void EditInteractor::setDebugChannel(std::FILE *debug)
-{
- d->debug = debug;
-}
-
-GpgME::Error EditInteractor::parseStatusError(const char *args)
-{
- Error err;
-
- const auto fields = split(args, ' ');
- if (fields.size() >= 2) {
- err = Error{static_cast<unsigned int>(std::stoul(fields[1]))};
- } else {
- err = Error::fromCode(GPG_ERR_GENERAL);
- }
-
- return err;
-}
-
-static Error sc_op_failure_to_error(unsigned int status)
-{
- switch (status) {
- case 1:
- // GPG_ERR_CANCELED or GPG_ERR_FULLY_CANCELED
- return Error::fromCode(GPG_ERR_CANCELED);
- case 2:
- // GPG_ERR_BAD_PIN or GPG_ERR_BAD_RESET_CODE [sic]
- return Error::fromCode(GPG_ERR_BAD_PIN);
- case 3:
- return Error::fromCode(GPG_ERR_PIN_BLOCKED);
- case 4:
- return Error::fromCode(GPG_ERR_NO_RESET_CODE);
- }
- return Error::fromCode(GPG_ERR_CARD);
-}
-
-// static
-Error parse_sc_op_failure(const char *args)
-{
- Error err;
-
- const auto fields = split(args, ' ');
- if (fields.size() >= 1) {
- err = sc_op_failure_to_error(static_cast<unsigned int>(std::stoul(fields[0])));
- } else {
- err = Error::fromCode(GPG_ERR_CARD);
- }
-
- return err;
-}
-
-static const char *const status_strings[] = {
- "EOF",
- /* mkstatus processing starts here */
- "ENTER",
- "LEAVE",
- "ABORT",
-
- "GOODSIG",
- "BADSIG",
- "ERRSIG",
-
- "BADARMOR",
-
- "RSA_OR_IDEA",
- "KEYEXPIRED",
- "KEYREVOKED",
-
- "TRUST_UNDEFINED",
- "TRUST_NEVER",
- "TRUST_MARGINAL",
- "TRUST_FULLY",
- "TRUST_ULTIMATE",
-
- "SHM_INFO",
- "SHM_GET",
- "SHM_GET_BOOL",
- "SHM_GET_HIDDEN",
-
- "NEED_PASSPHRASE",
- "VALIDSIG",
- "SIG_ID",
- "ENC_TO",
- "NODATA",
- "BAD_PASSPHRASE",
- "NO_PUBKEY",
- "NO_SECKEY",
- "NEED_PASSPHRASE_SYM",
- "DECRYPTION_FAILED",
- "DECRYPTION_OKAY",
- "MISSING_PASSPHRASE",
- "GOOD_PASSPHRASE",
- "GOODMDC",
- "BADMDC",
- "ERRMDC",
- "IMPORTED",
- "IMPORT_OK",
- "IMPORT_PROBLEM",
- "IMPORT_RES",
- "FILE_START",
- "FILE_DONE",
- "FILE_ERROR",
-
- "BEGIN_DECRYPTION",
- "END_DECRYPTION",
- "BEGIN_ENCRYPTION",
- "END_ENCRYPTION",
-
- "DELETE_PROBLEM",
- "GET_BOOL",
- "GET_LINE",
- "GET_HIDDEN",
- "GOT_IT",
- "PROGRESS",
- "SIG_CREATED",
- "SESSION_KEY",
- "NOTATION_NAME",
- "NOTATION_DATA",
- "POLICY_URL",
- "BEGIN_STREAM",
- "END_STREAM",
- "KEY_CREATED",
- "USERID_HINT",
- "UNEXPECTED",
- "INV_RECP",
- "NO_RECP",
- "ALREADY_SIGNED",
- "SIGEXPIRED",
- "EXPSIG",
- "EXPKEYSIG",
- "TRUNCATED",
- "ERROR",
- "NEWSIG",
- "REVKEYSIG",
- "SIG_SUBPACKET",
- "NEED_PASSPHRASE_PIN",
- "SC_OP_FAILURE",
- "SC_OP_SUCCESS",
- "CARDCTRL",
- "BACKUP_KEY_CREATED",
- "PKA_TRUST_BAD",
- "PKA_TRUST_GOOD",
-
- "PLAINTEXT",
-};
-static const unsigned int num_status_strings = sizeof status_strings / sizeof * status_strings ;
-
-const char *status_to_string(unsigned int idx)
-{
- if (idx < num_status_strings) {
- return status_strings[idx];
- } else {
- return "(unknown)";
- }
-}