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

View File

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

View File

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

View File

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

View File

@ -337,3 +337,27 @@ _gpgme_parse_plaintext (char *args, char **filenamep)
} }
return 0; 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. */ FILENAMEP. */
gpgme_error_t _gpgme_parse_plaintext (char *args, char **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. */ /* From verify.c. */

View File

@ -128,6 +128,19 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
} }
break; 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: default:
/* Ignore all other codes. */ /* Ignore all other codes. */
break; break;

View File

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

View File

@ -39,6 +39,9 @@ typedef struct
{ {
struct _gpgme_op_sign_result result; 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 /* A pointer to the next pointer of the last invalid signer in
the list. This makes appending new invalid signers painless the list. This makes appending new invalid signers painless
while preserving the order. */ 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; opd->last_signer_p = &(*opd->last_signer_p)->next;
break; break;
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF: case GPGME_STATUS_EOF:
/* The UI server does not send information about the created /* The UI server does not send information about the created
signature. This is irrelevant for this protocol and thus we 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); err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
else if (!opd->sig_created_seen else if (!opd->sig_created_seen
&& ctx->protocol != GPGME_PROTOCOL_UISERVER) && ctx->protocol != GPGME_PROTOCOL_UISERVER)
err = gpg_error (GPG_ERR_GENERAL); err = opd->failure_code? opd->failure_code:gpg_error (GPG_ERR_GENERAL);
break; break;
case GPGME_STATUS_INQUIRE_MAXLEN: case GPGME_STATUS_INQUIRE_MAXLEN:
@ -374,6 +381,7 @@ sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp)
opd = hook; opd = hook;
if (err) if (err)
return err; return err;
opd->failure_code = 0;
opd->last_signer_p = &opd->result.invalid_signers; opd->last_signer_p = &opd->result.invalid_signers;
opd->last_sig_p = &opd->result.signatures; opd->last_sig_p = &opd->result.signatures;
opd->ignore_inv_recp = !!ignore_inv_recp; opd->ignore_inv_recp = !!ignore_inv_recp;

View File

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

View File

@ -38,6 +38,9 @@ typedef struct
{ {
struct _gpgme_op_verify_result result; 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; gpgme_signature_t current_sig;
int did_prepare_new_sig; int did_prepare_new_sig;
int only_newsig_seen; 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. */ error code if we are not ready to process this status. */
return parse_error (sig, args, !!sig ); return parse_error (sig, args, !!sig );
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF: case GPGME_STATUS_EOF:
if (sig && !opd->did_prepare_new_sig) if (sig && !opd->did_prepare_new_sig)
calc_sig_summary (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->current_sig = NULL;
} }
opd->only_newsig_seen = 0; opd->only_newsig_seen = 0;
if (opd->failure_code)
return opd->failure_code;
break; break;
case GPGME_STATUS_PLAINTEXT: case GPGME_STATUS_PLAINTEXT: