1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-26 01:52:45 +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 void menu_delkey (KBNODE pub_keyblock);
static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive); static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
static int menu_expire (KBNODE pub_keyblock); static int menu_expire (KBNODE pub_keyblock);
static int menu_changeusage (kbnode_t keyblock);
static int menu_backsign (KBNODE pub_keyblock); static int menu_backsign (KBNODE pub_keyblock);
static int menu_set_primary_uid (KBNODE pub_keyblock); static int menu_set_primary_uid (KBNODE pub_keyblock);
static int menu_set_preferences (KBNODE pub_keyblock); static int menu_set_preferences (KBNODE pub_keyblock);
@ -1362,7 +1363,7 @@ enum cmdids
cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG, cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY, cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
cmdEXPIRE, cmdBACKSIGN, cmdEXPIRE, cmdCHANGEUSAGE, cmdBACKSIGN,
#ifndef NO_TRUST_MODELS #ifndef NO_TRUST_MODELS
cmdENABLEKEY, cmdDISABLEKEY, cmdENABLEKEY, cmdDISABLEKEY,
#endif /*!NO_TRUST_MODELS*/ #endif /*!NO_TRUST_MODELS*/
@ -1393,6 +1394,7 @@ static struct
{ "key", cmdSELKEY, 0, N_("select subkey N")}, { "key", cmdSELKEY, 0, N_("select subkey N")},
{ "check", cmdCHECK, 0, N_("check signatures")}, { "check", cmdCHECK, 0, N_("check signatures")},
{ "c", cmdCHECK, 0, NULL}, { "c", cmdCHECK, 0, NULL},
{ "change-usage", cmdCHANGEUSAGE, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
{ "cross-certify", cmdBACKSIGN, 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}, { "backsign", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
{ "sign", cmdSIGN, KEYEDIT_NOT_SK | KEYEDIT_TAIL_MATCH, { "sign", cmdSIGN, KEYEDIT_NOT_SK | KEYEDIT_TAIL_MATCH,
@ -2122,6 +2124,15 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
} }
break; break;
case cmdCHANGEUSAGE:
if (menu_changeusage (keyblock))
{
merge_keys_and_selfsig (keyblock);
modified = 1;
redisplay = 1;
}
break;
case cmdBACKSIGN: case cmdBACKSIGN:
if (menu_backsign (keyblock)) 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 static int
menu_backsign (KBNODE pub_keyblock) menu_backsign (KBNODE pub_keyblock)
{ {

View File

@ -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 static int
keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque) keygen_add_key_flags_and_expire (PKT_signature *sig, void *opaque)
{ {
@ -1646,9 +1658,10 @@ print_key_flags(int flags)
} }
/* Returns the key flags */ /* Ask for the key flags and return them. CURRENT gives the curren
static unsigned int * usage which should normally be given as 0. */
ask_key_flags(int algo,int subkey) unsigned int
ask_key_flags (int algo, int subkey, unsigned int current)
{ {
/* TRANSLATORS: Please use only plain ASCII characters for the /* TRANSLATORS: Please use only plain ASCII characters for the
translation. If this is not possible use single digits. 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"); const char *togglers=_("SsEeAaQq");
char *answer=NULL; char *answer=NULL;
const char *s; const char *s;
unsigned int current=0;
unsigned int possible=openpgp_pk_algo_usage(algo); unsigned int possible=openpgp_pk_algo_usage(algo);
if ( strlen(togglers) != 8 ) if ( strlen(togglers) != 8 )
@ -1678,8 +1690,12 @@ ask_key_flags(int algo,int subkey)
possible&=~PUBKEY_USAGE_CERT; possible&=~PUBKEY_USAGE_CERT;
/* Preload the current set with the possible set, minus /* Preload the current set with the possible set, minus
authentication, since nobody really uses auth yet. */ authentication if CURRENT has been given as 0. If CURRENT has
current=possible&~PUBKEY_USAGE_AUTH; been has non-zero we mask with all possible usages. */
if (current)
current &= possible;
else
current = (possible&~PUBKEY_USAGE_AUTH);
for(;;) 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) else if ((algo == 7 || !strcmp (answer, "dsa/*")) && opt.expert)
{ {
algo = PUBKEY_ALGO_DSA; algo = PUBKEY_ALGO_DSA;
*r_usage = ask_key_flags (algo, addmode); *r_usage = ask_key_flags (algo, addmode, 0);
break; break;
} }
else if ((algo == 8 || !strcmp (answer, "rsa/*")) && opt.expert) else if ((algo == 8 || !strcmp (answer, "rsa/*")) && opt.expert)
{ {
algo = PUBKEY_ALGO_RSA; algo = PUBKEY_ALGO_RSA;
*r_usage = ask_key_flags (algo, addmode); *r_usage = ask_key_flags (algo, addmode, 0);
break; break;
} }
else if ((algo == 9 || !strcmp (answer, "ecc+ecc")) 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) else if ((algo == 11 || !strcmp (answer, "ecc/*")) && opt.expert)
{ {
algo = PUBKEY_ALGO_ECDSA; algo = PUBKEY_ALGO_ECDSA;
*r_usage = ask_key_flags (algo, addmode); *r_usage = ask_key_flags (algo, addmode, 0);
break; break;
} }
else if ((algo == 12 || !strcmp (answer, "ecc/e")) 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); xfree (keygrip);
keygrip = answer; keygrip = answer;
answer = NULL; answer = NULL;
*r_usage = ask_key_flags (algo, addmode); *r_usage = ask_key_flags (algo, addmode, 0);
break; break;
} }
else else

View File

@ -280,12 +280,14 @@ void show_basic_key_info (KBNODE keyblock);
u32 parse_expire_string(const char *string); u32 parse_expire_string(const char *string);
u32 ask_expire_interval(int object,const char *def_expire); u32 ask_expire_interval(int object,const char *def_expire);
u32 ask_expiredate(void); 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 quick_generate_keypair (ctrl_t ctrl, const char *uid);
void generate_keypair (ctrl_t ctrl, int full, const char *fname, void generate_keypair (ctrl_t ctrl, int full, const char *fname,
const char *card_serialno, int card_backup_key); const char *card_serialno, int card_backup_key);
int keygen_set_std_prefs (const char *string,int personal); int keygen_set_std_prefs (const char *string,int personal);
PKT_user_id *keygen_get_std_prefs (void); PKT_user_id *keygen_get_std_prefs (void);
int keygen_add_key_expire( PKT_signature *sig, void *opaque ); 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_add_std_prefs( PKT_signature *sig, void *opaque );
int keygen_upd_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); int keygen_add_keyserver_url(PKT_signature *sig, void *opaque);