gpg: In search-keys return "Not found" instead of "No Data".
[gnupg.git] / g10 / parse-packet.c
index 0fa8be6..21a26c7 100644 (file)
 #define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
 #define MAX_ATTR_PACKET_LENGTH    ( 16 * 1024*1024)
 
-
 static int mpi_print_mode;
 static int list_mode;
 static estream_t listfp;
 
+/* A linked list of known notation names.  Note that the FLAG is used
+ * to store the length of the name to speed up the check.  */
+static strlist_t known_notations_list;
+
+
 static int parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts,
                  off_t * retpos, int *skip, IOBUF out, int do_skip
 #if DEBUG_PARSE_PACKET
@@ -189,6 +193,36 @@ mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure)
 }
 
 
+/* Register STRING as a known critical notation name.  */
+void
+register_known_notation (const char *string)
+{
+  strlist_t sl;
+
+  if (!known_notations_list)
+    {
+      sl = add_to_strlist (&known_notations_list,
+                           "preferred-email-encoding@pgp.com");
+      sl->flags = 32;
+      sl = add_to_strlist (&known_notations_list, "pka-address@gnupg.org");
+      sl->flags = 21;
+    }
+  if (!string)
+    return; /* Only initialized the default known notations.  */
+
+  /* In --set-notation we use an exclamation mark to indicate a
+   * critical notation.  As a convenience skip this here.  */
+  if (*string == '!')
+    string++;
+
+  if (!*string || strlist_find (known_notations_list, string))
+    return; /* Empty string or already registered.  */
+
+  sl = add_to_strlist (&known_notations_list, string);
+  sl->flags = strlen (string);
+}
+
+
 int
 set_packet_list_mode (int mode)
 {
@@ -1640,14 +1674,24 @@ parse_one_sig_subpkt (const byte * buffer, size_t n, int type)
 
 /* Return true if we understand the critical notation.  */
 static int
-can_handle_critical_notation (const byte * name, size_t len)
+can_handle_critical_notation (const byte *name, size_t len)
 {
-  if (len == 32 && memcmp (name, "preferred-email-encoding@pgp.com", 32) == 0)
-    return 1;
-  if (len == 21 && memcmp (name, "pka-address@gnupg.org", 21) == 0)
-    return 1;
+  strlist_t sl;
 
-  return 0;
+  register_known_notation (NULL); /* Make sure it is initialized.  */
+
+  for (sl = known_notations_list; sl; sl = sl->next)
+    if (sl->flags == len && !memcmp (sl->d, name, len))
+      return 1; /* Known */
+
+  if (opt.verbose)
+    {
+      log_info(_("Unknown critical signature notation: ") );
+      print_utf8_buffer (log_get_stream(), name, len);
+      log_printf ("\n");
+    }
+
+  return 0; /* Unknown.  */
 }
 
 
@@ -1861,21 +1905,23 @@ parse_revkeys (PKT_signature * sig)
   while ((revkey = enum_sig_subpkt (sig->hashed, SIGSUBPKT_REV_KEY,
                                    &len, &seq, NULL)))
     {
-      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.  */
+      /* Consider only valid packets.  They must have a length of
+       * either 2+20 or 2+32 octets and bit 7 of the class octet must
+       * be set.  */
+      if ((len == 22 || len == 34)
           && (revkey[0] & 0x80))
        {
          sig->revkey = xrealloc (sig->revkey,
                                  sizeof (struct revocation_key) *
                                  (sig->numrevkeys + 1));
 
-         /* 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);
-
+          len -= 2;
+         sig->revkey[sig->numrevkeys].fprlen = len;
+         memcpy (sig->revkey[sig->numrevkeys].fpr, revkey+2, len);
+         memset (sig->revkey[sig->numrevkeys].fpr+len, 0,
+                  sizeof (sig->revkey[sig->numrevkeys].fpr) - len);
          sig->numrevkeys++;
        }
     }
@@ -1888,7 +1934,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
 {
   int md5_len = 0;
   unsigned n;
-  int is_v4 = 0;
+  int is_v4or5 = 0;
   int rc = 0;
   int i, ndata;
 
@@ -1901,8 +1947,8 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
     }
   sig->version = iobuf_get_noeof (inp);
   pktlen--;
-  if (sig->version == 4)
-    is_v4 = 1;
+  if (sig->version == 4 || sig->version == 5)
+    is_v4or5 = 1;
   else if (sig->version != 2 && sig->version != 3)
     {
       log_error ("packet(%d) with unknown version %d\n",
@@ -1913,7 +1959,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
       goto leave;
     }
 
-  if (!is_v4)
+  if (!is_v4or5)
     {
       if (pktlen == 0)
        goto underflow;
@@ -1924,7 +1970,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
     goto underflow;
   sig->sig_class = iobuf_get_noeof (inp);
   pktlen--;
-  if (!is_v4)
+  if (!is_v4or5)
     {
       if (pktlen < 12)
        goto underflow;
@@ -1943,7 +1989,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
   pktlen--;
   sig->flags.exportable = 1;
   sig->flags.revocable = 1;
-  if (is_v4) /* Read subpackets.  */
+  if (is_v4or5) /* Read subpackets.  */
     {
       if (pktlen < 2)
        goto underflow;
@@ -2014,7 +2060,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
   sig->digest_start[1] = iobuf_get_noeof (inp);
   pktlen--;
 
-  if (is_v4 && sig->pubkey_algo)  /* Extract required information.  */
+  if (is_v4or5 && sig->pubkey_algo)  /* Extract required information.  */
     {
       const byte *p;
       size_t len;
@@ -2115,7 +2161,7 @@ parse_signature (IOBUF inp, int pkttype, unsigned long pktlen,
                   (ulong) sig->keyid[0], (ulong) sig->keyid[1],
                   sig->version, (ulong) sig->timestamp, md5_len, sig->sig_class,
                   sig->digest_algo, sig->digest_start[0], sig->digest_start[1]);
-      if (is_v4)
+      if (is_v4or5)
        {
          parse_sig_subpkt (sig->hashed, SIGSUBPKT_LIST_HASHED, NULL);
          parse_sig_subpkt (sig->unhashed, SIGSUBPKT_LIST_UNHASHED, NULL);
@@ -2307,7 +2353,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
     {
       log_error ("packet(%d) too large\n", pkttype);
       if (list_mode)
-        es_fputs (":key packet: [too larget]\n", listfp);
+        es_fputs (":key packet: [too large]\n", listfp);
       err = gpg_error (GPG_ERR_INV_PACKET);
       goto leave;
     }
@@ -3136,7 +3182,7 @@ parse_plaintext (IOBUF inp, int pkttype, unsigned long pktlen,
          pt->name[i] = c;
     }
   /* Fill up NAME so that a check with valgrind won't complain about
-   * reading from uninitalized memory.  This case may be triggred by
+   * reading from uninitialized memory.  This case may be triggred by
    * corrupted packets.  */
   for (; i < namelen; i++)
     pt->name[i] = 0;