unitas/app-crypt/gnupg/files/gnupg-2.0.28-change_usage.p...

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;
}