From e4a95746ada20d41161c3cdfb36d5167e2712098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= Date: Fri, 5 Apr 2024 15:08:01 +0200 Subject: [PATCH] cpp: Handle smart card op failure status messages * lang/cpp/src/editinteractor.cpp (parse_sc_op_failure): New. (CallbackHelper::edit_interactor_callback_impl): Parse failure code on GPGME_STATUS_SC_OP_FAILURE status. (sc_op_failure_to_error): New. -- This converts a SC_OP_FAILURE status message logged by gpg to a corresponding error. Unfortunately, GPG_ERR_BAD_PIN and GPG_ERR_BAD_RESET_CODE are mapped to the same SC_OP_FAILURE code, so that we had to choose one. GnuPG-bug-id: 6971 --- lang/cpp/src/editinteractor.cpp | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lang/cpp/src/editinteractor.cpp b/lang/cpp/src/editinteractor.cpp index 373a4464..72ed92f7 100644 --- a/lang/cpp/src/editinteractor.cpp +++ b/lang/cpp/src/editinteractor.cpp @@ -52,6 +52,7 @@ 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 { @@ -102,6 +103,9 @@ public: } 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); } @@ -280,6 +284,38 @@ GpgME::Error EditInteractor::parseStatusError(const char *args) 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(std::stoul(fields[0]))); + } else { + err = Error::fromCode(GPG_ERR_CARD); + } + + return err; +} + static const char *const status_strings[] = { "EOF", /* mkstatus processing starts here */