gpg: Factor out code into a standalone function.
[gnupg.git] / kbx / keybox-dump.c
index c397f9c..8815a6f 100644 (file)
 
 #include "keybox-defs.h"
 #include <gcrypt.h>
 
 #include "keybox-defs.h"
 #include <gcrypt.h>
+#include "host2net.h"
 
 /* Argg, we can't include ../common/util.h */
 char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf);
 
 
 /* Argg, we can't include ../common/util.h */
 char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf);
 
+#define get32(a) buf32_to_ulong ((a))
+#define get16(a) buf16_to_ulong ((a))
 
 
-static ulong
-get32 (const byte *buffer)
-{
-  ulong a;
-  a =  *buffer << 24;
-  a |= buffer[1] << 16;
-  a |= buffer[2] << 8;
-  a |= buffer[3];
-  return a;
-}
-
-static ulong
-get16 (const byte *buffer)
-{
-  ulong a;
-  a =  *buffer << 8;
-  a |= buffer[1];
-  return a;
-}
 
 void
 print_string (FILE *fp, const byte *p, size_t n, int delim)
 
 void
 print_string (FILE *fp, const byte *p, size_t n, int delim)
@@ -141,6 +125,25 @@ dump_header_blob (const byte *buffer, size_t length, FILE *fp)
       return -1;
     }
   fprintf (fp, "Version: %d\n", buffer[5]);
       return -1;
     }
   fprintf (fp, "Version: %d\n", buffer[5]);
+
+  n = get16 (buffer + 6);
+  fprintf( fp, "Flags:   %04lX", n);
+  if (n)
+    {
+      int any = 0;
+
+      fputs (" (", fp);
+      if ((n & 2))
+        {
+          if (any)
+            putc (',', fp);
+          fputs ("openpgp", fp);
+          any++;
+        }
+      putc (')', fp);
+    }
+  putc ('\n', fp);
+
   if ( memcmp (buffer+8, "KBXf", 4))
     fprintf (fp, "[Error: invalid magic number]\n");
 
   if ( memcmp (buffer+8, "KBXf", 4))
     fprintf (fp, "[Error: invalid magic number]\n");
 
@@ -186,17 +189,17 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
   type = buffer[4];
   switch (type)
     {
   type = buffer[4];
   switch (type)
     {
-    case BLOBTYPE_EMPTY:
+    case KEYBOX_BLOBTYPE_EMPTY:
       fprintf (fp, "Type:   Empty\n");
       return 0;
 
       fprintf (fp, "Type:   Empty\n");
       return 0;
 
-    case BLOBTYPE_HEADER:
+    case KEYBOX_BLOBTYPE_HEADER:
       fprintf (fp, "Type:   Header\n");
       return dump_header_blob (buffer, length, fp);
       fprintf (fp, "Type:   Header\n");
       return dump_header_blob (buffer, length, fp);
-    case BLOBTYPE_PGP:
+    case KEYBOX_BLOBTYPE_PGP:
       fprintf (fp, "Type:   OpenPGP\n");
       break;
       fprintf (fp, "Type:   OpenPGP\n");
       break;
-    case BLOBTYPE_X509:
+    case KEYBOX_BLOBTYPE_X509:
       fprintf (fp, "Type:   X.509\n");
       break;
     default:
       fprintf (fp, "Type:   X.509\n");
       break;
     default:
@@ -245,14 +248,14 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
       || rawdata_len + 4 > length
       || rawdata_off+rawdata_len + 4 > length)
     fprintf (fp, "[Error: raw data larger than blob]\n");
       || rawdata_len + 4 > length
       || rawdata_off+rawdata_len + 4 > length)
     fprintf (fp, "[Error: raw data larger than blob]\n");
-  unhashed = get32 (buffer + rawdata_off + rawdata_len);
+  unhashed = length - rawdata_off - rawdata_len;
   fprintf (fp, "Unhashed: %lu\n", unhashed);
 
   nkeys = get16 (buffer + 16);
   fprintf (fp, "Key-Count: %lu\n", nkeys );
   if (!nkeys)
     fprintf (fp, "[Error: no keys]\n");
   fprintf (fp, "Unhashed: %lu\n", unhashed);
 
   nkeys = get16 (buffer + 16);
   fprintf (fp, "Key-Count: %lu\n", nkeys );
   if (!nkeys)
     fprintf (fp, "[Error: no keys]\n");
-  if (nkeys > 1 && type == BLOBTYPE_X509)
+  if (nkeys > 1 && type == KEYBOX_BLOBTYPE_X509)
     fprintf (fp, "[Error: only one key allowed for X509]\n");
 
   keyinfolen = get16 (buffer + 18 );
     fprintf (fp, "[Error: only one key allowed for X509]\n");
 
   keyinfolen = get16 (buffer + 18 );
@@ -302,13 +305,13 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
 
       uidoff = get32( p );
       uidlen = get32( p+4 );
 
       uidoff = get32( p );
       uidlen = get32( p+4 );
-      if (type == BLOBTYPE_X509 && !n)
+      if (type == KEYBOX_BLOBTYPE_X509 && !n)
         {
           fprintf (fp, "Issuer-Off: %lu\n", uidoff );
           fprintf (fp, "Issuer-Len: %lu\n", uidlen );
           fprintf (fp, "Issuer: \"");
         }
         {
           fprintf (fp, "Issuer-Off: %lu\n", uidoff );
           fprintf (fp, "Issuer-Len: %lu\n", uidlen );
           fprintf (fp, "Issuer: \"");
         }
-      else if (type == BLOBTYPE_X509 && n == 1)
+      else if (type == KEYBOX_BLOBTYPE_X509 && n == 1)
         {
           fprintf (fp, "Subject-Off: %lu\n", uidoff );
           fprintf (fp, "Subject-Len: %lu\n", uidlen );
         {
           fprintf (fp, "Subject-Off: %lu\n", uidoff );
           fprintf (fp, "Subject-Len: %lu\n", uidlen );
@@ -323,12 +326,12 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
       print_string (fp, buffer+uidoff, uidlen, '\"');
       fputs ("\"\n", fp);
       uflags = get16 (p + 8);
       print_string (fp, buffer+uidoff, uidlen, '\"');
       fputs ("\"\n", fp);
       uflags = get16 (p + 8);
-      if (type == BLOBTYPE_X509 && !n)
+      if (type == KEYBOX_BLOBTYPE_X509 && !n)
         {
           fprintf (fp, "Issuer-Flags: %04lX\n", uflags );
           fprintf (fp, "Issuer-Validity: %d\n", p[10] );
         }
         {
           fprintf (fp, "Issuer-Flags: %04lX\n", uflags );
           fprintf (fp, "Issuer-Validity: %d\n", p[10] );
         }
-      else if (type == BLOBTYPE_X509 && n == 1)
+      else if (type == KEYBOX_BLOBTYPE_X509 && n == 1)
         {
           fprintf (fp, "Subject-Flags: %04lX\n", uflags );
           fprintf (fp, "Subject-Validity: %d\n", p[10] );
         {
           fprintf (fp, "Subject-Flags: %04lX\n", uflags );
           fprintf (fp, "Subject-Validity: %d\n", p[10] );
@@ -378,7 +381,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
           fputs ("[bad signature]", fp);
         else if (sflags < 0x10000000)
           fprintf (fp, "[bad flag %0lx]", sflags);
           fputs ("[bad signature]", fp);
         else if (sflags < 0x10000000)
           fprintf (fp, "[bad flag %0lx]", sflags);
-        else if (sflags == 0xffffffff)
+        else if (sflags == (ulong)(-1))
           fputs ("[good - does not expire]", fp );
         else
           fprintf (fp, "[good - expires at %lu]", sflags);
           fputs ("[good - does not expire]", fp );
         else
           fprintf (fp, "[good - expires at %lu]", sflags);
@@ -402,7 +405,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
   n = get32 (p ); p += 4;
   fprintf (fp, "Reserved-Space: %lu\n", n );
 
   n = get32 (p ); p += 4;
   fprintf (fp, "Reserved-Space: %lu\n", n );
 
-  if (unhashed >= 24)
+  if (n >= 4 && unhashed >= 24)
     {
       n = get32 ( buffer + length - unhashed);
       fprintf (fp, "Storage-Flags: %08lx\n", n );
     {
       n = get32 ( buffer + length - unhashed);
       fprintf (fp, "Storage-Flags: %08lx\n", n );
@@ -433,12 +436,12 @@ hash_blob_rawdata (KEYBOXBLOB blob, unsigned char *digest)
   type = buffer[4];
   switch (type)
     {
   type = buffer[4];
   switch (type)
     {
-    case BLOBTYPE_PGP:
-    case BLOBTYPE_X509:
+    case KEYBOX_BLOBTYPE_PGP:
+    case KEYBOX_BLOBTYPE_X509:
       break;
 
       break;
 
-    case BLOBTYPE_EMPTY:
-    case BLOBTYPE_HEADER:
+    case KEYBOX_BLOBTYPE_EMPTY:
+    case KEYBOX_BLOBTYPE_HEADER:
     default:
       memset (digest, 0, 20);
       return 0;
     default:
       memset (digest, 0, 20);
       return 0;
@@ -472,6 +475,7 @@ struct file_stats_s
   unsigned long non_flagged;
   unsigned long secret_flagged;
   unsigned long ephemeral_flagged;
   unsigned long non_flagged;
   unsigned long secret_flagged;
   unsigned long ephemeral_flagged;
+  unsigned long skipped_long_blobs;
 };
 
 static int
 };
 
 static int
@@ -499,16 +503,16 @@ update_stats (KEYBOXBLOB blob, struct file_stats_s *s)
   type = buffer[4];
   switch (type)
     {
   type = buffer[4];
   switch (type)
     {
-    case BLOBTYPE_EMPTY:
+    case KEYBOX_BLOBTYPE_EMPTY:
       s->empty_blob_count++;
       return 0;
       s->empty_blob_count++;
       return 0;
-    case BLOBTYPE_HEADER:
+    case KEYBOX_BLOBTYPE_HEADER:
       s->header_blob_count++;
       return 0;
       s->header_blob_count++;
       return 0;
-    case BLOBTYPE_PGP:
+    case KEYBOX_BLOBTYPE_PGP:
       s->pgp_blob_count++;
       break;
       s->pgp_blob_count++;
       break;
-    case BLOBTYPE_X509:
+    case KEYBOX_BLOBTYPE_X509:
       s->x509_blob_count++;
       break;
     default:
       s->x509_blob_count++;
       break;
     default:
@@ -575,8 +579,25 @@ _keybox_dump_file (const char *filename, int stats_only, FILE *outfp)
   if (!(fp = open_file (&filename, outfp)))
     return gpg_error_from_syserror ();
 
   if (!(fp = open_file (&filename, outfp)))
     return gpg_error_from_syserror ();
 
-  while ( !(rc = _keybox_read_blob (&blob, fp)) )
+  for (;;)
     {
     {
+      rc = _keybox_read_blob (&blob, fp);
+      if (gpg_err_code (rc) == GPG_ERR_TOO_LARGE
+          && gpg_err_source (rc) == GPG_ERR_SOURCE_KEYBOX)
+        {
+          if (stats_only)
+            stats.skipped_long_blobs++;
+          else
+            {
+              fprintf (outfp, "BEGIN-RECORD: %lu\n", count );
+              fprintf (outfp, "# Record too large\nEND-RECORD\n");
+            }
+          count++;
+          continue;
+        }
+      if (rc)
+        break;
+
       if (stats_only)
         {
           update_stats (blob, &stats);
       if (stats_only)
         {
           update_stats (blob, &stats);
@@ -593,7 +614,7 @@ _keybox_dump_file (const char *filename, int stats_only, FILE *outfp)
   if (rc == -1)
     rc = 0;
   if (rc)
   if (rc == -1)
     rc = 0;
   if (rc)
-    fprintf (outfp, "error reading '%s': %s\n", filename, gpg_strerror (rc));
+    fprintf (outfp, "error reading '%s': %s\n", filename, gpg_strerror (rc));
 
   if (fp != stdin)
     fclose (fp);
 
   if (fp != stdin)
     fclose (fp);
@@ -617,14 +638,17 @@ _keybox_dump_file (const char *filename, int stats_only, FILE *outfp)
                stats.non_flagged,
                stats.secret_flagged,
                stats.ephemeral_flagged);
                stats.non_flagged,
                stats.secret_flagged,
                stats.ephemeral_flagged);
+        if (stats.skipped_long_blobs)
+          fprintf (outfp, "   skipped long blobs: %8lu\n",
+                   stats.skipped_long_blobs);
         if (stats.unknown_blob_count)
           fprintf (outfp, "   unknown blob types: %8lu\n",
                    stats.unknown_blob_count);
         if (stats.too_short_blobs)
         if (stats.unknown_blob_count)
           fprintf (outfp, "   unknown blob types: %8lu\n",
                    stats.unknown_blob_count);
         if (stats.too_short_blobs)
-          fprintf (outfp, "      too short blobs: %8lu\n",
+          fprintf (outfp, "      too short blobs: %8lu (error)\n",
                    stats.too_short_blobs);
         if (stats.too_large_blobs)
                    stats.too_short_blobs);
         if (stats.too_large_blobs)
-          fprintf (outfp, "      too large blobs: %8lu\n",
+          fprintf (outfp, "      too large blobs: %8lu (error)\n",
                    stats.too_large_blobs);
     }
 
                    stats.too_large_blobs);
     }