g10: Fix use-after-free.
[gnupg.git] / g10 / mainproc.c
index 7bb4350..c1819f0 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -757,7 +757,12 @@ proc_plaintext( CTX c, PACKET *pkt )
 
   if (!rc)
     {
-      rc = handle_plaintext (pt, &c->mfx, c->sigs_only, clearsig);
+      /* It we are in --verify mode, we do not want to output the
+       * signed text.  However, if --output is also used we do what
+       * has been requested and write out the signed data.  */
+      rc = handle_plaintext (pt, &c->mfx,
+                             (opt.outfp || opt.outfile)? 0 :  c->sigs_only,
+                             clearsig);
       if (gpg_err_code (rc) == GPG_ERR_EACCES && !c->sigs_only)
         {
           /* Can't write output but we hash it anyway to check the
@@ -1743,7 +1748,7 @@ check_sig_and_print (CTX c, kbnode_t node)
     write_status_text (STATUS_NEWSIG, NULL);
 
   astr = openpgp_pk_algo_name ( sig->pubkey_algo );
-  if (opt.flags.rfc4880bis && (issuer_fpr = issuer_fpr_string (sig)))
+  if ((issuer_fpr = issuer_fpr_string (sig)))
     {
       log_info (_("Signature made %s\n"), asctimestamp(sig->timestamp));
       log_info (_("               using %s key %s\n"),
@@ -1798,7 +1803,7 @@ check_sig_and_print (CTX c, kbnode_t node)
                   free_public_key (pk);
                   pk = NULL;
                   glo_ctrl.in_auto_key_retrieve++;
-                  res = keyserver_import_keyid (c->ctrl, sig->keyid,spec);
+                  res = keyserver_import_keyid (c->ctrl, sig->keyid,spec, 1);
                   glo_ctrl.in_auto_key_retrieve--;
                   if (!res)
                     rc = do_check_sig (c, node, NULL,
@@ -1833,7 +1838,7 @@ check_sig_and_print (CTX c, kbnode_t node)
               free_public_key (pk);
               pk = NULL;
               glo_ctrl.in_auto_key_retrieve++;
-              res = keyserver_import_keyid (c->ctrl, sig->keyid, spec);
+              res = keyserver_import_keyid (c->ctrl, sig->keyid, spec, 1);
               glo_ctrl.in_auto_key_retrieve--;
               free_keyserver_spec (spec);
               if (!res)
@@ -1842,14 +1847,12 @@ check_sig_and_print (CTX c, kbnode_t node)
         }
     }
 
-  /* If the above methods didn't work, our next try is to use locate
+  /* If the above methods didn't work, our next try is to locate
    * the key via its fingerprint from a keyserver.  This requires
    * that the signers fingerprint is encoded in the signature.  We
    * favor this over the WKD method (to be tried next), because an
-   * arbitrary keyserver is less subject to web bug like
-   * monitoring.  */
+   * arbitrary keyserver is less subject to web bug like monitoring.  */
   if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
-      && opt.flags.rfc4880bis
       && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
       && keyserver_any_configured (c->ctrl))
     {
@@ -1864,7 +1867,7 @@ check_sig_and_print (CTX c, kbnode_t node)
           free_public_key (pk);
           pk = NULL;
           glo_ctrl.in_auto_key_retrieve++;
-          res = keyserver_import_fprint (c->ctrl, p+1, n-1, opt.keyserver);
+          res = keyserver_import_fprint (c->ctrl, p+1, n-1, opt.keyserver, 1);
           glo_ctrl.in_auto_key_retrieve--;
           if (!res)
             rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
@@ -1884,7 +1887,7 @@ check_sig_and_print (CTX c, kbnode_t node)
       free_public_key (pk);
       pk = NULL;
       glo_ctrl.in_auto_key_retrieve++;
-      res = keyserver_import_wkd (c->ctrl, sig->signers_uid, NULL, NULL);
+      res = keyserver_import_wkd (c->ctrl, sig->signers_uid, 1, NULL, NULL);
       glo_ctrl.in_auto_key_retrieve--;
       /* Fixme: If the fingerprint is embedded in the signature,
        * compare it to the fingerprint of the returned key.  */
@@ -1903,7 +1906,7 @@ check_sig_and_print (CTX c, kbnode_t node)
       free_public_key (pk);
       pk = NULL;
       glo_ctrl.in_auto_key_retrieve++;
-      res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver );
+      res = keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver, 1);
       glo_ctrl.in_auto_key_retrieve--;
       if (!res)
         rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey, &pk);
@@ -1971,7 +1974,7 @@ check_sig_and_print (CTX c, kbnode_t node)
             before calling that function.  */
           if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY))
             valid = get_validity (c->ctrl, mainpk, un->pkt->pkt.user_id,
-                                  sig, 0);
+                                  NULL, 0);
           else
             valid = 0; /* Not used.  */
 
@@ -2073,7 +2076,7 @@ check_sig_and_print (CTX c, kbnode_t node)
                       information.  */
                     valid = (trust_value_to_string
                              (get_validity (c->ctrl, mainpk,
-                                            un->pkt->pkt.user_id, sig, 0)));
+                                            un->pkt->pkt.user_id, NULL, 0)));
                   log_printf (" [%s]\n",valid);
                 }
               else
@@ -2200,6 +2203,8 @@ check_sig_and_print (CTX c, kbnode_t node)
             }
         }
 
+      free_public_key (pk);
+      pk = NULL;
       release_kbnode( keyblock );
       if (rc)
         g10_errors_seen = 1;
@@ -2242,7 +2247,7 @@ proc_tree (CTX c, kbnode_t node)
 
   /* We must skip our special plaintext marker packets here because
      they may be the root packet.  These packets are only used in
-     addional checks and skipping them here doesn't matter.  */
+     additional checks and skipping them here doesn't matter.  */
   while (node
          && node->pkt->pkttype == PKT_GPG_CONTROL
           && node->pkt->pkt.gpg_control->control == CTRLPKT_PLAINTEXT_MARK)
@@ -2355,11 +2360,16 @@ proc_tree (CTX c, kbnode_t node)
           for (; n1; (n1 = find_next_kbnode(n1, PKT_SIGNATURE)))
             {
               /* We can't currently handle multiple signatures of
-                 different classes or digests (we'd pretty much have
-                 to run a different hash context for each), but if
-                 they are all the same, make an exception. */
+               * different classes (we'd pretty much have to run a
+               * different hash context for each), but if they are all
+               * the same and it is detached signature, we make an
+               * exception.  Note that the old code also disallowed
+               * multiple signatures if the digest algorithms are
+               * different.  We softened this restriction only for
+               * detached signatures, to be on the safe side. */
               if (n1->pkt->pkt.signature->sig_class != class
-                  || n1->pkt->pkt.signature->digest_algo != hash)
+                  || (c->any.data
+                      && n1->pkt->pkt.signature->digest_algo != hash))
                 {
                   multiple_ok = 0;
                   log_info (_("WARNING: multiple signatures detected.  "
@@ -2381,6 +2391,17 @@ proc_tree (CTX c, kbnode_t node)
           if (rc)
             goto detached_hash_err;
 
+          if (multiple_ok)
+            {
+              /* If we have and want to handle multiple signatures we
+               * need to enable all hash algorithms for the context.  */
+              for (n1 = node; (n1 = find_next_kbnode (n1, PKT_SIGNATURE)); )
+                if (!openpgp_md_test_algo (n1->pkt->pkt.signature->digest_algo))
+                  gcry_md_enable (c->mfx.md,
+                                  map_md_openpgp_to_gcry
+                                  (n1->pkt->pkt.signature->digest_algo));
+            }
+
           if (RFC2440 || RFC4880)
             ; /* Strict RFC mode.  */
           else if (sig->digest_algo == DIGEST_ALGO_SHA1
@@ -2388,7 +2409,9 @@ proc_tree (CTX c, kbnode_t node)
                    && sig->sig_class == 0x01)
             {
               /* Enable a workaround for a pgp5 bug when the detached
-               * signature has been created in textmode.  */
+               * signature has been created in textmode.  Note that we
+               * do not implement this for multiple signatures with
+               * different hash algorithms. */
               rc = gcry_md_open (&c->mfx.md2, sig->digest_algo, 0);
               if (rc)
                 goto detached_hash_err;