diff options
author | Werner Koch <[email protected]> | 2016-02-14 14:50:12 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2016-02-14 15:01:53 +0000 |
commit | 9b28b82e7c40d1eacc446d5932cd613c56378ed8 (patch) | |
tree | 370ca775e4b925b1fc4194debb4d4545d011d922 | |
parent | gpg: Improve API documentation. (diff) | |
download | gnupg-9b28b82e7c40d1eacc446d5932cd613c56378ed8.tar.gz gnupg-9b28b82e7c40d1eacc446d5932cd613c56378ed8.zip |
gpg: Add hidden key-edit subcommand "change-usage".
* g10/keyedit.c (cmdCHANGEUSAGE): New.
(cmds): Add command "change-usage".
(keyedit_menu): Handle that command.
(menu_changeusage): New.
* g10/keygen.c (keygen_add_key_flags): New.
(ask_key_flags): Add optional arg current.
--
Signed-off-by: Werner Koch <[email protected]>
-rw-r--r-- | g10/keyedit.c | 119 | ||||
-rw-r--r-- | g10/keygen.c | 36 | ||||
-rw-r--r-- | g10/main.h | 2 |
3 files changed, 146 insertions, 11 deletions
diff --git a/g10/keyedit.c b/g10/keyedit.c index 30f52a4b0..19ddf2922 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -70,6 +70,7 @@ static int menu_clean (KBNODE keyblock, int self_only); static void menu_delkey (KBNODE pub_keyblock); static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive); static int menu_expire (KBNODE pub_keyblock); +static int menu_changeusage (kbnode_t keyblock); static int menu_backsign (KBNODE pub_keyblock); static int menu_set_primary_uid (KBNODE pub_keyblock); static int menu_set_preferences (KBNODE pub_keyblock); @@ -1362,7 +1363,7 @@ enum cmdids cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, - cmdEXPIRE, cmdBACKSIGN, + cmdEXPIRE, cmdCHANGEUSAGE, cmdBACKSIGN, #ifndef NO_TRUST_MODELS cmdENABLEKEY, cmdDISABLEKEY, #endif /*!NO_TRUST_MODELS*/ @@ -1393,6 +1394,7 @@ static struct { "key", cmdSELKEY, 0, N_("select subkey N")}, { "check", cmdCHECK, 0, N_("check signatures")}, { "c", cmdCHECK, 0, NULL}, + { "change-usage", cmdCHANGEUSAGE, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, { "cross-certify", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, { "backsign", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL}, { "sign", cmdSIGN, KEYEDIT_NOT_SK | KEYEDIT_TAIL_MATCH, @@ -2122,6 +2124,15 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, } break; + case cmdCHANGEUSAGE: + if (menu_changeusage (keyblock)) + { + merge_keys_and_selfsig (keyblock); + modified = 1; + redisplay = 1; + } + break; + case cmdBACKSIGN: if (menu_backsign (keyblock)) { @@ -4110,6 +4121,112 @@ menu_expire (KBNODE pub_keyblock) } +/* Change the capability of a selected key. This command should only + * be used to rectify badly created keys and as such is not suggested + * for general use. */ +static int +menu_changeusage (kbnode_t keyblock) +{ + int n1, rc; + int mainkey = 0; + PKT_public_key *main_pk, *sub_pk; + PKT_user_id *uid; + kbnode_t node; + u32 keyid[2]; + + n1 = count_selected_keys (keyblock); + if (n1 > 1) + { + tty_printf (_("You must select exactly one key.\n")); + return 0; + } + else if (n1) + tty_printf ("Changing usage of a subkey.\n"); + else + { + tty_printf ("Changing usage of the primary key.\n"); + mainkey = 1; + } + + /* Now we can actually change the self-signature(s) */ + main_pk = sub_pk = NULL; + uid = NULL; + for (node = keyblock; node; node = node->next) + { + if (node->pkt->pkttype == PKT_PUBLIC_KEY) + { + main_pk = node->pkt->pkt.public_key; + keyid_from_pk (main_pk, keyid); + } + else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + if (node->flag & NODFLG_SELKEY) + sub_pk = node->pkt->pkt.public_key; + else + sub_pk = NULL; + } + else if (node->pkt->pkttype == PKT_USER_ID) + uid = node->pkt->pkt.user_id; + else if (main_pk && node->pkt->pkttype == PKT_SIGNATURE + && (mainkey || sub_pk)) + { + PKT_signature *sig = node->pkt->pkt.signature; + if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] + && ((mainkey && uid + && uid->created && (sig->sig_class & ~3) == 0x10) + || (!mainkey && sig->sig_class == 0x18)) + && sig->flags.chosen_selfsig) + { + /* This is the self-signature which is to be replaced. */ + PKT_signature *newsig; + PACKET *newpkt; + + if ((mainkey && main_pk->version < 4) + || (!mainkey && sub_pk->version < 4)) + { + log_info ("You can't change the capabilities of a v3 key\n"); + return 0; + } + + if (mainkey) + main_pk->pubkey_usage = ask_key_flags (main_pk->pubkey_algo, 0, + main_pk->pubkey_usage); + else + sub_pk->pubkey_usage = ask_key_flags (sub_pk->pubkey_algo, 1, + sub_pk->pubkey_usage); + + if (mainkey) + rc = update_keysig_packet (&newsig, sig, main_pk, uid, NULL, + main_pk, keygen_add_key_flags, + main_pk); + else + rc = + update_keysig_packet (&newsig, sig, main_pk, NULL, sub_pk, + main_pk, keygen_add_key_flags, sub_pk); + if (rc) + { + log_error ("make_keysig_packet failed: %s\n", + gpg_strerror (rc)); + return 0; + } + + /* Replace the packet. */ + newpkt = xmalloc_clear (sizeof *newpkt); + newpkt->pkttype = PKT_SIGNATURE; + newpkt->pkt.signature = newsig; + free_packet (node->pkt); + xfree (node->pkt); + node->pkt = newpkt; + sub_pk = NULL; + break; + } + } + } + + return 1; +} + + static int menu_backsign (KBNODE pub_keyblock) { diff --git a/g10/keygen.c b/g10/keygen.c index 0f7a6a0aa..7b5a35be9 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -252,6 +252,18 @@ keygen_add_key_expire (PKT_signature *sig, void *opaque) } +/* Add the key usage (i.e. key flags) in SIG from the public keys + * pubkey_usage field. OPAQUE has the public key. */ +int +keygen_add_key_flags (PKT_signature *sig, void *opaque) +{ + PKT_public_key *pk = opaque; + + do_add_key_flags (sig, pk->pubkey_usage); + return 0; +} + + static int keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque) { @@ -1646,9 +1658,10 @@ print_key_flags(int flags) } -/* Returns the key flags */ -static unsigned int -ask_key_flags(int algo,int subkey) +/* Ask for the key flags and return them. CURRENT gives the curren + * usage which should normally be given as 0. */ +unsigned int +ask_key_flags (int algo, int subkey, unsigned int current) { /* TRANSLATORS: Please use only plain ASCII characters for the translation. If this is not possible use single digits. The @@ -1663,7 +1676,6 @@ ask_key_flags(int algo,int subkey) const char *togglers=_("SsEeAaQq"); char *answer=NULL; const char *s; - unsigned int current=0; unsigned int possible=openpgp_pk_algo_usage(algo); if ( strlen(togglers) != 8 ) @@ -1678,8 +1690,12 @@ ask_key_flags(int algo,int subkey) possible&=~PUBKEY_USAGE_CERT; /* Preload the current set with the possible set, minus - authentication, since nobody really uses auth yet. */ - current=possible&~PUBKEY_USAGE_AUTH; + authentication if CURRENT has been given as 0. If CURRENT has + been has non-zero we mask with all possible usages. */ + if (current) + current &= possible; + else + current = (possible&~PUBKEY_USAGE_AUTH); for(;;) { @@ -1922,13 +1938,13 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage, else if ((algo == 7 || !strcmp (answer, "dsa/*")) && opt.expert) { algo = PUBKEY_ALGO_DSA; - *r_usage = ask_key_flags (algo, addmode); + *r_usage = ask_key_flags (algo, addmode, 0); break; } else if ((algo == 8 || !strcmp (answer, "rsa/*")) && opt.expert) { algo = PUBKEY_ALGO_RSA; - *r_usage = ask_key_flags (algo, addmode); + *r_usage = ask_key_flags (algo, addmode, 0); break; } else if ((algo == 9 || !strcmp (answer, "ecc+ecc")) @@ -1947,7 +1963,7 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage, else if ((algo == 11 || !strcmp (answer, "ecc/*")) && opt.expert) { algo = PUBKEY_ALGO_ECDSA; - *r_usage = ask_key_flags (algo, addmode); + *r_usage = ask_key_flags (algo, addmode, 0); break; } else if ((algo == 12 || !strcmp (answer, "ecc/e")) @@ -1985,7 +2001,7 @@ ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage, xfree (keygrip); keygrip = answer; answer = NULL; - *r_usage = ask_key_flags (algo, addmode); + *r_usage = ask_key_flags (algo, addmode, 0); break; } else diff --git a/g10/main.h b/g10/main.h index ec2442661..863afa9e0 100644 --- a/g10/main.h +++ b/g10/main.h @@ -280,12 +280,14 @@ void show_basic_key_info (KBNODE keyblock); u32 parse_expire_string(const char *string); u32 ask_expire_interval(int object,const char *def_expire); u32 ask_expiredate(void); +unsigned int ask_key_flags (int algo, int subkey, unsigned int current); void quick_generate_keypair (ctrl_t ctrl, const char *uid); void generate_keypair (ctrl_t ctrl, int full, const char *fname, const char *card_serialno, int card_backup_key); int keygen_set_std_prefs (const char *string,int personal); PKT_user_id *keygen_get_std_prefs (void); int keygen_add_key_expire( PKT_signature *sig, void *opaque ); +int keygen_add_key_flags (PKT_signature *sig, void *opaque); int keygen_add_std_prefs( PKT_signature *sig, void *opaque ); int keygen_upd_std_prefs( PKT_signature *sig, void *opaque ); int keygen_add_keyserver_url(PKT_signature *sig, void *opaque); |