diff --git a/kbx/ChangeLog b/kbx/ChangeLog index aa39df815..1c3b9e3a1 100644 --- a/kbx/ChangeLog +++ b/kbx/ChangeLog @@ -1,3 +1,9 @@ +2004-06-18 Werner Koch + + * keybox-dump.c (_keybox_dump_file): New arg STATS_ONLY. + (update_stats): New. + * kbxutil.c (main): New command --stats. + 2004-04-23 Werner Koch * keybox-blob.c (_keybox_update_header_blob): New. diff --git a/kbx/kbxutil.c b/kbx/kbxutil.c index 76678619c..37c19130b 100644 --- a/kbx/kbxutil.c +++ b/kbx/kbxutil.c @@ -47,6 +47,7 @@ enum cmd_and_opt_values { aFindByFpr, aFindByKid, aFindByUid, + aStats, oDebug, oDebugAll, @@ -61,15 +62,16 @@ enum cmd_and_opt_values { static ARGPARSE_OPTS opts[] = { { 300, NULL, 0, N_("@Commands:\n ") }, - { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, - { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, - { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, +/* { aFindByFpr, "find-by-fpr", 0, "|FPR| find key using it's fingerprnt" }, */ +/* { aFindByKid, "find-by-kid", 0, "|KID| find key using it's keyid" }, */ +/* { aFindByUid, "find-by-uid", 0, "|NAME| find key by user name" }, */ + { aStats, "stats", 0, "show key statistics" }, { 301, NULL, 0, N_("@\nOptions:\n ") }, - { oArmor, "armor", 0, N_("create ascii armored output")}, - { oArmor, "armour", 0, "@" }, - { oOutput, "output", 2, N_("use as output file")}, +/* { oArmor, "armor", 0, N_("create ascii armored output")}, */ +/* { oArmor, "armour", 0, "@" }, */ +/* { oOutput, "output", 2, N_("use as output file")}, */ { oVerbose, "verbose", 0, N_("verbose") }, { oQuiet, "quiet", 0, N_("be somewhat more quiet") }, { oDryRun, "dry-run", 0, N_("do not make any changes") }, @@ -261,6 +263,7 @@ main( int argc, char **argv ) case aFindByFpr: case aFindByKid: case aFindByUid: + case aStats: cmd = pargs.r_opt; break; @@ -275,50 +278,65 @@ main( int argc, char **argv ) if (!cmd) { /* default is to list a KBX file */ if (!argc) - _keybox_dump_file (NULL, stdout); + _keybox_dump_file (NULL, 0, stdout); else { for (; argc; argc--, argv++) - _keybox_dump_file (*argv, stdout); + _keybox_dump_file (*argv, 0, stdout); + } + } + else if (cmd == aStats ) + { + if (!argc) + _keybox_dump_file (NULL, 1, stdout); + else + { + for (; argc; argc--, argv++) + _keybox_dump_file (*argv, 1, stdout); } } #if 0 - else if ( cmd == aFindByFpr ) { - char *fpr; - if ( argc != 2 ) - wrong_args ("kbxfile foingerprint"); - fpr = format_fingerprint ( argv[1] ); - if ( !fpr ) - log_error ("invalid formatted fingerprint\n"); - else { - kbxfile_search_by_fpr ( argv[0], fpr ); - gcry_free ( fpr ); + else if ( cmd == aFindByFpr ) + { + char *fpr; + if ( argc != 2 ) + wrong_args ("kbxfile foingerprint"); + fpr = format_fingerprint ( argv[1] ); + if ( !fpr ) + log_error ("invalid formatted fingerprint\n"); + else + { + kbxfile_search_by_fpr ( argv[0], fpr ); + gcry_free ( fpr ); + } + } + else if ( cmd == aFindByKid ) + { + u32 kid[2]; + int mode; + + if ( argc != 2 ) + wrong_args ("kbxfile short-or-long-keyid"); + mode = format_keyid ( argv[1], kid ); + if ( !mode ) + log_error ("invalid formatted keyID\n"); + else + { + kbxfile_search_by_kid ( argv[0], kid, mode ); } } - else if ( cmd == aFindByKid ) { - u32 kid[2]; - int mode; - - if ( argc != 2 ) - wrong_args ("kbxfile short-or-long-keyid"); - mode = format_keyid ( argv[1], kid ); - if ( !mode ) - log_error ("invalid formatted keyID\n"); - else { - kbxfile_search_by_kid ( argv[0], kid, mode ); - } - } - else if ( cmd == aFindByUid ) { - if ( argc != 2 ) - wrong_args ("kbxfile userID"); - kbxfile_search_by_uid ( argv[0], argv[1] ); + else if ( cmd == aFindByUid ) + { + if ( argc != 2 ) + wrong_args ("kbxfile userID"); + kbxfile_search_by_uid ( argv[0], argv[1] ); } #endif - else - log_error ("unsupported action\n"); - - myexit(0); - return 8; /*NEVER REACHED*/ + else + log_error ("unsupported action\n"); + + myexit(0); + return 8; /*NEVER REACHED*/ } diff --git a/kbx/keybox-defs.h b/kbx/keybox-defs.h index 705762c41..759289a0e 100644 --- a/kbx/keybox-defs.h +++ b/kbx/keybox-defs.h @@ -122,7 +122,7 @@ gpg_err_code_t _keybox_get_flag_location (const unsigned char *buffer, /*-- keybox-dump.c --*/ int _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp); -int _keybox_dump_file (const char *filename, FILE *outfp); +int _keybox_dump_file (const char *filename, int stats_only, FILE *outfp); /*-- keybox-util.c --*/ diff --git a/kbx/keybox-dump.c b/kbx/keybox-dump.c index 2fb0984c0..495fb249e 100644 --- a/kbx/keybox-dump.c +++ b/kbx/keybox-dump.c @@ -323,14 +323,95 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp) } +struct file_stats_s +{ + unsigned long too_short_blobs; + unsigned long too_large_blobs; + unsigned long total_blob_count; + unsigned long empty_blob_count; + unsigned long header_blob_count; + unsigned long pgp_blob_count; + unsigned long x509_blob_count; + unsigned long unknown_blob_count; + unsigned long non_flagged; + unsigned long secret_flagged; + unsigned long ephemeral_flagged; +}; + +static int +update_stats (KEYBOXBLOB blob, struct file_stats_s *s) +{ + const unsigned char *buffer; + size_t length; + int type; + unsigned long n; + + buffer = _keybox_get_blob_image (blob, &length); + if (length < 32) + { + s->too_short_blobs++; + return -1; + } + + n = get32( buffer ); + if (n > length) + s->too_large_blobs++; + else + length = n; /* ignore the rest */ + + s->total_blob_count++; + type = buffer[4]; + switch (type) + { + case BLOBTYPE_EMPTY: + s->empty_blob_count++; + return 0; + case BLOBTYPE_HEADER: + s->header_blob_count++; + return 0; + case BLOBTYPE_PGP: + s->pgp_blob_count++; + break; + case BLOBTYPE_X509: + s->x509_blob_count++; + break; + default: + s->unknown_blob_count++; + return 0; + } + + if (length < 40) + { + s->too_short_blobs++; + return -1; + } + + n = get16 (buffer + 6); + if (n) + { + if ((n & 1)) + s->secret_flagged++; + if ((n & 2)) + s->ephemeral_flagged++; + } + else + s->non_flagged++; + + return 0; +} + + int -_keybox_dump_file (const char *filename, FILE *outfp) +_keybox_dump_file (const char *filename, int stats_only, FILE *outfp) { FILE *fp; KEYBOXBLOB blob; int rc; unsigned long count = 0; + struct file_stats_s stats; + + memset (&stats, 0, sizeof stats); if (!filename) { @@ -348,10 +429,17 @@ _keybox_dump_file (const char *filename, FILE *outfp) while ( !(rc = _keybox_read_blob (&blob, fp)) ) { - fprintf (outfp, "BEGIN-RECORD: %lu\n", count ); - _keybox_dump_blob (blob, outfp); + if (stats_only) + { + update_stats (blob, &stats); + } + else + { + fprintf (outfp, "BEGIN-RECORD: %lu\n", count ); + _keybox_dump_blob (blob, outfp); + fprintf (outfp, "END-RECORD\n"); + } _keybox_release_blob (blob); - fprintf (outfp, "END-RECORD\n"); count++; } if (rc == -1) @@ -361,5 +449,36 @@ _keybox_dump_file (const char *filename, FILE *outfp) if (fp != stdin) fclose (fp); + + if (stats_only) + { + fprintf (outfp, + "Total number of blobs: %8lu\n" + " header: %8lu\n" + " empty: %8lu\n" + " openpgp: %8lu\n" + " x509: %8lu\n" + " non flagged: %8lu\n" + " secret flagged: %8lu\n" + " ephemeral flagged: %8lu\n", + stats.total_blob_count, + stats.header_blob_count, + stats.empty_blob_count, + stats.pgp_blob_count, + stats.x509_blob_count, + stats.non_flagged, + stats.secret_flagged, + stats.ephemeral_flagged); + 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", + stats.too_short_blobs); + if (stats.too_large_blobs) + fprintf (outfp, " too large blobs: %8lu\n", + stats.too_large_blobs); + } + return rc; }