diff --git a/NEWS b/NEWS index a8352ca53..521ccf9aa 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,10 @@ Noteworthy changes in version 2.1.0beta4 (unreleased) * The hash algorithm is now printed for sig records in key listings. + * GPG does not anymore allow the use of the long deprecated v3 keys + (PGP 2 keys). The new option --allow-v3-keys can be used to + exceptionally allow them. + Noteworthy changes in version 2.1.0beta3 (2011-12-20) ----------------------------------------------------- diff --git a/doc/DETAILS b/doc/DETAILS index 59434f10c..55f9ce6dd 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -459,7 +459,7 @@ more arguments in future versions. IMPORT_RES - + Final statistics on import process (this is one long line) FILE_START diff --git a/doc/gpg.texi b/doc/gpg.texi index 420326b5d..d8e4bcdef 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -2637,6 +2637,20 @@ Disable all checks on the form of the user ID while generating a new one. This option should only be used in very special environments as it does not ensure the de-facto standard format of user IDs. +@ifset gpgtwoone +@item --allow-v3-keys +@itemx --no-allow-v3-keys +@opindex allow-v3-keys +Allow the use of deprecated v3 keys with @command{gpg}. The default +is not to allow their use. + +Since version 2.1 GnuPG does not anymore allow the import or use of v3 +keys. Those keys have been generated in the past by PGP 2 and exhibit +a couple of flaws. For example they rely on the broken MD5 algorithm. +OpenPGP has long deprecated their use (cf. RFC-4880, section 5.5.2). +This option may be used to exceptionally allow their use. +@end ifset + @item --ignore-time-conflict @opindex ignore-time-conflict GnuPG normally checks that the timestamps associated with keys and diff --git a/g10/getkey.c b/g10/getkey.c index 929427302..348755df1 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -2318,6 +2318,12 @@ finish_lookup (GETKEY_CTX ctx) if (DBG_CACHE) log_debug ("\tchecking subkey %08lX\n", (ulong) keyid_from_pk (pk, NULL)); + if (pk->version <= 3 && !opt.allow_v3_keys) + { + if (DBG_CACHE) + log_debug ("\tv3 subkey not allowed\n"); + continue; + } if (!pk->flags.valid) { if (DBG_CACHE) @@ -2373,7 +2379,12 @@ finish_lookup (GETKEY_CTX ctx) if (DBG_CACHE && !foundk && !req_prim) log_debug ("\tno suitable subkeys found - trying primary\n"); pk = keyblock->pkt->pkt.public_key; - if (!pk->flags.valid) + if (pk->version <= 3 && !opt.allow_v3_keys) + { + if (DBG_CACHE) + log_debug ("\tv3 primary key not allowed\n"); + } + else if (!pk->flags.valid) { if (DBG_CACHE) log_debug ("\tprimary key not valid\n"); diff --git a/g10/gpg.c b/g10/gpg.c index c8dbbfe83..74f34f6b4 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -305,6 +305,8 @@ enum cmd_and_opt_values oNoAllowNonSelfsignedUID, oAllowFreeformUID, oNoAllowFreeformUID, + oAllowV3Keys, + oNoAllowV3Keys, oAllowSecretKeyImport, oEnableSpecialFilenames, oNoLiteral, @@ -682,6 +684,9 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oNoAllowNonSelfsignedUID, "no-allow-non-selfsigned-uid", "@"), ARGPARSE_s_n (oAllowFreeformUID, "allow-freeform-uid", "@"), ARGPARSE_s_n (oNoAllowFreeformUID, "no-allow-freeform-uid", "@"), + ARGPARSE_s_n (oAllowFreeformUID, "allow-freeform-uid", "@"), + ARGPARSE_s_n (oAllowV3Keys, "allow-v3-keys", "@"), + ARGPARSE_s_n (oNoAllowV3Keys, "no-allow-v3-keys", "@"), ARGPARSE_s_n (oNoLiteral, "no-literal", "@"), ARGPARSE_p_u (oSetFilesize, "set-filesize", "@"), ARGPARSE_s_n (oHonorHttpProxy, "honor-http-proxy", "@"), @@ -2805,6 +2810,8 @@ main (int argc, char **argv) case oNoAllowNonSelfsignedUID: opt.allow_non_selfsigned_uid=0; break; case oAllowFreeformUID: opt.allow_freeform_uid = 1; break; case oNoAllowFreeformUID: opt.allow_freeform_uid = 0; break; + case oAllowV3Keys: opt.allow_v3_keys = 1; break; + case oNoAllowV3Keys: opt.allow_v3_keys = 0; break; case oNoLiteral: opt.no_literal = 1; break; case oSetFilesize: opt.set_filesize = pargs.r.ret_ulong; break; case oHonorHttpProxy: @@ -3184,6 +3191,7 @@ main (int argc, char **argv) xfree(s2k_digest_string); s2k_digest_string = xstrdup("md5"); opt.compress_algo = COMPRESS_ALGO_ZIP; + opt.allow_v3_keys = 1; } } else if(PGP6) diff --git a/g10/import.c b/g10/import.c index bfe02eb16..06a92af02 100644 --- a/g10/import.c +++ b/g10/import.c @@ -57,6 +57,8 @@ struct stats_s { ulong not_imported; ulong n_sigs_cleaned; ulong n_uids_cleaned; + ulong skipped_v3_keys; + ulong skipped_v3_subkeys; }; @@ -77,6 +79,7 @@ static int chk_self_sigs( const char *fname, KBNODE keyblock, PKT_public_key *pk, u32 *keyid, int *non_self ); static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid, unsigned int options ); +static int delete_v3_subkeys (kbnode_t keyblock); static int merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock, u32 *keyid, int *n_uids, int *n_sigs, int *n_subk ); @@ -330,6 +333,9 @@ import_print_stats (void *hd) if( stats->skipped_new_keys ) log_info(_(" skipped new keys: %lu\n"), stats->skipped_new_keys ); + if( stats->skipped_v3_keys ) + log_info(_(" skipped v3 keys: %lu\n"), + stats->skipped_v3_keys); if( stats->no_user_id ) log_info(_(" w/o user IDs: %lu\n"), stats->no_user_id ); if( stats->imported || stats->imported_rsa ) { @@ -344,6 +350,9 @@ import_print_stats (void *hd) log_info(_(" new user IDs: %lu\n"), stats->n_uids ); if( stats->n_subk ) log_info(_(" new subkeys: %lu\n"), stats->n_subk ); + if( stats->skipped_v3_subkeys) + log_info(_(" skipped v3 subkeys: %lu\n"), + stats->skipped_v3_subkeys); if( stats->n_sigs ) log_info(_(" new signatures: %lu\n"), stats->n_sigs ); if( stats->n_revoc ) @@ -363,8 +372,10 @@ import_print_stats (void *hd) } if( is_status_enabled() ) { - char buf[14*20]; - sprintf(buf, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + char buf[16*20]; + snprintf (buf, sizeof buf, + "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu" + " %lu %lu", stats->count, stats->no_user_id, stats->imported, @@ -378,7 +389,9 @@ import_print_stats (void *hd) stats->secret_imported, stats->secret_dups, stats->skipped_new_keys, - stats->not_imported ); + stats->not_imported, + stats->skipped_v3_keys, + stats->skipped_v3_subkeys); write_status_text( STATUS_IMPORT_RES, buf ); } } @@ -771,6 +784,7 @@ import_one (ctrl_t ctrl, int mod_key = 0; int same_key = 0; int non_self = 0; + int count; /* get the key and print some info about it */ node = find_kbnode( keyblock, PKT_PUBLIC_KEY ); @@ -795,6 +809,18 @@ import_one (ctrl_t ctrl, log_printf ("\n"); } + /* We don't allow to import v3 keys unless the --allow-v3-keys + option is active. Note that this checks only the primary key. + v3 subkeys will be removed later. */ + if (pk->version <= 3 && !opt.allow_v3_keys) + { + if (opt.verbose) + log_info (_("key %s: v3 keys are not allowed - skipped\n"), + keystr (keyid)); + stats->skipped_new_keys++; + stats->skipped_v3_keys++; + return 0; + } if( !uidnode ) { @@ -855,6 +881,14 @@ import_one (ctrl_t ctrl, return 0; } + if (!opt.allow_v3_keys && (count = delete_v3_subkeys (keyblock))) + { + stats->skipped_v3_subkeys += count; + if (!opt.quiet) + log_info (_("key %s: removed v3 subkeys: %d\n"), + keystr (keyid), count); + } + /* do we have this key already in one of our pubrings ? */ pk_orig = xmalloc_clear( sizeof *pk_orig ); rc = get_pubkey_fast ( pk_orig, keyid ); @@ -2094,6 +2128,37 @@ delete_inv_parts( const char *fname, KBNODE keyblock, } +/* Remove all v3 public subkeys from KEYBLOCK. Returns the number of + * removed subkeys. */ +static int +delete_v3_subkeys (kbnode_t keyblock) +{ + kbnode_t node; + int count = 0; + + for (node = keyblock->next; node; node = node->next ) + { + if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY + && node->pkt->pkt.public_key->version == 3) + { + delete_kbnode (node); + while (node->next && node->next->pkt->pkttype == PKT_SIGNATURE) + { + delete_kbnode (node->next); + node = node->next; + } + count++; + } + } + + /* Because KEYBLOCK is the primary public key, it is never marked + * for deletion and thus commit_keyblock won't change KEYBLOCK. */ + if (count) + commit_kbnode (&keyblock); + return count; +} + + /**************** * It may happen that the imported keyblock has duplicated user IDs. * We check this here and collapse those user IDs together with their diff --git a/g10/options.h b/g10/options.h index e67d0ce04..3a9f43c36 100644 --- a/g10/options.h +++ b/g10/options.h @@ -170,6 +170,7 @@ struct strlist_t sig_subpackets; int allow_non_selfsigned_uid; int allow_freeform_uid; + int allow_v3_keys; /* Allow the use of v3 keys. */ int no_literal; ulong set_filesize; int fast_list_mode;