347 lines
10 KiB
Diff
347 lines
10 KiB
Diff
|
diff -Naur gnupg-2.0.28-orig/g10/keyedit.c gnupg-2.0.28/g10/keyedit.c
|
||
|
--- gnupg-2.0.28-orig/g10/keyedit.c 2015-06-02 10:13:55.000000000 +0200
|
||
|
+++ gnupg-2.0.28/g10/keyedit.c 2015-09-28 11:40:08.216132804 +0200
|
||
|
@@ -62,6 +62,7 @@
|
||
|
static int menu_addrevoker( KBNODE pub_keyblock,
|
||
|
KBNODE sec_keyblock, int sensitive );
|
||
|
static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||
|
+static int menu_usage( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||
|
static int menu_backsign(KBNODE pub_keyblock,KBNODE sec_keyblock);
|
||
|
static int menu_set_primary_uid( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||
|
static int menu_set_preferences( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||
|
@@ -107,6 +108,11 @@
|
||
|
char *trust_regexp;
|
||
|
};
|
||
|
|
||
|
+/* Bad hack: Copy from keygen.c for menu_usage */
|
||
|
+struct opaque_data_usage_and_pk {
|
||
|
+ unsigned int usage;
|
||
|
+ PKT_public_key *pk;
|
||
|
+};
|
||
|
|
||
|
#ifdef ENABLE_CARD_SUPPORT
|
||
|
/* Given a node SEC_NODE with a secret key or subkey, locate the
|
||
|
@@ -1366,7 +1372,7 @@
|
||
|
cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
|
||
|
cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
|
||
|
cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
|
||
|
- cmdEXPIRE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
|
||
|
+ cmdEXPIRE, cmdUSAGE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
|
||
|
cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
|
||
|
cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCLEAN,
|
||
|
cmdMINIMIZE, cmdNOP
|
||
|
@@ -1436,6 +1442,8 @@
|
||
|
N_("delete signatures from the selected user IDs") },
|
||
|
{ "expire" , cmdEXPIRE , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||
|
N_("change the expiration date for the key or selected subkeys") },
|
||
|
+ { "usage" , cmdUSAGE , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||
|
+ N_("change the usage flag for the key or selected subkeys") },
|
||
|
{ "primary" , cmdPRIMARY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||
|
N_("flag the selected user ID as primary")},
|
||
|
{ "toggle" , cmdTOGGLE , KEYEDIT_NEED_SK,
|
||
|
@@ -2120,6 +2128,17 @@
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
+ case cmdUSAGE:
|
||
|
+ if( menu_usage( keyblock, sec_keyblock ) )
|
||
|
+ {
|
||
|
+ merge_keys_and_selfsig( sec_keyblock );
|
||
|
+ merge_keys_and_selfsig( keyblock );
|
||
|
+ sec_modified = 1;
|
||
|
+ modified = 1;
|
||
|
+ redisplay = 1;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
case cmdBACKSIGN:
|
||
|
if(menu_backsign(keyblock,sec_keyblock))
|
||
|
{
|
||
|
@@ -3792,6 +3811,286 @@
|
||
|
if( rc ) {
|
||
|
log_error("make_keysig_packet failed: %s\n",
|
||
|
g10_errstr(rc));
|
||
|
+ free_secret_key( sk );
|
||
|
+ 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;
|
||
|
+ if( sn ) {
|
||
|
+ newpkt = xmalloc_clear( sizeof *newpkt );
|
||
|
+ newpkt->pkttype = PKT_SIGNATURE;
|
||
|
+ newpkt->pkt.signature = copy_signature( NULL, newsig );
|
||
|
+ free_packet( sn->pkt );
|
||
|
+ xfree( sn->pkt );
|
||
|
+ sn->pkt = newpkt;
|
||
|
+ }
|
||
|
+ sub_pk = NULL;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ free_secret_key( sk );
|
||
|
+ update_trust=1;
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+/* Bad hack: Copy from keygen.c for menu_usage */
|
||
|
+static void
|
||
|
+print_key_flags(int flags)
|
||
|
+{
|
||
|
+ if(flags&PUBKEY_USAGE_SIG)
|
||
|
+ tty_printf("%s ",_("Sign"));
|
||
|
+
|
||
|
+ if(flags&PUBKEY_USAGE_CERT)
|
||
|
+ tty_printf("%s ",_("Certify"));
|
||
|
+
|
||
|
+ if(flags&PUBKEY_USAGE_ENC)
|
||
|
+ tty_printf("%s ",_("Encrypt"));
|
||
|
+
|
||
|
+ if(flags&PUBKEY_USAGE_AUTH)
|
||
|
+ tty_printf("%s ",_("Authenticate"));
|
||
|
+}
|
||
|
+
|
||
|
+/* Bad hack: Copy from keygen.c for menu_usage */
|
||
|
+static void
|
||
|
+do_add_key_flags (PKT_signature *sig, unsigned int use)
|
||
|
+{
|
||
|
+ byte buf[1];
|
||
|
+
|
||
|
+ buf[0] = 0;
|
||
|
+
|
||
|
+ /* The spec says that all primary keys MUST be able to certify. */
|
||
|
+ if(sig->sig_class!=0x18)
|
||
|
+ buf[0] |= 0x01;
|
||
|
+
|
||
|
+ if (use & PUBKEY_USAGE_SIG)
|
||
|
+ buf[0] |= 0x02;
|
||
|
+ if (use & PUBKEY_USAGE_ENC)
|
||
|
+ buf[0] |= 0x04 | 0x08;
|
||
|
+ if (use & PUBKEY_USAGE_AUTH)
|
||
|
+ buf[0] |= 0x20;
|
||
|
+
|
||
|
+ build_sig_subpkt (sig, SIGSUBPKT_KEY_FLAGS, buf, 1);
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+keygen_add_key_flags (PKT_signature *sig, void *opaque)
|
||
|
+{
|
||
|
+ struct opaque_data_usage_and_pk *oduap = opaque;
|
||
|
+
|
||
|
+ do_add_key_flags (sig, oduap->usage);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+/* Bad hack: Copy from keygen.c for menu_usage */
|
||
|
+static unsigned int
|
||
|
+ask_key_flags(int algo,int subkey)
|
||
|
+{
|
||
|
+ /* TRANSLATORS: Please use only plain ASCII characters for the
|
||
|
+ translation. If this is not possible use single digits. The
|
||
|
+ string needs to 8 bytes long. Here is a description of the
|
||
|
+ functions:
|
||
|
+
|
||
|
+ s = Toggle signing capability
|
||
|
+ e = Toggle encryption capability
|
||
|
+ a = Toggle authentication capability
|
||
|
+ q = Finish
|
||
|
+ */
|
||
|
+ const char *togglers=_("SsEeAaQq");
|
||
|
+ char *answer=NULL;
|
||
|
+ unsigned int current=0;
|
||
|
+ unsigned int possible=openpgp_pk_algo_usage(algo);
|
||
|
+
|
||
|
+ if ( strlen(togglers) != 8 )
|
||
|
+ {
|
||
|
+ tty_printf ("NOTE: Bad translation at %s:%d. "
|
||
|
+ "Please report.\n", __FILE__, __LINE__);
|
||
|
+ togglers = "11223300";
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Only primary keys may certify. */
|
||
|
+ if(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;
|
||
|
+
|
||
|
+ for(;;)
|
||
|
+ {
|
||
|
+ tty_printf("\n");
|
||
|
+ tty_printf(_("Possible actions for a %s key: "),
|
||
|
+ gcry_pk_algo_name (algo));
|
||
|
+ print_key_flags(possible);
|
||
|
+ tty_printf("\n");
|
||
|
+ tty_printf(_("Current allowed actions: "));
|
||
|
+ print_key_flags(current);
|
||
|
+ tty_printf("\n\n");
|
||
|
+
|
||
|
+ if(possible&PUBKEY_USAGE_SIG)
|
||
|
+ tty_printf(_(" (%c) Toggle the sign capability\n"),
|
||
|
+ togglers[0]);
|
||
|
+ if(possible&PUBKEY_USAGE_ENC)
|
||
|
+ tty_printf(_(" (%c) Toggle the encrypt capability\n"),
|
||
|
+ togglers[2]);
|
||
|
+ if(possible&PUBKEY_USAGE_AUTH)
|
||
|
+ tty_printf(_(" (%c) Toggle the authenticate capability\n"),
|
||
|
+ togglers[4]);
|
||
|
+
|
||
|
+ tty_printf(_(" (%c) Finished\n"),togglers[6]);
|
||
|
+ tty_printf("\n");
|
||
|
+
|
||
|
+ xfree(answer);
|
||
|
+ answer = cpr_get("keygen.flags",_("Your selection? "));
|
||
|
+ cpr_kill_prompt();
|
||
|
+
|
||
|
+ if(strlen(answer)>1)
|
||
|
+ tty_printf(_("Invalid selection.\n"));
|
||
|
+ else if(*answer=='\0' || *answer==togglers[6] || *answer==togglers[7])
|
||
|
+ break;
|
||
|
+ else if((*answer==togglers[0] || *answer==togglers[1])
|
||
|
+ && possible&PUBKEY_USAGE_SIG)
|
||
|
+ {
|
||
|
+ if(current&PUBKEY_USAGE_SIG)
|
||
|
+ current&=~PUBKEY_USAGE_SIG;
|
||
|
+ else
|
||
|
+ current|=PUBKEY_USAGE_SIG;
|
||
|
+ }
|
||
|
+ else if((*answer==togglers[2] || *answer==togglers[3])
|
||
|
+ && possible&PUBKEY_USAGE_ENC)
|
||
|
+ {
|
||
|
+ if(current&PUBKEY_USAGE_ENC)
|
||
|
+ current&=~PUBKEY_USAGE_ENC;
|
||
|
+ else
|
||
|
+ current|=PUBKEY_USAGE_ENC;
|
||
|
+ }
|
||
|
+ else if((*answer==togglers[4] || *answer==togglers[5])
|
||
|
+ && possible&PUBKEY_USAGE_AUTH)
|
||
|
+ {
|
||
|
+ if(current&PUBKEY_USAGE_AUTH)
|
||
|
+ current&=~PUBKEY_USAGE_AUTH;
|
||
|
+ else
|
||
|
+ current|=PUBKEY_USAGE_AUTH;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ tty_printf(_("Invalid selection.\n"));
|
||
|
+ }
|
||
|
+
|
||
|
+ xfree(answer);
|
||
|
+
|
||
|
+ return current;
|
||
|
+}
|
||
|
+
|
||
|
+/* Bad hack: mainly copy and paste of menu_expire */
|
||
|
+static int
|
||
|
+menu_usage( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
||
|
+{
|
||
|
+ int n1, signumber, rc;
|
||
|
+ unsigned int use;
|
||
|
+ int mainkey=0;
|
||
|
+ PKT_secret_key *sk; /* copy of the main sk */
|
||
|
+ PKT_public_key *main_pk, *sub_pk;
|
||
|
+ struct opaque_data_usage_and_pk oduap;
|
||
|
+ PKT_user_id *uid;
|
||
|
+ KBNODE node;
|
||
|
+ u32 keyid[2];
|
||
|
+
|
||
|
+ if( count_selected_keys( sec_keyblock ) ) {
|
||
|
+ tty_printf(_("Please remove selections from the secret keys.\n"));
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ n1 = count_selected_keys( pub_keyblock );
|
||
|
+ if( n1 > 1 ) {
|
||
|
+ tty_printf(_("Please select at most one subkey.\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;
|
||
|
+ no_primary_warning(pub_keyblock);
|
||
|
+ }
|
||
|
+
|
||
|
+ use = ask_key_flags(PUBKEY_ALGO_RSA, n1); /* TODO: algo abfragen und einsetzen */
|
||
|
+ node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
|
||
|
+ sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
|
||
|
+
|
||
|
+ /* Now we can actually change the self signature(s) */
|
||
|
+ main_pk = sub_pk = NULL;
|
||
|
+ uid = NULL;
|
||
|
+ signumber = 0;
|
||
|
+ for( node=pub_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
|
||
|
+ && (node->flag & NODFLG_SELKEY ) ) {
|
||
|
+ sub_pk = node->pkt->pkt.public_key;
|
||
|
+ }
|
||
|
+ 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 a selfsignature which is to be replaced */
|
||
|
+ PKT_signature *newsig;
|
||
|
+ PACKET *newpkt;
|
||
|
+ KBNODE sn;
|
||
|
+ int signumber2 = 0;
|
||
|
+
|
||
|
+ signumber++;
|
||
|
+
|
||
|
+ if( (mainkey && main_pk->version < 4)
|
||
|
+ || (!mainkey && sub_pk->version < 4 ) ) {
|
||
|
+ log_info(_(
|
||
|
+ "You can't change the expiration date of a v3 key\n"));
|
||
|
+ free_secret_key( sk );
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* find the corresponding secret self-signature */
|
||
|
+ for( sn=sec_keyblock; sn; sn = sn->next ) {
|
||
|
+ if( sn->pkt->pkttype == PKT_SIGNATURE ) {
|
||
|
+ PKT_signature *b = sn->pkt->pkt.signature;
|
||
|
+ if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
|
||
|
+ && sig->sig_class == b->sig_class
|
||
|
+ && ++signumber2 == signumber )
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ if( !sn )
|
||
|
+ log_info(_("No corresponding signature in secret ring\n"));
|
||
|
+
|
||
|
+ if( mainkey ) {
|
||
|
+ oduap.usage = use;
|
||
|
+ oduap.pk = main_pk;
|
||
|
+ rc = update_keysig_packet(&newsig, sig, main_pk, uid, NULL,
|
||
|
+ sk, keygen_add_key_flags, &oduap);
|
||
|
+ }
|
||
|
+ else {
|
||
|
+ oduap.usage = use;
|
||
|
+ oduap.pk = sub_pk;
|
||
|
+ rc = update_keysig_packet(&newsig, sig, main_pk, NULL, sub_pk,
|
||
|
+ sk, keygen_add_key_flags, &oduap);
|
||
|
+ }
|
||
|
+ if( rc ) {
|
||
|
+ log_error("make_keysig_packet failed: %s\n",
|
||
|
+ g10_errstr(rc));
|
||
|
free_secret_key( sk );
|
||
|
return 0;
|
||
|
}
|