1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

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 <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-02-14 15:50:12 +01:00
parent 9663b08848
commit 9b28b82e7c
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
3 changed files with 146 additions and 11 deletions

View file

@ -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)
{