core: Return NO_SECKEY error code on decryption

* src/decrypt.c (op_data_t): Add flag any_no_seckey.
(_gpgme_decrypt_status_handler): Consult that flag.
(_gpgme_decrypt_status_handler): Set that flag.
--

The NO_SECKEY is emitted instead of an "S ERROR pkdecrypt_failed" if
gpg knowns that a key has been encrypted to that key (cf. "S ENC_TO").
it is not fool proffof but in the majority of cases we can provide a
better error message than just DECRYPTION_FAILED.

GnuPG-bug-id: 3270
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2017-07-12 18:30:49 +02:00
parent d37bc7e025
commit ad0c5ab4cd
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 12 additions and 3 deletions

View File

@ -4893,7 +4893,7 @@ if @var{ctx}, @var{cipher} or @var{plain} is not a valid pointer,
@code{GPG_ERR_NO_DATA} if @var{cipher} does not contain any data to @code{GPG_ERR_NO_DATA} if @var{cipher} does not contain any data to
decrypt, @code{GPG_ERR_DECRYPT_FAILED} if @var{cipher} is not a valid decrypt, @code{GPG_ERR_DECRYPT_FAILED} if @var{cipher} is not a valid
cipher text, @code{GPG_ERR_BAD_PASSPHRASE} if the passphrase for the cipher text, @code{GPG_ERR_BAD_PASSPHRASE} if the passphrase for the
secret key could not be retrieved, and passes through any errors that secret key could not be retrieved, and passes through some errors that
are reported by the crypto engine support routines. are reported by the crypto engine support routines.
@end deftypefun @end deftypefun

View File

@ -1,6 +1,6 @@
/* decrypt.c - Decrypt function. /* decrypt.c - Decrypt function.
Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH Copyright (C) 2001, 2002, 2003, 2004, 2017 g10 Code GmbH
This file is part of GPGME. This file is part of GPGME.
@ -49,6 +49,13 @@ typedef struct
int failed; int failed;
gpg_error_t pkdecrypt_failed; gpg_error_t pkdecrypt_failed;
/* At least one secret key is not available. gpg issues NO_SECKEY
* status lines for each key the message has been encrypted to but
* that secret key is not available. This can't be done for hidden
* recipients, though. We track it here to allow for a better error
* message that the general DECRYPTION_FAILED. */
int any_no_seckey;
/* A pointer to the next pointer of the last recipient in the list. /* A pointer to the next pointer of the last recipient in the list.
This makes appending new invalid signers painless while This makes appending new invalid signers painless while
preserving the order. */ preserving the order. */
@ -273,6 +280,8 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
the underlying crypto engine (as error source). */ the underlying crypto engine (as error source). */
if (opd->failed && opd->pkdecrypt_failed) if (opd->failed && opd->pkdecrypt_failed)
return opd->pkdecrypt_failed; return opd->pkdecrypt_failed;
else if (opd->failed && opd->any_no_seckey)
return gpg_error (GPG_ERR_NO_SECKEY);
else if (opd->failed) else if (opd->failed)
return gpg_error (GPG_ERR_DECRYPT_FAILED); return gpg_error (GPG_ERR_DECRYPT_FAILED);
else if (!opd->okay) else if (!opd->okay)
@ -319,7 +328,6 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
case GPGME_STATUS_NO_SECKEY: case GPGME_STATUS_NO_SECKEY:
{ {
gpgme_recipient_t rec = opd->result.recipients; gpgme_recipient_t rec = opd->result.recipients;
while (rec) while (rec)
{ {
if (!strcmp (rec->keyid, args)) if (!strcmp (rec->keyid, args))
@ -332,6 +340,7 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
/* FIXME: Is this ok? */ /* FIXME: Is this ok? */
if (!rec) if (!rec)
return trace_gpg_error (GPG_ERR_INV_ENGINE); return trace_gpg_error (GPG_ERR_INV_ENGINE);
opd->any_no_seckey = 1;
} }
break; break;