Update copyright notices for 2017.
[gnupg.git] / g10 / parse-packet.c
index 4ba9419..7f44ce5 100644 (file)
  * 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>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 
 #include "gpg.h"
 #include "util.h"
@@ -212,7 +211,7 @@ set_packet_list_mode (int mode)
      enable the list mode only with a special option. */
   if (!listfp)
     {
-      if (opt.list_packets == 2)
+      if (opt.list_packets)
         {
           listfp = es_stdout;
           if (opt.verbose)
@@ -221,7 +220,7 @@ set_packet_list_mode (int mode)
       else
         listfp = es_stderr;
 
-      if (opt.debug && DBG_MPI_VALUE)
+      if (DBG_MPI)
         mpi_print_mode = 1;
     }
   return old;
@@ -336,6 +335,10 @@ dbg_copy_all_packets (IOBUF inp, IOBUF out, const char *dbg_f, int dbg_l)
 {
   PACKET pkt;
   int skip, rc = 0;
+
+  if (! out)
+    log_bug ("copy_all_packets: OUT may not be NULL.\n");
+
   do
     {
       init_packet (&pkt);
@@ -351,6 +354,10 @@ copy_all_packets (IOBUF inp, IOBUF out)
 {
   PACKET pkt;
   int skip, rc = 0;
+
+  if (! out)
+    log_bug ("copy_all_packets: OUT may not be NULL.\n");
+
   do
     {
       init_packet (&pkt);
@@ -479,7 +486,7 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
   off_t pos;
 
   *skip = 0;
-  assert (!pkt->pkt.generic);
+  log_assert (!pkt->pkt.generic);
   if (retpos || list_mode)
     {
       pos = iobuf_tell (inp);
@@ -550,27 +557,20 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
       else if (c == 255)
         {
          int i;
-         int eof = 0;
          char value[4];
 
          for (i = 0; i < 4; i ++)
-           if ((value[i] = hdr[hdrlen++] = iobuf_get (inp)) == -1)
-             {
-               eof = 1;
-               break;
-             }
-
-         if (eof)
             {
-              log_error ("%s: 4 byte length invalid\n", iobuf_where (inp));
-              rc = gpg_error (GPG_ERR_INV_PACKET);
-              goto leave;
+              if ((c = iobuf_get (inp)) == -1)
+                {
+                  log_error ("%s: 4 byte length invalid\n", iobuf_where (inp));
+                  rc = gpg_error (GPG_ERR_INV_PACKET);
+                  goto leave;
+                }
+              value[i] = hdr[hdrlen++] = c;
             }
 
-         pktlen = (((unsigned long) value[0] << 24)
-                   | ((unsigned long) value[1] << 16)
-                   | ((unsigned long) value[2] << 8)
-                   | ((unsigned long) value[3]));
+         pktlen = buf32_to_ulong (value);
         }
       else /* Partial body length.  */
         {
@@ -580,7 +580,7 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
             case PKT_ENCRYPTED:
             case PKT_ENCRYPTED_MDC:
             case PKT_COMPRESSED:
-              iobuf_set_partial_block_mode (inp, c & 0xff);
+              iobuf_set_partial_body_length_mode (inp, c & 0xff);
               pktlen = 0;      /* To indicate partial length.  */
               partial = 1;
               break;
@@ -635,7 +635,14 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
        }
     }
 
-  if (pktlen == (unsigned long) (-1))
+  /* Sometimes the decompressing layer enters an error state in which
+     it simply outputs 0xff for every byte read.  If we have a stream
+     of 0xff bytes, then it will be detected as a new format packet
+     with type 63 and a 4-byte encoded length that is 4G-1.  Since
+     packets with type 63 are private and we use them as a control
+     packet, which won't be 4 GB, we reject such packets as
+     invalid.  */
+  if (pkttype == 63 && pktlen == 0xFFFFFFFF)
     {
       /* With some probability this is caused by a problem in the
        * the uncompressing layer - in some error cases it just loops
@@ -646,6 +653,17 @@ parse (IOBUF inp, PACKET * pkt, int onlykeypkts, off_t * retpos,
 
   if (out && pkttype)
     {
+      /* This type of copying won't work if the packet uses a partial
+        body length.  (In other words, this only works if HDR is
+        actually the length.)  Currently, no callers require this
+        functionality so we just log this as an error.  */
+      if (partial)
+       {
+         log_error ("parse: Can't copy partial packet.  Aborting.\n");
+         rc = gpg_error (GPG_ERR_INV_PACKET);
+         goto leave;
+       }
+
       rc = iobuf_write (out, hdr, hdrlen);
       if (!rc)
        rc = copy_packet (inp, out, pkttype, pktlen, partial);
@@ -791,8 +809,8 @@ dump_hex_line (int c, int *i)
    decoded values are given as PKGTYPE and PKTLEN.
 
    If the packet is a partial body length packet (RFC 4880, Section
-   4.2.2.4), then iobuf_set_partial_block_mode should already have
-   been called on INP and PARTIAL should be set.
+   4.2.2.4), then iobuf_set_partial_block_modeiobuf_set_partial_block_mode
+   should already have been called on INP and PARTIAL should be set.
 
    If PARTIAL is set or PKTLEN is 0 and PKTTYPE is PKT_COMPRESSED,
    copy until the first EOF is encountered on INP.
@@ -1095,7 +1113,7 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
        log_info (_("WARNING: potentially insecure symmetrically"
                    " encrypted session key\n"));
     }
-  assert (!pktlen);
+  log_assert (!pktlen);
 
   if (list_mode)
     {
@@ -1317,6 +1335,19 @@ dump_sig_subpkt (int hashed, int type, int critical,
                     (ulong) buf32_to_u32 (buffer),
                     (ulong) buf32_to_u32 (buffer + 4));
       break;
+    case SIGSUBPKT_ISSUER_FPR:
+      if (length >= 21)
+        {
+          char *tmp;
+          es_fprintf (listfp, "issuer fpr v%d ", buffer[0]);
+          tmp = bin2hex (buffer+1, length-1, NULL);
+          if (tmp)
+            {
+              es_fputs (tmp, listfp);
+              xfree (tmp);
+            }
+        }
+      break;
     case SIGSUBPKT_NOTATION:
       {
        es_fputs ("notation: ", listfp);
@@ -1356,12 +1387,12 @@ dump_sig_subpkt (int hashed, int type, int critical,
        es_fprintf (listfp, " %d", buffer[i]);
       break;
     case SIGSUBPKT_KS_FLAGS:
-      es_fputs ("key server preferences:", listfp);
+      es_fputs ("keyserver preferences:", listfp);
       for (i = 0; i < length; i++)
        es_fprintf (listfp, " %02X", buffer[i]);
       break;
     case SIGSUBPKT_PREF_KS:
-      es_fputs ("preferred key server: ", listfp);
+      es_fputs ("preferred keyserver: ", listfp);
       es_write_sanitized (listfp, buffer, length, ")", NULL);
       break;
     case SIGSUBPKT_PRIMARY_UID:
@@ -1467,6 +1498,10 @@ parse_one_sig_subpkt (const byte * buffer, size_t n, int type)
       if (n < 8)
        break;
       return 0;
+    case SIGSUBPKT_ISSUER_FPR: /* issuer key ID */
+      if (n < 21)
+       break;
+      return 0;
     case SIGSUBPKT_NOTATION:
       /* minimum length needed, and the subpacket must be well-formed
          where the name length and value length all fit inside the
@@ -1525,6 +1560,7 @@ can_handle_critical (const byte * buffer, size_t n, int type)
     case SIGSUBPKT_REVOCABLE:
     case SIGSUBPKT_REV_KEY:
     case SIGSUBPKT_ISSUER:     /* issuer key ID */
+    case SIGSUBPKT_ISSUER_FPR: /* issuer fingerprint */
     case SIGSUBPKT_PREF_SYM:
     case SIGSUBPKT_PREF_HASH:
     case SIGSUBPKT_PREF_COMPR:
@@ -1649,7 +1685,7 @@ enum_sig_subpkt (const subpktarea_t * pktbuf, sigsubpkttype_t reqtype,
     }
   if (reqtype == SIGSUBPKT_TEST_CRITICAL)
     /* Returning NULL means we found a subpacket with the critical bit
-       set that we dn't grok.  We've iterated over all the subpackets
+       set that we don't grok.  We've iterated over all the subpackets
        and haven't found such a packet so we need to return a non-NULL
        value.  */
     return buffer;
@@ -1692,25 +1728,31 @@ parse_sig_subpkt2 (PKT_signature * sig, sigsubpkttype_t reqtype)
 void
 parse_revkeys (PKT_signature * sig)
 {
-  struct revocation_key *revkey;
+  const byte *revkey;
   int seq = 0;
   size_t len;
 
   if (sig->sig_class != 0x1F)
     return;
 
-  while ((revkey =
-         (struct revocation_key *) enum_sig_subpkt (sig->hashed,
-                                                    SIGSUBPKT_REV_KEY,
-                                                    &len, &seq, NULL)))
+  while ((revkey = enum_sig_subpkt (sig->hashed, SIGSUBPKT_REV_KEY,
+                                   &len, &seq, NULL)))
     {
-      if (len == sizeof (struct revocation_key)
-          && (revkey->class & 0x80))  /* 0x80 bit must be set.  */
+      if (/* The only valid length is 22 bytes.  See RFC 4880
+            5.2.3.15.  */
+         len == 22
+         /* 0x80 bit must be set on the class.  */
+          && (revkey[0] & 0x80))
        {
          sig->revkey = xrealloc (sig->revkey,
-                                 sizeof (struct revocation_key *) *
+                                 sizeof (struct revocation_key) *
                                  (sig->numrevkeys + 1));
-         sig->revkey[sig->numrevkeys] = revkey;
+
+         /* Copy the individual fields.  */
+         sig->revkey[sig->numrevkeys].class = revkey[0];
+         sig->revkey[sig->numrevkeys].algid = revkey[1];
+         memcpy (sig->revkey[sig->numrevkeys].fpr, &revkey[2], 20);
+
          sig->numrevkeys++;
        }
     }
@@ -1891,6 +1933,17 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
       if (p)
        sig->flags.pref_ks = 1;
 
+      p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIGNERS_UID, &len);
+      if (p && len)
+        {
+          sig->signers_uid = try_make_printable_string (p, len, 0);
+          if (!sig->signers_uid)
+            {
+              rc = gpg_error_from_syserror ();
+              goto leave;
+            }
+        }
+
       p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_NOTATION, NULL);
       if (p)
        sig->flags.notation = 1;
@@ -2288,6 +2341,11 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
                case 3:
                  for (i = 0; i < 8 && pktlen; i++, pktlen--)
                    temp[i] = iobuf_get_noeof (inp);
+                  if (i < 8)
+                    {
+                     err = gpg_error (GPG_ERR_INV_PACKET);
+                     goto leave;
+                    }
                  memcpy (ski->s2k.salt, temp, 8);
                  break;
                }
@@ -2391,7 +2449,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
           * NOTE: if you change the ivlen above 16, don't forget to
           * enlarge temp.  */
          ski->ivlen = openpgp_cipher_blocklen (ski->algo);
-         assert (ski->ivlen <= sizeof (temp));
+         log_assert (ski->ivlen <= sizeof (temp));
 
          if (ski->s2k.mode == 1001)
            ski->ivlen = 0;
@@ -2403,7 +2461,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
               err = gpg_error (GPG_ERR_INV_PACKET);
              goto leave;
            }
-         for (i = 0; i < ski->ivlen && pktlen; i++, pktlen--)
+         for (i = 0; i < ski->ivlen; i++, pktlen--)
            temp[i] = iobuf_get_noeof (inp);
          if (list_mode)
            {
@@ -2492,6 +2550,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
        }
     }
 
+  /* Note that KEYID below has been initialized above in list_mode.  */
   if (list_mode)
     es_fprintf (listfp, "\tkeyid: %08lX%08lX\n",
                 (ulong) keyid[0], (ulong) keyid[1]);
@@ -2629,7 +2688,7 @@ parse_user_id (IOBUF inp, int pkttype, unsigned long pktlen, PACKET * packet)
 void
 make_attribute_uidname (PKT_user_id * uid, size_t max_namelen)
 {
-  assert (max_namelen > 70);
+  log_assert (max_namelen > 70);
   if (uid->numattribs <= 0)
     sprintf (uid->name, "[bad attribute packet of size %lu]",
             uid->attrib_len);
@@ -2836,7 +2895,6 @@ parse_plaintext (IOBUF inp, int pkttype, unsigned long pktlen,
     pktlen -= 4;
   pt->len = pktlen;
   pt->buf = inp;
-  pktlen = 0;
 
   if (list_mode)
     {
@@ -2992,9 +3050,9 @@ parse_mdc (IOBUF inp, int pkttype, unsigned long pktlen,
 
 
 /*
- * This packet is internally generated by us (ibn armor.c) to transfer
+ * This packet is internally generated by us (in armor.c) to transfer
  * some information to the lower layer.  To make sure that this packet
- * is really a GPG faked one and not one comming from outside, we
+ * is really a GPG faked one and not one coming from outside, we
  * first check that there is a unique tag in it.
  *
  * The format of such a control packet is: