Fix returning new signatures when there are none.
authorBen Kibbey <bjk@luxsci.net>
Sun, 9 Nov 2014 21:42:54 +0000 (16:42 -0500)
committerWerner Koch <wk@gnupg.org>
Fri, 21 Nov 2014 19:25:43 +0000 (20:25 +0100)
* src/sign.c (gpgme_op_sign_result): Test that invalid and valid
signatures add up to gpgme_signers_count().
--

When invalid and valid signatures do not equal gpgme_signers_count() it
means that there was a bad passphrase during signing after the first
signer. This leaves the result.signatures from previous signers intact
which isn't correct since gpg will report:

gpg: number of one-pass packets does not match number of signature
packets
gpg: can't handle this ambiguous signature data

during verify. So when this happens append the valid signatures to the
.invalid_signers list with .reason set to GPG_ERR_GENERAL.

src/sign.c

index c55441d..034a869 100644 (file)
@@ -54,12 +54,22 @@ typedef struct
 } *op_data_t;
 
 
+static void release_signatures (gpgme_new_signature_t sig)
+{
+  while (sig)
+    {
+      gpgme_new_signature_t next = sig->next;
+      free (sig->fpr);
+      free (sig);
+      sig = next;
+    }
+}
+
 static void
 release_op_data (void *hook)
 {
   op_data_t opd = (op_data_t) hook;
   gpgme_invalid_key_t invalid_signer = opd->result.invalid_signers;
-  gpgme_new_signature_t sig = opd->result.signatures;
 
   while (invalid_signer)
     {
@@ -70,13 +80,7 @@ release_op_data (void *hook)
       invalid_signer = next;
     }
 
-  while (sig)
-    {
-      gpgme_new_signature_t next = sig->next;
-      free (sig->fpr);
-      free (sig);
-      sig = next;
-    }
+  release_signatures (opd->result.signatures);
 }
 
 
@@ -115,6 +119,48 @@ gpgme_op_sign_result (gpgme_ctx_t ctx)
          sig = sig->next;
        }
 
+      if (gpgme_signers_count (ctx)
+          && signatures + inv_signers != gpgme_signers_count (ctx))
+        {
+          TRACE_LOG3 ("result: invalid signers: %i, signatures: %i, count: %i",
+                      inv_signers, signatures, gpgme_signers_count (ctx));
+
+          sig = opd->result.signatures;
+          while (sig)
+            {
+              gpgme_invalid_key_t key;
+
+              key = malloc (sizeof (*key));
+              key->fpr = strdup (sig->fpr);
+              key->reason = GPG_ERR_GENERAL;
+              key->next = NULL;
+
+              inv_key = opd->result.invalid_signers;
+              if (!inv_key)
+                {
+                  opd->result.invalid_signers = inv_key = key;
+                  sig = sig->next;
+                  continue;
+                }
+
+              while (inv_key)
+                {
+                  if (!inv_key->next)
+                    {
+                      inv_key->next = key;
+                      break;
+                    }
+
+                  inv_key = inv_key->next;
+                }
+
+              sig = sig->next;
+            }
+
+          release_signatures (opd->result.signatures);
+          opd->result.signatures = NULL;
+        }
+
       TRACE_LOG2 ("result: invalid signers: %i, signatures: %i",
                  inv_signers, signatures);
       inv_key = opd->result.invalid_signers;