[git] GnuPG - branch, master, updated. gnupg-2.1.19-93-ga8895c9

by Werner Koch cvs at cvs.gnupg.org
Thu Mar 30 09:20:01 CEST 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  a8895c99a7d0750132477d80cd66caaf3a709113 (commit)
       via  afa86809087909a8ba2f9356588bf90cc923529c (commit)
       via  ba57f8302a3ee12ff117b0243047241c44388179 (commit)
      from  0526c99164d3531b5ec763ffc672407eb24b2296 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a8895c99a7d0750132477d80cd66caaf3a709113
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Mar 30 09:07:02 2017 +0200

    gpg: Revamp reading and writing of ring trust packets.
    
    * g10/parse-packet.c (parse_trust): Rename to ...
    (parse_ring_trust): this.  Change args and implement new ring trust
    packet format.
    (parse): Add special ring trust packet handling.
    * g10/packet.h (PKT_user_id): New fields KEYUPDATE, UPDATEURL, and
    KEYSRC.
    (PKT_public_key): Ditto.
    (RING_TRUST_SIG, RING_TRUST_KEY, RING_TRUST_UID): New consts.
    (PKT_ring_trust): New.
    (struct packet_struct): Remove member RING_TRUST.
    (strcu parse_packet_ctx_s): Add field SKIP_META.
    (init_parse_packet): Init SKIPT_META.
    * g10/free-packet.c (release_public_key_parts): Free UDPATEURL.
    (free_user_id): Ditto.
    * g10/mainproc.c (list_node): Remove printing of non-documented "rtv"
    lines.
    * g10/build-packet.c (build_packet_and_meta): New.
    (do_ring_trust): New.
    * g10/export.c (write_keyblock_to_output): Use build_packet_and_meta
    in backup mode.
    (do_export_one_keyblock): Ditto.
    * g10/import.c (read_block): Add arg WITH_META.  Skip ring trust
    packets if that ism not set.
    (import): Call read_block WITH_META in restore mode.
    * g10/keydb.h (KEYSRC_UNKNOWN, KEYSRC_FILE, KEYSRC_KS, KEYSRC_PREF_KS)
    (KEYSRC_WKD, KEYSRC_WKD_SD, KEYSRC_DANE): New constants.  They are not
    yet used, though.
    * g10/keydb.c (parse_keyblock_image): Allow ring trust packets.
    (build_keyblock_image): Ditto.  Use build_packet_and_meta.
    * g10/keyring.c (keyring_get_keyblock): Remove specila treatment of
    ring trust packets.
    (write_keyblock): Use build_packet_and_meta.  Remove special treatment
    of ring trust packets and initialization of the signature caches.
    --
    
    This patch introduced the framework to store meta data for keys and
    user ids in the keyrings/keyboxes.  Ring trust packets are
    implementation defined and have always been used in gpg to cache the
    signature verification status.
    
    Ring trust packets are only exported with the export option "backup"
    and only imported with the import option "restore".
    
    The new code uses a cleaner way to handle the ring trust packets: When
    the parser reads a ring trust packet and the previously read packet
    matches the type of that ring trust packet, the information is stored
    in that previously read packet (signature, user id, or primary key)
    and the next packet is read immediately.  Thus only the parser sees
    the ring trust packets.  Ring trust packets are written by using the
    new function build_packet_and_meta instead of build_packet.  That
    function writes a ring trust packet when the needed information is
    available.
    
    As a side-effect of this patch the signature status cache works again
    and "gpg --check-sigs" is thus much faster.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/doc/DETAILS b/doc/DETAILS
index 83d9fea..1624315 100644
--- a/doc/DETAILS
+++ b/doc/DETAILS
@@ -1311,6 +1311,43 @@ CREATE TABLE signatures (
   S2K Specifier with an offset of 1000.
 
 
+* Format of the OpenPGP TRUST packet
+
+  According to RFC4880 (5.10), the trust packet (aka ring trust) is
+  only used within keyrings and contains data that records the user's
+  specifications of which key holds trusted introducers.  The RFC also
+  states that the format of this packet is implementation defined and
+  SHOULD NOT be emitted to output streams or should be ignored on
+  import.  GnuPG uses this packet in several additional ways:
+
+  - 1 octet :: Trust-Value (only used by Subtype SIG)
+  - 1 octet :: Signature-Cache (only used by Subtype SIG; value must
+               be less than 128)
+  - 3 octets :: Fixed value: "gpg"
+  - 1 octet  :: Subtype
+               - 0 :: Signature cache (SIG)
+               - 1 :: Key source on the primary key (KEY)
+               - 2 :: Key source on a user id (UID)
+  - 1 octet :: Key Source; i.e. the origin of the key:
+               - 0 :: Unknown source.
+               - 1 :: Direct import from a file.
+               - 2 :: Public keyserver.
+               - 3 :: Preferred keysrver.
+               - 4 :: Web Key Directory.
+               - 5 :: Web Key Directory via sub-domain.
+               - 6 :: OpenPGP DANE.
+  - 4 octets :: Time of last update.  This is a a four-octet scalar
+                with the seconds since Epoch.
+  - 1 octet  :: Scalar with the length of the following field.
+  - N octets :: String with the URL of the source.  This may be a
+                zero-length string.
+
+  If the packets contains only two octets a Subtype of 0 is assumed;
+  this is the only format recognized by GnuPG versions < 2.1.18.
+  Trust-Value and Signature-Cache must be zero for all subtypes other
+  than SIG.
+
+
 * Keyserver helper message format
 
   *This information is obsolete*
diff --git a/g10/build-packet.c b/g10/build-packet.c
index 512e55c..60e7d45 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -33,6 +33,7 @@
 #include "options.h"
 #include "../common/host2net.h"
 
+static gpg_error_t do_ring_trust (iobuf_t out, PKT_ring_trust *rt);
 static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
 static int do_key (iobuf_t out, int ctb, PKT_public_key *pk);
 static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
@@ -76,14 +77,11 @@ ctb_pkttype (int ctb)
     return (ctb & ((1 << 6) - 1)) >> 2;
 }
 
-/****************
- * Build a packet and write it to INP
- * Returns: 0 := okay
- *	   >0 := error
- * Note: Caller must free the packet
- */
+
+/* Build a packet and write it to the stream OUT.
+ * Returns: 0 on success or on an error code.  */
 int
-build_packet( IOBUF out, PACKET *pkt )
+build_packet (IOBUF out, PACKET *pkt)
 {
   int rc = 0;
   int new_ctb = 0;
@@ -170,7 +168,7 @@ build_packet( IOBUF out, PACKET *pkt )
       rc = do_onepass_sig (out, ctb, pkt->pkt.onepass_sig);
       break;
     case PKT_RING_TRUST:
-      /* Ignore it (keyring.c does write it directly)  */
+      /* Ignore it (only written by build_packet_and_meta)  */
       break;
     case PKT_MDC:
       /* We write it directly, so we should never see it here. */
@@ -183,6 +181,62 @@ build_packet( IOBUF out, PACKET *pkt )
 }
 
 
+/* Build a packet and write it to the stream OUT.  This variant also
+ * writes the meta data using ring tyrust packets.  Returns: 0 on
+ * success or on aerror code.  */
+gpg_error_t
+build_packet_and_meta (iobuf_t out, PACKET *pkt)
+{
+  gpg_error_t err;
+  PKT_ring_trust rt = {0};
+
+  err = build_packet (out, pkt);
+  if (err)
+    ;
+  else if (pkt->pkttype == PKT_SIGNATURE)
+    {
+      PKT_signature *sig = pkt->pkt.signature;
+
+      rt.subtype = RING_TRUST_SIG;
+      /* Note: trustval is not yet used.  */
+      if (sig->flags.checked)
+        {
+          rt.sigcache = 1;
+          if (sig->flags.valid)
+            rt.sigcache |= 2;
+        }
+      err = do_ring_trust (out, &rt);
+    }
+  else if (pkt->pkttype == PKT_USER_ID
+           || pkt->pkttype == PKT_ATTRIBUTE)
+    {
+      PKT_user_id *uid = pkt->pkt.user_id;
+
+      rt.subtype = RING_TRUST_UID;
+      rt.keysrc = uid->keysrc;
+      rt.keyupdate = uid->keyupdate;
+      rt.url = uid->updateurl;
+      err = do_ring_trust (out, &rt);
+      rt.url = NULL;
+    }
+  else if (pkt->pkttype == PKT_PUBLIC_KEY
+           || pkt->pkttype == PKT_SECRET_KEY)
+    {
+      PKT_public_key *pk = pkt->pkt.public_key;
+
+      rt.subtype = RING_TRUST_KEY;
+      rt.keysrc = pk->keysrc;
+      rt.keyupdate = pk->keyupdate;
+      rt.url = pk->updateurl;
+      err = do_ring_trust (out, &rt);
+      rt.url = NULL;
+
+    }
+
+  return err;
+}
+
+
 /*
  * Write the mpi A to OUT.
  */
@@ -320,6 +374,38 @@ write_fake_data (IOBUF out, gcry_mpi_t a)
 }
 
 
+/* Write a ring trust meta packet.  */
+static gpg_error_t
+do_ring_trust (iobuf_t out, PKT_ring_trust *rt)
+{
+  unsigned int namelen = 0;
+  unsigned int pktlen = 6;
+
+  if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID)
+    {
+      if (rt->url)
+        namelen = strlen (rt->url);
+      pktlen += 1 + 4 + 1 + namelen;
+    }
+
+  write_header (out, (0x80 | ((PKT_RING_TRUST & 15)<<2)), pktlen);
+  iobuf_put (out, rt->trustval);
+  iobuf_put (out, rt->sigcache);
+  iobuf_write (out, "gpg", 3);
+  iobuf_put (out, rt->subtype);
+  if (rt->subtype == RING_TRUST_KEY || rt->subtype == RING_TRUST_UID)
+    {
+      iobuf_put (out, rt->keysrc);
+      write_32 (out, rt->keyupdate);
+      iobuf_put (out, namelen);
+      if (namelen)
+        iobuf_write (out, rt->url, namelen);
+    }
+
+  return 0;
+}
+
+
 /* Serialize the user id (RFC 4880, Section 5.11) or the user
  * attribute UID (Section 5.12) and write it to OUT.
  *
diff --git a/g10/export.c b/g10/export.c
index 5b0c81d..e2adcc4 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -1284,14 +1284,17 @@ write_keyblock_to_output (kbnode_t keyblock, int with_armor,
     {
       if (is_deleted_kbnode (node))
         continue;
-      if (node->pkt->pkttype == PKT_RING_TRUST && !(options & EXPORT_BACKUP))
-        continue;
+      if (node->pkt->pkttype == PKT_RING_TRUST)
+        continue; /* Skip - they should not be here anyway.  */
 
       if (!pk && (node->pkt->pkttype == PKT_PUBLIC_KEY
                   || node->pkt->pkttype == PKT_SECRET_KEY))
         pk = node->pkt->pkt.public_key;
 
-      err = build_packet (out_help? out_help : out, node->pkt);
+      if ((options & EXPORT_BACKUP))
+        err = build_packet_and_meta (out_help? out_help : out, node->pkt);
+      else
+        err = build_packet (out_help? out_help : out, node->pkt);
       if (err)
         {
           log_error ("build_packet(%d) failed: %s\n",
@@ -1555,9 +1558,8 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
       if (node->pkt->pkttype == PKT_COMMENT)
         continue;
 
-      /* Make sure that ring_trust packets are only exported in backup
-       * mode. */
-      if (node->pkt->pkttype == PKT_RING_TRUST && !(options & EXPORT_BACKUP))
+      /* Skip ring trust packets - they should not ne here anyway.  */
+      if (node->pkt->pkttype == PKT_RING_TRUST)
         continue;
 
       /* If exact is set, then we only export what was requested
@@ -1723,7 +1725,10 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
                     ski->iv[ski->ivlen] = xtoi_2 (s);
                 }
 
-              err = build_packet (out, node->pkt);
+              if ((options & EXPORT_BACKUP))
+                err = build_packet_and_meta (out, node->pkt);
+              else
+                err = build_packet (out, node->pkt);
               if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
                 {
                   stats->exported++;
@@ -1744,7 +1749,10 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
                 }
               else
                 {
-                  err = build_packet (out, node->pkt);
+                  if ((options & EXPORT_BACKUP))
+                    err = build_packet_and_meta (out, node->pkt);
+                  else
+                    err = build_packet (out, node->pkt);
                   if (node->pkt->pkttype == PKT_PUBLIC_KEY)
                     {
                       stats->exported++;
@@ -1775,7 +1783,10 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
         }
       else /* Not secret or common packets.  */
         {
-          err = build_packet (out, node->pkt);
+          if ((options & EXPORT_BACKUP))
+            err = build_packet_and_meta (out, node->pkt);
+          else
+            err = build_packet (out, node->pkt);
           if (!err && node->pkt->pkttype == PKT_PUBLIC_KEY)
             {
               stats->exported++;
diff --git a/g10/free-packet.c b/g10/free-packet.c
index 535a17f..c144246 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -127,6 +127,11 @@ release_public_key_parts (PKT_public_key *pk)
       xfree (pk->serialno);
       pk->serialno = NULL;
     }
+  if (pk->updateurl)
+    {
+      xfree (pk->updateurl);
+      pk->updateurl = NULL;
+    }
 }
 
 
@@ -314,6 +319,7 @@ free_user_id (PKT_user_id *uid)
   free_attributes(uid);
   xfree (uid->prefs);
   xfree (uid->namehash);
+  xfree (uid->updateurl);
   xfree (uid->mbox);
   xfree (uid);
 }
diff --git a/g10/import.c b/g10/import.c
index 3321a7e..d43b2a8 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -97,8 +97,8 @@ static int import (ctrl_t ctrl,
                    IOBUF inp, const char* fname, struct import_stats_s *stats,
 		   unsigned char **fpr, size_t *fpr_len, unsigned int options,
 		   import_screener_t screener, void *screener_arg);
-static int read_block (IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root,
-                       int *r_v3keys);
+static int read_block (IOBUF a, int with_meta,
+                       PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys);
 static void revocation_present (ctrl_t ctrl, kbnode_t keyblock);
 static int import_one (ctrl_t ctrl,
                        kbnode_t keyblock,
@@ -333,7 +333,7 @@ read_key_from_file (ctrl_t ctrl, const char *fname, kbnode_t *r_keyblock)
   }
 
   /* Read the first non-v3 keyblock.  */
-  while (!(err = read_block (inp, &pending_pkt, &keyblock, &v3keys)))
+  while (!(err = read_block (inp, 0, &pending_pkt, &keyblock, &v3keys)))
     {
       if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
         break;
@@ -563,7 +563,8 @@ import (ctrl_t ctrl, IOBUF inp, const char* fname,struct import_stats_s *stats,
       release_armor_context (afx);
     }
 
-  while (!(rc = read_block (inp, &pending_pkt, &keyblock, &v3keys)))
+  while (!(rc = read_block (inp, !!(options & IMPORT_RESTORE),
+                            &pending_pkt, &keyblock, &v3keys)))
     {
       stats->v3keys += v3keys;
       if (keyblock->pkt->pkttype == PKT_PUBLIC_KEY)
@@ -637,7 +638,7 @@ import_old_secring (ctrl_t ctrl, const char *fname)
 
   getkey_disable_caches();
   stats = import_new_stats_handle ();
-  while (!(err = read_block (inp, &pending_pkt, &keyblock, &v3keys)))
+  while (!(err = read_block (inp, 0, &pending_pkt, &keyblock, &v3keys)))
     {
       if (keyblock->pkt->pkttype == PKT_SECRET_KEY)
         err = import_secret_one (ctrl, keyblock, stats, 1, 0, 1,
@@ -752,14 +753,15 @@ valid_keyblock_packet (int pkttype)
 
 /****************
  * Read the next keyblock from stream A.
- * PENDING_PKT should be initialzed to NULL
- * and not changed by the caller.
+ * Meta data (ring trust packets) are only considered of WITH_META is set.
+ * PENDING_PKT should be initialzed to NULL and not changed by the caller.
  * Return: 0 = okay, -1 no more blocks or another errorcode.
  *         The int at at R_V3KEY counts the number of unsupported v3
  *         keyblocks.
  */
 static int
-read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
+read_block( IOBUF a, int with_meta,
+            PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
 {
   int rc;
   struct parse_packet_ctx_s parsectx;
@@ -781,6 +783,8 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
   pkt = xmalloc (sizeof *pkt);
   init_packet (pkt);
   init_parse_packet (&parsectx, a);
+  if (!with_meta)
+    parsectx.skip_meta = 1;
   in_v3key = 0;
   while ((rc=parse_packet (&parsectx, pkt)) != -1)
     {
diff --git a/g10/keydb.c b/g10/keydb.c
index 1bbda35..67957f8 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -1202,6 +1202,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
         case PKT_USER_ID:
         case PKT_ATTRIBUTE:
         case PKT_SIGNATURE:
+        case PKT_RING_TRUST:
           break; /* Allowed per RFC.  */
 
         default:
@@ -1458,14 +1459,13 @@ build_keyblock_image (kbnode_t keyblock, iobuf_t *r_iobuf, u32 **r_sigstatus)
         case PKT_SIGNATURE:
         case PKT_USER_ID:
         case PKT_ATTRIBUTE:
-          /* Note that we don't want the ring trust packets.  They are
-             not useful. */
+        case PKT_RING_TRUST:
           break;
         default:
           continue;
         }
 
-      err = build_packet (iobuf, node->pkt);
+      err = build_packet_and_meta (iobuf, node->pkt);
       if (err)
         {
           iobuf_close (iobuf);
diff --git a/g10/keydb.h b/g10/keydb.h
index 6f57583..2de52d5 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -119,6 +119,19 @@ union pref_hint
 };
 
 
+/* Constants to describe from where a key was fetched or updated.  */
+enum
+  {
+    KEYSRC_UNKNOWN = 0,
+    KEYSRC_FILE    = 1, /* Direct import from a file.  */
+    KEYSRC_KS      = 2, /* Public keyserver.    */
+    KEYSRC_PREF_KS = 3, /* Preferred keysrver.  */
+    KEYSRC_WKD     = 4, /* Web Key Directory.   */
+    KEYSRC_WKD_SD  = 5, /* Web Key Directory but from a sub domain.  */
+    KEYSRC_DANE    = 6  /* OpenPGP DANE.  */
+  };
+
+
 /*-- keydb.c --*/
 
 #define KEYDB_RESOURCE_FLAG_PRIMARY  2  /* The primary resource.  */
diff --git a/g10/keyring.c b/g10/keyring.c
index 2210df9..e7ebbb3 100644
--- a/g10/keyring.c
+++ b/g10/keyring.c
@@ -473,29 +473,6 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
         }
 
         in_cert = 1;
-        if (pkt->pkttype == PKT_RING_TRUST)
-          {
-            /*(this code is duplicated after the loop)*/
-            if ( lastnode
-                 && lastnode->pkt->pkttype == PKT_SIGNATURE
-                 && (pkt->pkt.ring_trust->sigcache & 1) ) {
-                /* This is a ring trust packet with a checked signature
-                 * status cache following directly a signature paket.
-                 * Set the cache status into that signature packet.  */
-                PKT_signature *sig = lastnode->pkt->pkt.signature;
-
-                sig->flags.checked = 1;
-                sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
-            }
-            /* Reset LASTNODE, so that we set the cache status only from
-             * the ring trust packet immediately following a signature. */
-            lastnode = NULL;
-	    free_packet(pkt, &parsectx);
-	    init_packet(pkt);
-	    continue;
-          }
-
-
         node = lastnode = new_kbnode (pkt);
         if (!keyblock)
           keyblock = node;
@@ -531,16 +508,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     if (rc || !ret_kb)
 	release_kbnode (keyblock);
     else {
-        /*(duplicated from the loop body)*/
-        if ( pkt && pkt->pkttype == PKT_RING_TRUST
-             && lastnode
-             && lastnode->pkt->pkttype == PKT_SIGNATURE
-             && (pkt->pkt.ring_trust->sigcache & 1) ) {
-            PKT_signature *sig = lastnode->pkt->pkt.signature;
-            sig->flags.checked = 1;
-            sig->flags.valid = !!(pkt->pkt.ring_trust->sigcache & 2);
-        }
-	*ret_kb = keyblock;
+        *ret_kb = keyblock;
     }
     free_packet (pkt, &parsectx);
     deinit_parse_packet (&parsectx);
@@ -1420,36 +1388,12 @@ write_keyblock (IOBUF fp, KBNODE keyblock)
 
   while ( (node = walk_kbnode (keyblock, &kbctx, 0)) )
     {
-      if (node->pkt->pkttype == PKT_RING_TRUST)
-        continue; /* we write it later on our own */
-
-      if ( (rc = build_packet (fp, node->pkt) ))
+      if ( (rc = build_packet_and_meta (fp, node->pkt) ))
         {
           log_error ("build_packet(%d) failed: %s\n",
                      node->pkt->pkttype, gpg_strerror (rc) );
           return rc;
         }
-      if (node->pkt->pkttype == PKT_SIGNATURE)
-        { /* always write a signature cache packet */
-          PKT_signature *sig = node->pkt->pkt.signature;
-          unsigned int cacheval = 0;
-
-          if (sig->flags.checked)
-            {
-              cacheval |= 1;
-              if (sig->flags.valid)
-                cacheval |= 2;
-            }
-          iobuf_put (fp, 0xb0); /* old style packet 12, 1 byte len*/
-          iobuf_put (fp, 2);    /* 2 bytes */
-          iobuf_put (fp, 0);    /* unused */
-          if (iobuf_put (fp, cacheval))
-            {
-              rc = gpg_error_from_syserror ();
-              log_error ("writing sigcache packet failed\n");
-              return rc;
-            }
-        }
     }
   return 0;
 }
@@ -1640,6 +1584,7 @@ keyring_rebuild_cache (void *token,int noisy)
   return rc;
 }
 
+
 

 /****************
  * Perform insert/delete/update operation.
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 8581104..7b2c456 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1046,13 +1046,6 @@ list_node (CTX c, kbnode_t node)
       else if ((pk->flags.primary && opt.fingerprint) || opt.fingerprint > 1)
         print_fingerprint (NULL, pk, 0);
 
-      if (opt.with_colons)
-        {
-          if (node->next && node->next->pkt->pkttype == PKT_RING_TRUST)
-            es_printf ("rtv:1:%u:\n",
-                       node->next->pkt->pkt.ring_trust->trustval);
-        }
-
       if (pk->flags.primary)
         {
           int kl = opt.keyid_format == KF_NONE? 0 : keystrlen ();
@@ -1077,14 +1070,6 @@ list_node (CTX c, kbnode_t node)
                   if (opt.with_colons)
                     es_putc (':', es_stdout);
                   es_putc ('\n', es_stdout);
-                  if (opt.with_colons
-                      && node->next
-                      && node->next->pkt->pkttype == PKT_RING_TRUST)
-                    {
-                      es_printf ("rtv:2:%u:\n",
-                                 node->next->pkt->pkt.ring_trust?
-                                 node->next->pkt->pkt.ring_trust->trustval : 0);
-                    }
 		}
               else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
                 {
diff --git a/g10/packet.h b/g10/packet.h
index ad6f317..b23298a 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -283,20 +283,25 @@ typedef struct
   u32 expiredate;       /* expires at this date or 0 if not at all */
   prefitem_t *prefs;    /* list of preferences (may be NULL)*/
   u32 created;          /* according to the self-signature */
+  u32 keyupdate;        /* From the ring trust packet.  */
+  char *updateurl;      /* NULL or the URL of the last update origin.  */
+  byte keysrc;          /* From the ring trust packet.  */
   byte selfsigversion;
   struct
   {
     unsigned int mdc:1;
     unsigned int ks_modify:1;
     unsigned int compacted:1;
-    unsigned int primary:2;       /* 2 if set via the primary flag, 1 if calculated */
+    unsigned int primary:2; /* 2 if set via the primary flag, 1 if calculated */
     unsigned int revoked:1;
     unsigned int expired:1;
   } flags;
+
   char *mbox;   /* NULL or the result of mailbox_from_userid.  */
+
   /* The text contained in the user id packet, which is normally the
-     name and email address of the key holder (See RFC 4880 5.11).
-     (Serialized.). For convenience an extra Nul is always appended.  */
+   * name and email address of the key holder (See RFC 4880 5.11).
+   * (Serialized.). For convenience an extra Nul is always appended.  */
   char name[1];
 } PKT_user_id;
 
@@ -402,6 +407,9 @@ typedef struct
   u32     trust_timestamp;
   byte    trust_depth;
   byte    trust_value;
+  byte    keysrc;         /* From the ring trust packet.  */
+  u32     keyupdate;      /* From the ring trust packet.  */
+  char    *updateurl;     /* NULL or the URL of the last update origin.  */
   const byte *trust_regexp;
   char    *serialno;      /* Malloced hex string or NULL if it is
                              likely not on a card.  See also
@@ -474,11 +482,28 @@ typedef struct {
     byte hash[20];
 } PKT_mdc;
 
+
+/* Subtypes for the ring trust packet.  */
+#define RING_TRUST_SIG 0  /* The classical signature cache.  */
+#define RING_TRUST_KEY 1  /* A KEYSRC on a primary key.      */
+#define RING_TRUST_UID 2  /* A KEYSRC on a user id.          */
+
+/* The local only ring trust packet which OpenPGP declares as
+ * implementation defined.  GnuPG uses this to cache signature
+ * verification status and since 2.1.18 also to convey information
+ * about the origin of a key.  Note that this packet is not part
+ * struct packet_struct becuase we use it only local in the packet
+ * parser and builder. */
 typedef struct {
-    unsigned int trustval;
-    unsigned int sigcache;
+  unsigned int trustval;
+  unsigned int sigcache;
+  unsigned char subtype; /* The subtype of this ring trust packet.   */
+  unsigned char keysrc;  /* The origin of the key (KEYSRC_*).        */
+  u32 keyupdate;         /* The wall time the key was last updated.  */
+  char *url;             /* NULL or the URL of the source.           */
 } PKT_ring_trust;
 
+
 /* A plaintext packet (see RFC 4880, 5.9).  */
 typedef struct {
   /* The length of data in BUF or 0 if unknown.  */
@@ -519,7 +544,6 @@ struct packet_struct {
 	PKT_compressed	*compressed;	/* PKT_COMPRESSED */
 	PKT_encrypted	*encrypted;	/* PKT_ENCRYPTED[_MDC] */
 	PKT_mdc 	*mdc;		/* PKT_MDC */
-	PKT_ring_trust	*ring_trust;	/* PKT_RING_TRUST */
 	PKT_plaintext	*plaintext;	/* PKT_PLAINTEXT */
         PKT_gpg_control *gpg_control;   /* PKT_GPG_CONTROL */
     } pkt;
@@ -599,6 +623,7 @@ struct parse_packet_ctx_s
   iobuf_t inp;       /* The input stream with the packets.  */
   PACKET *last_pkt;  /* The last parsed packet.  */
   int free_last_pkt; /* Indicates that LAST_PKT must be freed.  */
+  int skip_meta;     /* Skip right trust packets.  */
 };
 typedef struct parse_packet_ctx_s *parse_packet_ctx_t;
 
@@ -606,6 +631,7 @@ typedef struct parse_packet_ctx_s *parse_packet_ctx_t;
     (a)->inp = (i);                 \
     (a)->last_pkt = NULL;           \
     (a)->free_last_pkt = 0;         \
+    (a)->skip_meta = 0;             \
   } while (0)
 
 #define deinit_parse_packet(a) do { \
@@ -786,7 +812,8 @@ PACKET *create_gpg_control ( ctrlpkttype_t type,
                              size_t datalen );
 
 /*-- build-packet.c --*/
-int build_packet( iobuf_t inp, PACKET *pkt );
+int build_packet (iobuf_t out, PACKET *pkt);
+gpg_error_t build_packet_and_meta (iobuf_t out, PACKET *pkt);
 gpg_error_t gpg_mpi_write (iobuf_t out, gcry_mpi_t a);
 gpg_error_t gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a);
 u32 calc_packet_length( PACKET *pkt );
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index ab273a5..df04fbc 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -74,8 +74,8 @@ static int parse_attribute (IOBUF inp, int pkttype, unsigned long pktlen,
 			    PACKET * packet);
 static int parse_comment (IOBUF inp, int pkttype, unsigned long pktlen,
 			  PACKET * packet);
-static void parse_trust (IOBUF inp, int pkttype, unsigned long pktlen,
-			 PACKET * packet);
+static gpg_error_t parse_ring_trust (parse_packet_ctx_t ctx,
+                                     unsigned long pktlen);
 static int parse_plaintext (IOBUF inp, int pkttype, unsigned long pktlen,
 			    PACKET * packet, int new_ctb, int partial);
 static int parse_compressed (IOBUF inp, int pkttype, unsigned long pktlen,
@@ -542,6 +542,7 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
   *skip = 0;
   inp = ctx->inp;
 
+ again:
   log_assert (!pkt->pkt.generic);
   if (retpos || list_mode)
     {
@@ -800,8 +801,11 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
       rc = parse_comment (inp, pkttype, pktlen, pkt);
       break;
     case PKT_RING_TRUST:
-      parse_trust (inp, pkttype, pktlen, pkt);
-      rc = 0;
+      {
+        rc = parse_ring_trust (ctx, pktlen);
+        if (!rc)
+          goto again; /* Directly read the next packet.  */
+      }
       break;
     case PKT_PLAINTEXT:
       rc = parse_plaintext (inp, pkttype, pktlen, pkt, new_ctb, partial);
@@ -2873,42 +2877,164 @@ parse_comment (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet)
 }
 
 
-static void
-parse_trust (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * pkt)
+/* Parse a ring trust packet RFC4880 (5.10).
+ *
+ * This parser is special in that the packet is not stored as a packet
+ * but its content is merged into the previous packet.  */
+static gpg_error_t
+parse_ring_trust (parse_packet_ctx_t ctx, unsigned long pktlen)
 {
+  gpg_error_t err;
+  iobuf_t inp = ctx->inp;
+  PKT_ring_trust rt = {0};
   int c;
+  int not_gpg = 0;
 
-  (void) pkttype;
+  if (!pktlen)
+    {
+      if (list_mode)
+	es_fprintf (listfp, ":trust packet: empty\n");
+      err = 0;
+      goto leave;
+    }
 
-  pkt->pkt.ring_trust = xmalloc (sizeof *pkt->pkt.ring_trust);
+  c = iobuf_get_noeof (inp);
+  pktlen--;
+  rt.trustval = c;
   if (pktlen)
     {
-      c = iobuf_get_noeof (inp);
+      if (!c)
+        {
+          c = iobuf_get_noeof (inp);
+          /* We require that bit 7 of the sigcache is 0 (easier
+           * eof handling).  */
+          if (!(c & 0x80))
+            rt.sigcache = c;
+        }
+      else
+        iobuf_get_noeof (inp);  /* Dummy read.  */
       pktlen--;
-      pkt->pkt.ring_trust->trustval = c;
-      pkt->pkt.ring_trust->sigcache = 0;
-      if (!c && pktlen == 1)
-	{
-	  c = iobuf_get_noeof (inp);
-	  pktlen--;
-	  /* We require that bit 7 of the sigcache is 0 (easier eof
-             handling).  */
-	  if (!(c & 0x80))
-	    pkt->pkt.ring_trust->sigcache = c;
-	}
-      if (list_mode)
-	es_fprintf (listfp, ":trust packet: flag=%02x sigcache=%02x\n",
-                    pkt->pkt.ring_trust->trustval,
-                    pkt->pkt.ring_trust->sigcache);
     }
-  else
+
+  /* Next is the optional subtype.  */
+  if (pktlen > 3)
     {
-      pkt->pkt.ring_trust->trustval = 0;
-      pkt->pkt.ring_trust->sigcache = 0;
-      if (list_mode)
-	es_fprintf (listfp, ":trust packet: empty\n");
+      char tmp[4];
+      tmp[0] = iobuf_get_noeof (inp);
+      tmp[1] = iobuf_get_noeof (inp);
+      tmp[2] = iobuf_get_noeof (inp);
+      tmp[3] = iobuf_get_noeof (inp);
+      pktlen -= 4;
+      if (!memcmp (tmp, "gpg", 3))
+        rt.subtype = tmp[3];
+      else
+        not_gpg = 1;
     }
+  /* If it is a key or uid subtype read the remaining data.  */
+  if ((rt.subtype == RING_TRUST_KEY || rt.subtype == RING_TRUST_UID)
+      && pktlen >= 6 )
+    {
+      int i;
+      unsigned int namelen;
+
+      rt.keysrc = iobuf_get_noeof (inp);
+      pktlen--;
+      rt.keyupdate = read_32 (inp);
+      pktlen -= 4;
+      namelen = iobuf_get_noeof (inp);
+      pktlen--;
+      if (namelen && pktlen)
+        {
+          rt.url = xtrymalloc (namelen + 1);
+          if (rt.url)
+            {
+              err = gpg_error_from_syserror ();
+              goto leave;
+            }
+          for (i = 0; pktlen && i < namelen; pktlen--, i++)
+            rt.url[i] = iobuf_get_noeof (inp);
+          rt.url[i] = 0;
+        }
+    }
+
+  if (list_mode)
+    {
+      if (rt.subtype == RING_TRUST_SIG)
+        es_fprintf (listfp, ":trust packet: sig flag=%02x sigcache=%02x\n",
+                    rt.trustval, rt.sigcache);
+      else if (rt.subtype == RING_TRUST_UID || rt.subtype == RING_TRUST_KEY)
+        {
+          unsigned char *p;
+
+          es_fprintf (listfp, ":trust packet: %s upd=%lu src=%d%s",
+                      (rt.subtype == RING_TRUST_UID? "uid" : "key"),
+                      (unsigned long)rt.keyupdate,
+                      rt.keysrc,
+                      (rt.url? " url=":""));
+          if (rt.url)
+            {
+              for (p = rt.url; *p; p++)
+                {
+                  if (*p >= ' ' && *p <= 'z')
+                    es_putc (*p, listfp);
+                  else
+                    es_fprintf (listfp, "\\x%02x", *p);
+                }
+            }
+          es_putc ('\n', listfp);
+        }
+      else if (not_gpg)
+        es_fprintf (listfp, ":trust packet: not created by gpg\n");
+      else
+        es_fprintf (listfp, ":trust packet: subtype=%02x\n",
+                    rt.subtype);
+    }
+
+  /* Now transfer the data to the respective packet.  Do not do this
+   * if SKIP_META is set.  */
+  if (!ctx->last_pkt || ctx->skip_meta)
+    ;
+  else if (rt.subtype == RING_TRUST_SIG
+           && ctx->last_pkt->pkttype == PKT_SIGNATURE)
+    {
+      PKT_signature *sig = ctx->last_pkt->pkt.signature;
+
+      if ((rt.sigcache & 1))
+        {
+          sig->flags.checked = 1;
+          sig->flags.valid = !!(rt.sigcache & 2);
+        }
+    }
+  else if (rt.subtype == RING_TRUST_UID
+           && (ctx->last_pkt->pkttype == PKT_USER_ID
+               || ctx->last_pkt->pkttype == PKT_ATTRIBUTE))
+    {
+      PKT_user_id *uid = ctx->last_pkt->pkt.user_id;
+
+      uid->keysrc = rt.keysrc;
+      uid->keyupdate = rt.keyupdate;
+      uid->updateurl = rt.url;
+      rt.url = NULL;
+    }
+  else if (rt.subtype == RING_TRUST_KEY
+           && (ctx->last_pkt->pkttype == PKT_PUBLIC_KEY
+               || ctx->last_pkt->pkttype == PKT_SECRET_KEY))
+    {
+      PKT_public_key *pk = ctx->last_pkt->pkt.public_key;
+
+      pk->keysrc = rt.keysrc;
+      pk->keyupdate = rt.keyupdate;
+      pk->updateurl = rt.url;
+      rt.url = NULL;
+    }
+
+  err = 0;
+
+ leave:
+  xfree (rt.url);
+  free_packet (NULL, ctx); /* This sets ctx->last_pkt to NULL.  */
   iobuf_skip_rest (inp, pktlen, 0);
+  return err;
 }
 
 

commit afa86809087909a8ba2f9356588bf90cc923529c
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Mar 29 11:57:40 2017 +0200

    gpg: Extend free_packet to handle a packet parser context.
    
    * g10/packet.h (struct parse_packet_ctx_s): Add fields LAST_PKT and
    FREE_LAST_PKT.
    (init_parse_packet): Clear them.
    (deinit_parse_packet): New macro.  Change all users if
    init_parse_packet to also call this macro.
    * g10/free-packet.c (free_packet): Add arg PARSECTX and handle shallow
    packet copies in the context.  Change all callers.
    * g10/parse-packet.c (parse): Store certain packets in the parse
    context.
    --
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/g10/encrypt.c b/g10/encrypt.c
index 0a892c2..a79a470 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -394,7 +394,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
     }
   if (pt)
     pt->buf = NULL;
-  free_packet (&pkt);
+  free_packet (&pkt, NULL);
   xfree (cfx.dek);
   xfree (s2k);
   release_armor_context (afx);
@@ -755,7 +755,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
     }
   if (pt)
     pt->buf = NULL;
-  free_packet (&pkt);
+  free_packet (&pkt, NULL);
   xfree (cfx.dek);
   xfree (symkey_dek);
   xfree (symkey_s2k);
diff --git a/g10/free-packet.c b/g10/free-packet.c
index 4cf80a4..535a17f 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -394,18 +394,40 @@ free_plaintext( PKT_plaintext *pt )
   xfree (pt);
 }
 
+
 /****************
  * Free the packet in PKT.
  */
 void
-free_packet (PACKET *pkt)
+free_packet (PACKET *pkt, parse_packet_ctx_t parsectx)
 {
   if (!pkt || !pkt->pkt.generic)
-    return;
+    {
+      if (parsectx && parsectx->last_pkt)
+        {
+          if (parsectx->free_last_pkt)
+            {
+              free_packet (parsectx->last_pkt, NULL);
+              parsectx->free_last_pkt = 0;
+            }
+          parsectx->last_pkt = NULL;
+        }
+      return;
+    }
 
   if (DBG_MEMORY)
     log_debug ("free_packet() type=%d\n", pkt->pkttype);
 
+  /* If we have a parser context holding PKT then do not free the
+   * packet but set a flag that the packet in the parser context is
+   * now a deep copy.  */
+  if (parsectx && parsectx->last_pkt == pkt && !parsectx->free_last_pkt)
+    {
+      parsectx->free_last_pkt = 1;
+      pkt->pkt.generic = NULL;
+      return;
+    }
+
   switch (pkt->pkttype)
     {
     case PKT_SIGNATURE:
diff --git a/g10/import.c b/g10/import.c
index 9aa6c8b..3321a7e 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -790,7 +790,7 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
         {
           in_v3key = 1;
           ++*r_v3keys;
-          free_packet (pkt);
+          free_packet (pkt, &parsectx);
           init_packet (pkt);
           continue;
         }
@@ -804,7 +804,7 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
               rc = GPG_ERR_INV_KEYRING;
               goto ready;
             }
-          free_packet( pkt );
+          free_packet (pkt, &parsectx);
           init_packet(pkt);
           continue;
 	}
@@ -812,7 +812,7 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
         if (in_v3key && !(pkt->pkttype == PKT_PUBLIC_KEY
                           || pkt->pkttype == PKT_SECRET_KEY))
           {
-	    free_packet( pkt );
+	    free_packet (pkt, &parsectx);
 	    init_packet(pkt);
 	    continue;
           }
@@ -843,7 +843,7 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
 		pkt->pkt.compressed->buf = NULL;
 		push_compress_filter2(a,cfx,pkt->pkt.compressed->algorithm,1);
 	      }
-	    free_packet( pkt );
+	    free_packet (pkt, &parsectx);
 	    init_packet(pkt);
 	    break;
 
@@ -851,7 +851,7 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
             /* Skip those packets unless we are in restore mode.  */
             if ((opt.import_options & IMPORT_RESTORE))
               goto x_default;
-	    free_packet( pkt );
+	    free_packet (pkt, &parsectx);
 	    init_packet(pkt);
             break;
 
@@ -887,7 +887,8 @@ read_block( IOBUF a, PACKET **pending_pkt, kbnode_t *ret_root, int *r_v3keys)
     release_kbnode( root );
   else
     *ret_root = root;
-  free_packet( pkt );
+  free_packet (pkt, &parsectx);
+  deinit_parse_packet (&parsectx);
   xfree( pkt );
   return rc;
 }
diff --git a/g10/kbnode.c b/g10/kbnode.c
index b8c31b7..c2aaacd 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -117,8 +117,8 @@ release_kbnode( KBNODE n )
     while( n ) {
 	n2 = n->next;
 	if( !is_cloned_kbnode(n) ) {
-	    free_packet( n->pkt );
-	    xfree( n->pkt );
+            free_packet (n->pkt, NULL);
+            xfree( n->pkt );
 	}
 	free_node( n );
 	n = n2;
@@ -288,7 +288,7 @@ commit_kbnode( KBNODE *root )
 	    else
 		nl->next = n->next;
 	    if( !is_cloned_kbnode(n) ) {
-		free_packet( n->pkt );
+                free_packet (n->pkt, NULL);
 		xfree( n->pkt );
 	    }
 	    free_node( n );
@@ -312,7 +312,7 @@ remove_kbnode( KBNODE *root, KBNODE node )
 	    else
 		nl->next = n->next;
 	    if( !is_cloned_kbnode(n) ) {
-		free_packet( n->pkt );
+                free_packet (n->pkt, NULL);
 		xfree( n->pkt );
 	    }
 	    free_node( n );
diff --git a/g10/keydb.c b/g10/keydb.c
index c0bc9f5..1bbda35 100644
--- a/g10/keydb.c
+++ b/g10/keydb.c
@@ -1180,7 +1180,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
     {
       if (gpg_err_code (err) == GPG_ERR_UNKNOWN_PACKET)
         {
-          free_packet (pkt);
+          free_packet (pkt, &parsectx);
           init_packet (pkt);
           continue;
 	}
@@ -1209,7 +1209,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
              the other GPG specific packets don't make sense either.  */
           log_error ("skipped packet of type %d in keybox\n",
                      (int)pkt->pkttype);
-          free_packet(pkt);
+          free_packet(pkt, &parsectx);
           init_packet(pkt);
           continue;
         }
@@ -1311,7 +1311,8 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
     release_kbnode (keyblock);
   else
     *r_keyblock = keyblock;
-  free_packet (pkt);
+  free_packet (pkt, &parsectx);
+  deinit_parse_packet (&parsectx);
   xfree (pkt);
   return err;
 }
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 76d1889..9a61126 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -2467,7 +2467,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 	    init_packet (pkt);
             init_parse_packet (&parsectx, a);
 	    err = parse_packet (&parsectx, pkt);
-	    iobuf_close (a);
+	    deinit_parse_packet (&parsectx);
+            iobuf_close (a);
 	    iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char *) fname);
 	    if (!err && pkt->pkttype != PKT_SECRET_KEY
 		&& pkt->pkttype != PKT_SECRET_SUBKEY)
@@ -2477,7 +2478,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                 tty_printf (_("Error reading backup key from '%s': %s\n"),
                             fname, gpg_strerror (err));
                 xfree (fname);
-                free_packet (pkt);
+                free_packet (pkt, NULL);
                 xfree (pkt);
                 break;
               }
@@ -5008,7 +5009,7 @@ menu_expire (kbnode_t pub_keyblock, int force_mainkey, u32 newexpiration)
 	      newpkt = xmalloc_clear (sizeof *newpkt);
 	      newpkt->pkttype = PKT_SIGNATURE;
 	      newpkt->pkt.signature = newsig;
-	      free_packet (node->pkt);
+	      free_packet (node->pkt, NULL);
 	      xfree (node->pkt);
 	      node->pkt = newpkt;
 	      sub_pk = NULL;
@@ -5114,7 +5115,7 @@ menu_changeusage (kbnode_t keyblock)
 	      newpkt = xmalloc_clear (sizeof *newpkt);
 	      newpkt->pkttype = PKT_SIGNATURE;
 	      newpkt->pkt.signature = newsig;
-	      free_packet (node->pkt);
+	      free_packet (node->pkt, NULL);
 	      xfree (node->pkt);
 	      node->pkt = newpkt;
 	      sub_pk = NULL;
@@ -5213,7 +5214,7 @@ menu_backsign (KBNODE pub_keyblock)
 	      newpkt = xmalloc_clear (sizeof (*newpkt));
 	      newpkt->pkttype = PKT_SIGNATURE;
 	      newpkt->pkt.signature = newsig;
-	      free_packet (sig_pk->pkt);
+	      free_packet (sig_pk->pkt, NULL);
 	      xfree (sig_pk->pkt);
 	      sig_pk->pkt = newpkt;
 
@@ -5371,7 +5372,7 @@ menu_set_primary_uid (KBNODE pub_keyblock)
 		      newpkt = xmalloc_clear (sizeof *newpkt);
 		      newpkt->pkttype = PKT_SIGNATURE;
 		      newpkt->pkt.signature = newsig;
-		      free_packet (node->pkt);
+		      free_packet (node->pkt, NULL);
 		      xfree (node->pkt);
 		      node->pkt = newpkt;
 		      modified = 1;
@@ -5460,7 +5461,7 @@ menu_set_preferences (KBNODE pub_keyblock)
 		  newpkt = xmalloc_clear (sizeof *newpkt);
 		  newpkt->pkttype = PKT_SIGNATURE;
 		  newpkt->pkt.signature = newsig;
-		  free_packet (node->pkt);
+		  free_packet (node->pkt, NULL);
 		  xfree (node->pkt);
 		  node->pkt = newpkt;
 		  modified = 1;
@@ -5596,7 +5597,7 @@ menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
 		  newpkt = xmalloc_clear (sizeof *newpkt);
 		  newpkt->pkttype = PKT_SIGNATURE;
 		  newpkt->pkt.signature = newsig;
-		  free_packet (node->pkt);
+		  free_packet (node->pkt, NULL);
 		  xfree (node->pkt);
 		  node->pkt = newpkt;
 		  modified = 1;
@@ -5797,7 +5798,7 @@ menu_set_notation (const char *string, KBNODE pub_keyblock)
 		  newpkt = xmalloc_clear (sizeof *newpkt);
 		  newpkt->pkttype = PKT_SIGNATURE;
 		  newpkt->pkt.signature = newsig;
-		  free_packet (node->pkt);
+		  free_packet (node->pkt, NULL);
 		  xfree (node->pkt);
 		  node->pkt = newpkt;
 		  modified = 1;
diff --git a/g10/keygen.c b/g10/keygen.c
index 44f139a..78c35a2 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -867,7 +867,7 @@ make_backsig (PKT_signature *sig, PKT_public_key *pk,
       backsig_pkt.pkttype = PKT_SIGNATURE;
       backsig_pkt.pkt.signature = backsig;
       err = build_packet (backsig_out, &backsig_pkt);
-      free_packet (&backsig_pkt);
+      free_packet (&backsig_pkt, NULL);
       if (err)
 	log_error ("build_packet failed for backsig: %s\n", gpg_strerror (err));
       else
diff --git a/g10/keyring.c b/g10/keyring.c
index e4fc111..2210df9 100644
--- a/g10/keyring.c
+++ b/g10/keyring.c
@@ -415,7 +415,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
     while ((rc=parse_packet (&parsectx, pkt)) != -1) {
         hd->found.n_packets++;
         if (gpg_err_code (rc) == GPG_ERR_UNKNOWN_PACKET) {
-	    free_packet (pkt);
+	    free_packet (pkt, &parsectx);
 	    init_packet (pkt);
 	    continue;
 	}
@@ -461,7 +461,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
           default:
 	    log_error ("skipped packet of type %d in keyring\n",
                        (int)pkt->pkttype);
-	    free_packet(pkt);
+	    free_packet(pkt, &parsectx);
 	    init_packet(pkt);
 	    continue;
           }
@@ -490,7 +490,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
             /* Reset LASTNODE, so that we set the cache status only from
              * the ring trust packet immediately following a signature. */
             lastnode = NULL;
-	    free_packet(pkt);
+	    free_packet(pkt, &parsectx);
 	    init_packet(pkt);
 	    continue;
           }
@@ -542,7 +542,8 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
         }
 	*ret_kb = keyblock;
     }
-    free_packet (pkt);
+    free_packet (pkt, &parsectx);
+    deinit_parse_packet (&parsectx);
     xfree (pkt);
     iobuf_close(a);
 
@@ -1132,7 +1133,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       rc = search_packet (&parsectx, &pkt, &offset, need_uid);
       if (ignore_legacy && gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
         {
-          free_packet (&pkt);
+          free_packet (&pkt, &parsectx);
           continue;
         }
       if (rc)
@@ -1146,7 +1147,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         }
       if (initial_skip)
         {
-          free_packet (&pkt);
+          free_packet (&pkt, &parsectx);
           continue;
         }
 
@@ -1228,7 +1229,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
             goto found;
           }
 	}
-      free_packet (&pkt);
+      free_packet (&pkt, &parsectx);
       continue;
     found:
       if (rc)
@@ -1255,7 +1256,7 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
         }
       if (n == ndesc)
         goto real_found;
-      free_packet (&pkt);
+      free_packet (&pkt, &parsectx);
     }
  real_found:
   if (!rc)
@@ -1309,7 +1310,8 @@ keyring_search (KEYRING_HANDLE hd, KEYDB_SEARCH_DESC *desc,
       hd->current.error = rc;
     }
 
-  free_packet(&pkt);
+  free_packet (&pkt, &parsectx);
+  deinit_parse_packet (&parsectx);
   set_packet_list_mode(save_mode);
   return rc;
 }
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 30d9b18..8581104 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -358,7 +358,7 @@ proc_symkey_enc (CTX c, PACKET *pkt)
 
  leave:
   c->symkeys++;
-  free_packet (pkt);
+  free_packet (pkt, NULL);
 }
 
 
@@ -456,7 +456,7 @@ proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
         log_info (_("public key encrypted data: good DEK\n"));
     }
 
-  free_packet(pkt);
+  free_packet(pkt, NULL);
 }
 
 
@@ -657,7 +657,7 @@ proc_encrypted (CTX c, PACKET *pkt)
 
   xfree (c->dek);
   c->dek = NULL;
-  free_packet (pkt);
+  free_packet (pkt, NULL);
   c->last_was_session_key = 0;
   write_status (STATUS_END_DECRYPTION);
 }
@@ -774,7 +774,7 @@ proc_plaintext( CTX c, PACKET *pkt )
   if (rc)
     log_error ("handle plaintext failed: %s\n", gpg_strerror (rc));
 
-  free_packet(pkt);
+  free_packet (pkt, NULL);
   c->last_was_session_key = 0;
 
   /* We add a marker control packet instead of the plaintext packet.
@@ -837,7 +837,7 @@ proc_compressed (CTX c, PACKET *pkt)
   else if (rc)
     log_error ("uncompressing failed: %s\n", gpg_strerror (rc));
 
-  free_packet(pkt);
+  free_packet (pkt, NULL);
   c->last_was_session_key = 0;
   return rc;
 }
@@ -1348,7 +1348,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
       any_data = 1;
       if (rc)
         {
-          free_packet (pkt);
+          free_packet (pkt, &parsectx);
           /* Stop processing when an invalid packet has been encountered
            * but don't do so when we are doing a --list-packets.  */
           if (gpg_err_code (rc) == GPG_ERR_INV_PACKET
@@ -1466,7 +1466,7 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
           init_packet (pkt);
 	}
       else
-        free_packet(pkt);
+        free_packet (pkt, &parsectx);
     }
 
   if (rc == GPG_ERR_INV_PACKET)
@@ -1481,7 +1481,8 @@ do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
  leave:
   release_list (c);
   xfree(c->dek);
-  free_packet (pkt);
+  free_packet (pkt, &parsectx);
+  deinit_parse_packet (&parsectx);
   xfree (pkt);
   free_md_filter_context (&c->mfx);
   return rc;
diff --git a/g10/packet.h b/g10/packet.h
index ffa1fe9..ad6f317 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -596,13 +596,22 @@ int set_packet_list_mode( int mode );
 /* A context used with parse_packet.  */
 struct parse_packet_ctx_s
 {
-  iobuf_t inp; /* The input stream with the packets.  */
+  iobuf_t inp;       /* The input stream with the packets.  */
+  PACKET *last_pkt;  /* The last parsed packet.  */
+  int free_last_pkt; /* Indicates that LAST_PKT must be freed.  */
 };
 typedef struct parse_packet_ctx_s *parse_packet_ctx_t;
 
-#define init_parse_packet(a,i) do { (a)->inp = (i);    \
-    /**/                       } while (0)
+#define init_parse_packet(a,i) do { \
+    (a)->inp = (i);                 \
+    (a)->last_pkt = NULL;           \
+    (a)->free_last_pkt = 0;         \
+  } while (0)
 
+#define deinit_parse_packet(a) do { \
+    if ((a)->free_last_pkt)         \
+      free_packet (NULL, (a));      \
+  } while (0)
 
 
 #if DEBUG_PARSE_PACKET
@@ -803,7 +812,7 @@ void free_public_key( PKT_public_key *key );
 void free_attributes(PKT_user_id *uid);
 void free_user_id( PKT_user_id *uid );
 void free_comment( PKT_comment *rem );
-void free_packet( PACKET *pkt );
+void free_packet (PACKET *pkt, parse_packet_ctx_t parsectx);
 prefitem_t *copy_prefs (const prefitem_t *prefs);
 PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
 PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 7766a45..ab273a5 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -352,6 +352,9 @@ dbg_copy_all_packets (iobuf_t inp, iobuf_t out, const char *dbg_f, int dbg_l)
 	 (rc =
 	  parse (&parsectx, &pkt, 0, NULL, &skip, out, 0, "copy",
                  dbg_f, dbg_l)));
+
+  deinit_parse_packet (&parsectx);
+
   return rc;
 }
 #else /*!DEBUG_PARSE_PACKET*/
@@ -372,6 +375,9 @@ copy_all_packets (iobuf_t inp, iobuf_t out)
       init_packet (&pkt);
     }
   while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0)));
+
+  deinit_parse_packet (&parsectx);
+
   return rc;
 }
 #endif /*!DEBUG_PARSE_PACKET*/
@@ -397,11 +403,17 @@ dbg_copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff,
   do
     {
       if (iobuf_tell (inp) >= stopoff)
-	return 0;
+        {
+          deinit_parse_packet (&parsectx);
+          return 0;
+        }
       init_packet (&pkt);
     }
   while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0,
 		       "some", dbg_f, dbg_l)));
+
+  deinit_parse_packet (&parsectx);
+
   return rc;
 }
 #else /*!DEBUG_PARSE_PACKET*/
@@ -418,10 +430,16 @@ copy_some_packets (iobuf_t inp, iobuf_t out, off_t stopoff)
   do
     {
       if (iobuf_tell (inp) >= stopoff)
-	return 0;
+        {
+          deinit_parse_packet (&parsectx);
+          return 0;
+        }
       init_packet (&pkt);
     }
   while (!(rc = parse (&parsectx, &pkt, 0, NULL, &skip, out, 0)));
+
+  deinit_parse_packet (&parsectx);
+
   return rc;
 }
 #endif /*!DEBUG_PARSE_PACKET*/
@@ -447,6 +465,9 @@ dbg_skip_some_packets (iobuf_t inp, unsigned n, const char *dbg_f, int dbg_l)
       rc = parse (&parsectx, &pkt, 0, NULL, &skip, NULL, 1, "skip",
                   dbg_f, dbg_l);
     }
+
+  deinit_parse_packet (&parsectx);
+
   return rc;
 }
 #else /*!DEBUG_PARSE_PACKET*/
@@ -465,6 +486,9 @@ skip_some_packets (iobuf_t inp, unsigned int n)
       init_packet (&pkt);
       rc = parse (&parsectx, &pkt, 0, NULL, &skip, NULL, 1);
     }
+
+  deinit_parse_packet (&parsectx);
+
   return rc;
 }
 #endif /*!DEBUG_PARSE_PACKET*/
@@ -804,6 +828,16 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
       break;
     }
 
+  /* Store a shallow copy of certain packets in the context.  */
+  if (!rc && (pkttype == PKT_PUBLIC_KEY
+              || pkttype == PKT_SECRET_KEY
+              || pkttype == PKT_USER_ID
+              || pkttype == PKT_ATTRIBUTE
+              || pkttype == PKT_SIGNATURE))
+    ctx->last_pkt = pkt;
+  else
+    ctx->last_pkt = NULL;
+
  leave:
   /* FIXME: We leak in case of an error (see the xmalloc's above).  */
   if (!rc && iobuf_error (inp))
diff --git a/g10/sign.c b/g10/sign.c
index 801c809..9bb1f44 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -575,7 +575,7 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass )
         pkt.pkttype = PKT_ONEPASS_SIG;
         pkt.pkt.onepass_sig = ops;
         rc = build_packet (out, &pkt);
-        free_packet (&pkt);
+        free_packet (&pkt, NULL);
         if (rc) {
             log_error ("build onepass_sig packet failed: %s\n",
                        gpg_strerror (rc));
@@ -645,7 +645,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
             log_error ("build_packet(PLAINTEXT) failed: %s\n",
                        gpg_strerror (rc) );
         pt->buf = NULL;
-        free_packet (&pkt);
+        free_packet (&pkt, NULL);
     }
     else {
         byte copy_buffer[4096];
@@ -732,7 +732,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
           rc = build_packet (out, &pkt);
           if (!rc && is_status_enabled())
             print_status_sig_created (pk, sig, status_letter);
-          free_packet (&pkt);
+          free_packet (&pkt, NULL);
           if (rc)
             log_error ("build signature packet failed: %s\n",
                        gpg_strerror (rc));

commit ba57f8302a3ee12ff117b0243047241c44388179
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Mar 29 11:28:30 2017 +0200

    indent: Re-indent function free-packet.
    
    --
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/g10/free-packet.c b/g10/free-packet.c
index 01db2a0..4cf80a4 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -395,56 +395,59 @@ free_plaintext( PKT_plaintext *pt )
 }
 
 /****************
- * Free the packet in pkt.
+ * Free the packet in PKT.
  */
 void
-free_packet( PACKET *pkt )
+free_packet (PACKET *pkt)
 {
-    if( !pkt || !pkt->pkt.generic )
-	return;
-
-    if( DBG_MEMORY )
-	log_debug("free_packet() type=%d\n", pkt->pkttype );
-
-    switch( pkt->pkttype ) {
-      case PKT_SIGNATURE:
-	free_seckey_enc( pkt->pkt.signature );
-	break;
-      case PKT_PUBKEY_ENC:
-	free_pubkey_enc( pkt->pkt.pubkey_enc );
-	break;
-      case PKT_SYMKEY_ENC:
-	free_symkey_enc( pkt->pkt.symkey_enc );
-	break;
-      case PKT_PUBLIC_KEY:
-      case PKT_PUBLIC_SUBKEY:
-      case PKT_SECRET_KEY:
-      case PKT_SECRET_SUBKEY:
-	free_public_key (pkt->pkt.public_key);
-	break;
-      case PKT_COMMENT:
-	free_comment( pkt->pkt.comment );
-	break;
-      case PKT_USER_ID:
-	free_user_id( pkt->pkt.user_id );
-	break;
-      case PKT_COMPRESSED:
-	free_compressed( pkt->pkt.compressed);
-	break;
-      case PKT_ENCRYPTED:
-      case PKT_ENCRYPTED_MDC:
-	free_encrypted( pkt->pkt.encrypted );
-	break;
-      case PKT_PLAINTEXT:
-	free_plaintext( pkt->pkt.plaintext );
-	break;
-      default:
-	xfree( pkt->pkt.generic );
-	break;
+  if (!pkt || !pkt->pkt.generic)
+    return;
+
+  if (DBG_MEMORY)
+    log_debug ("free_packet() type=%d\n", pkt->pkttype);
+
+  switch (pkt->pkttype)
+    {
+    case PKT_SIGNATURE:
+      free_seckey_enc (pkt->pkt.signature);
+      break;
+    case PKT_PUBKEY_ENC:
+      free_pubkey_enc (pkt->pkt.pubkey_enc);
+      break;
+    case PKT_SYMKEY_ENC:
+      free_symkey_enc (pkt->pkt.symkey_enc);
+      break;
+    case PKT_PUBLIC_KEY:
+    case PKT_PUBLIC_SUBKEY:
+    case PKT_SECRET_KEY:
+    case PKT_SECRET_SUBKEY:
+      free_public_key (pkt->pkt.public_key);
+      break;
+    case PKT_COMMENT:
+      free_comment (pkt->pkt.comment);
+      break;
+    case PKT_USER_ID:
+      free_user_id (pkt->pkt.user_id);
+      break;
+    case PKT_COMPRESSED:
+      free_compressed (pkt->pkt.compressed);
+      break;
+    case PKT_ENCRYPTED:
+    case PKT_ENCRYPTED_MDC:
+      free_encrypted (pkt->pkt.encrypted);
+      break;
+    case PKT_PLAINTEXT:
+      free_plaintext (pkt->pkt.plaintext);
+      break;
+    default:
+      xfree (pkt->pkt.generic);
+      break;
     }
-    pkt->pkt.generic = NULL;
+
+  pkt->pkt.generic = NULL;
 }
 
+
 /****************
  * returns 0 if they match.
  */

-----------------------------------------------------------------------

Summary of changes:
 doc/DETAILS        |  37 +++++++++
 g10/build-packet.c | 102 ++++++++++++++++++++++--
 g10/encrypt.c      |   4 +-
 g10/export.c       |  29 ++++---
 g10/free-packet.c  | 119 +++++++++++++++++-----------
 g10/import.c       |  33 ++++----
 g10/kbnode.c       |   8 +-
 g10/keydb.c        |  13 ++--
 g10/keydb.h        |  13 ++++
 g10/keyedit.c      |  19 ++---
 g10/keygen.c       |   2 +-
 g10/keyring.c      |  79 ++++---------------
 g10/mainproc.c     |  32 +++-----
 g10/packet.h       |  58 +++++++++++---
 g10/parse-packet.c | 222 +++++++++++++++++++++++++++++++++++++++++++++--------
 g10/sign.c         |   6 +-
 16 files changed, 545 insertions(+), 231 deletions(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list