Improve error return by checking the FAILURE status.

* src/gpgme.h.in (GPGME_STATUS_FAILURE): New.
* src/status-table.c (FAILURE): New.
* src/op-support.c (_gpgme_parse_failure): New.
* src/passphrase.c (_gpgme_passphrase_status_handler): Forward FAILURE
status line to the status callback.

* src/decrypt.c (op_data_t): Add field failure_code.
(_gpgme_decrypt_status_handler): Parse that code and act upon it on EOF.
* src/encrypt.c (op_data_t): Add field failure_code.
(_gpgme_encrypt_status_handler): Parse that code and act upon it on EOF.
* src/genkey.c (op_data_t): Add field failure_code.
(genkey_status_handler): Parse that code and act upon it on EOF.
* src/passwd.c (op_data_t): Add field failure_code.
(passwd_status_handler): Parse that code and act upon it on EOF.
* src/sign.c (op_data_t): Add field failure_code.
(_gpgme_sign_status_handler): Parse that code and act upon it on EOF.
* src/verify.c (op_data_t): Add field failure_code.
(_gpgme_verify_status_handler): Parse that code and act upon it on EOF.

--

This requires GnuPG 2.1.8 to actually make a difference.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-08-25 13:22:43 +02:00
parent 208f029746
commit 8ddc5801ad
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
11 changed files with 98 additions and 2 deletions

View File

@ -38,6 +38,9 @@ typedef struct
{
struct _gpgme_op_decrypt_result result;
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
int okay;
int failed;
@ -192,6 +195,10 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
switch (code)
{
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
/* FIXME: These error values should probably be attributed to
the underlying crypto engine (as error source). */
@ -199,6 +206,8 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
return gpg_error (GPG_ERR_DECRYPT_FAILED);
else if (!opd->okay)
return gpg_error (GPG_ERR_NO_DATA);
else if (opd->failure_code)
return opd->failure_code;
break;
case GPGME_STATUS_DECRYPTION_INFO:

View File

@ -36,6 +36,9 @@ typedef struct
{
struct _gpgme_op_encrypt_result result;
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
/* A pointer to the next pointer of the last invalid recipient in
the list. This makes appending new invalid recipients painless
while preserving the order. */
@ -114,9 +117,15 @@ _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code,
switch (code)
{
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
if (opd->result.invalid_recipients)
return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
if (opd->failure_code)
return opd->failure_code;
break;
case GPGME_STATUS_INV_RECP:

View File

@ -37,6 +37,9 @@ typedef struct
{
struct _gpgme_op_genkey_result result;
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
/* The key parameters passed to the crypto engine. */
gpgme_data_t key_parameter;
} *op_data_t;
@ -118,10 +121,16 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
}
break;
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
/* FIXME: Should return some more useful error value. */
if (!opd->result.primary && !opd->result.sub)
return gpg_error (GPG_ERR_GENERAL);
else if (opd->failure_code)
return opd->failure_code;
break;
case GPGME_STATUS_INQUIRE_MAXLEN:

View File

@ -548,7 +548,8 @@ typedef enum
GPGME_STATUS_ATTRIBUTE = 89,
GPGME_STATUS_BEGIN_SIGNING = 90,
GPGME_STATUS_KEY_NOT_CREATED = 91,
GPGME_STATUS_INQUIRE_MAXLEN = 92
GPGME_STATUS_INQUIRE_MAXLEN = 92,
GPGME_STATUS_FAILURE = 93
}
gpgme_status_code_t;

View File

@ -337,3 +337,27 @@ _gpgme_parse_plaintext (char *args, char **filenamep)
}
return 0;
}
/* Parse a FAILURE status line and return the error code. ARGS is
modified to contain the location part. */
gpgme_error_t
_gpgme_parse_failure (char *args)
{
char *where, *which;
where = strchr (args, ' ');
if (!where)
return trace_gpg_error (GPG_ERR_INV_ENGINE);
*where = '\0';
which = where + 1;
where = strchr (which, ' ');
if (where)
*where = '\0';
where = args;
return atoi (which);
}

View File

@ -65,6 +65,10 @@ gpgme_error_t _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key);
FILENAMEP. */
gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep);
/* Parse a FAILURE status line and return the error code. ARGS is
modified to contain the location part. */
gpgme_error_t _gpgme_parse_failure (char *args);
/* From verify.c. */

View File

@ -128,6 +128,19 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
}
break;
case GPGME_STATUS_FAILURE:
/* We abuse this status handler to forward FAILURE status codes
to the caller. This should better be done in a generic
handler, but for now this is sufficient. */
if (ctx->status_cb)
{
err = ctx->status_cb (ctx->status_cb_value, "FAILURE", args);
if (err)
return err;
}
break;
default:
/* Ignore all other codes. */
break;

View File

@ -30,6 +30,9 @@
typedef struct
{
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
int success_seen;
int error_seen;
} *op_data_t;
@ -92,6 +95,10 @@ passwd_status_handler (void *priv, gpgme_status_code_t code, char *args)
opd->success_seen = 1;
break;
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
/* In case the OpenPGP engine does not properly implement the
passwd command we won't get a success status back and thus we
@ -102,6 +109,8 @@ passwd_status_handler (void *priv, gpgme_status_code_t code, char *args)
if (ctx->protocol == GPGME_PROTOCOL_OpenPGP
&& !opd->error_seen && !opd->success_seen)
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else if (opd->failure_code)
err = opd->failure_code;
break;
default:

View File

@ -39,6 +39,9 @@ typedef struct
{
struct _gpgme_op_sign_result result;
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
/* A pointer to the next pointer of the last invalid signer in
the list. This makes appending new invalid signers painless
while preserving the order. */
@ -327,6 +330,10 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
opd->last_signer_p = &(*opd->last_signer_p)->next;
break;
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
/* The UI server does not send information about the created
signature. This is irrelevant for this protocol and thus we
@ -335,7 +342,7 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
else if (!opd->sig_created_seen
&& ctx->protocol != GPGME_PROTOCOL_UISERVER)
err = gpg_error (GPG_ERR_GENERAL);
err = opd->failure_code? opd->failure_code:gpg_error (GPG_ERR_GENERAL);
break;
case GPGME_STATUS_INQUIRE_MAXLEN:
@ -374,6 +381,7 @@ sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp)
opd = hook;
if (err)
return err;
opd->failure_code = 0;
opd->last_signer_p = &opd->result.invalid_signers;
opd->last_sig_p = &opd->result.signatures;
opd->ignore_inv_recp = !!ignore_inv_recp;

View File

@ -66,6 +66,7 @@ static struct status_table_s status_table[] =
{ "ERRSIG", GPGME_STATUS_ERRSIG },
{ "EXPKEYSIG", GPGME_STATUS_EXPKEYSIG },
{ "EXPSIG", GPGME_STATUS_EXPSIG },
{ "FAILURE", GPGME_STATUS_FAILURE },
{ "FILE_DONE", GPGME_STATUS_FILE_DONE },
{ "FILE_ERROR", GPGME_STATUS_FILE_ERROR },
{ "FILE_START", GPGME_STATUS_FILE_START },

View File

@ -38,6 +38,9 @@ typedef struct
{
struct _gpgme_op_verify_result result;
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
gpgme_signature_t current_sig;
int did_prepare_new_sig;
int only_newsig_seen;
@ -769,6 +772,10 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
error code if we are not ready to process this status. */
return parse_error (sig, args, !!sig );
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
if (sig && !opd->did_prepare_new_sig)
calc_sig_summary (sig);
@ -795,6 +802,8 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
opd->current_sig = NULL;
}
opd->only_newsig_seen = 0;
if (opd->failure_code)
return opd->failure_code;
break;
case GPGME_STATUS_PLAINTEXT: