core: Return NO_SECKEY error code on decryption
authorWerner Koch <wk@gnupg.org>
Wed, 12 Jul 2017 16:30:49 +0000 (18:30 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 12 Jul 2017 16:30:49 +0000 (18:30 +0200)
* 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>
doc/gpgme.texi
src/decrypt.c

index bc40430..31929d3 100644 (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
 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
-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.
 @end deftypefun
 
index 1d8412a..aa17771 100644 (file)
@@ -1,6 +1,6 @@
 /* decrypt.c - Decrypt function.
    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.
 
@@ -49,6 +49,13 @@ typedef struct
   int 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.
      This makes appending new invalid signers painless while
      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).  */
       if (opd->failed && 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)
        return gpg_error (GPG_ERR_DECRYPT_FAILED);
       else if (!opd->okay)
@@ -319,7 +328,6 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
     case GPGME_STATUS_NO_SECKEY:
       {
        gpgme_recipient_t rec = opd->result.recipients;
-
        while (rec)
          {
            if (!strcmp (rec->keyid, args))
@@ -332,6 +340,7 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
        /* FIXME: Is this ok?  */
        if (!rec)
          return trace_gpg_error (GPG_ERR_INV_ENGINE);
+        opd->any_no_seckey = 1;
       }
       break;