diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c index bfe7b4899..dfa82007f 100644 --- a/kbx/keybox-dump.c +++ b/kbx/keybox-dump.c @@ -491,6 +491,7 @@ struct file_stats_s unsigned long non_flagged; unsigned long secret_flagged; unsigned long ephemeral_flagged; + unsigned long skipped_long_blobs; }; static int @@ -594,8 +595,25 @@ _keybox_dump_file (const char *filename, int stats_only, FILE *outfp) 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); @@ -612,7 +630,7 @@ _keybox_dump_file (const char *filename, int stats_only, FILE *outfp) 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); @@ -636,14 +654,17 @@ _keybox_dump_file (const char *filename, int stats_only, FILE *outfp) 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) - fprintf (outfp, " too short blobs: %8lu\n", + fprintf (outfp, " too short blobs: %8lu (error)\n", 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); } diff --git a/kbx/keybox-file.c b/kbx/keybox-file.c index def896bca..1ed51696e 100644 --- a/kbx/keybox-file.c +++ b/kbx/keybox-file.c @@ -27,6 +27,9 @@ #include "keybox-defs.h" +#define IMAGELEN_LIMIT (2*1024*1024) + + #if !defined(HAVE_FTELLO) && !defined(ftello) static off_t ftello (FILE *stream) @@ -75,9 +78,6 @@ _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted) } imagelen = (c1 << 24) | (c2 << 16) | (c3 << 8 ) | c4; - if (imagelen > 1000000) /* Sanity check. */ - return gpg_error (GPG_ERR_TOO_LARGE); - if (imagelen < 5) return gpg_error (GPG_ERR_TOO_SHORT); @@ -90,6 +90,15 @@ _keybox_read_blob2 (KEYBOXBLOB *r_blob, FILE *fp, int *skipped_deleted) goto again; } + if (imagelen > IMAGELEN_LIMIT) /* Sanity check. */ + { + /* Seek forward so that the caller may choose to ignore this + record. */ + if (fseek (fp, imagelen-5, SEEK_CUR)) + return gpg_error_from_syserror (); + return gpg_error (GPG_ERR_TOO_LARGE); + } + image = xtrymalloc (imagelen); if (!image) return gpg_error_from_syserror (); @@ -124,6 +133,10 @@ _keybox_write_blob (KEYBOXBLOB blob, FILE *fp) size_t length; image = _keybox_get_blob_image (blob, &length); + + if (length > IMAGELEN_LIMIT) + return gpg_error (GPG_ERR_TOO_LARGE); + if (fwrite (image, length, 1, fp) != 1) return gpg_error_from_syserror (); return 0;