[Pkg-gnupg-commit] [gnupg2] 28/205: gpg: Add hidden key-edit subcommand "change-usage".

Daniel Kahn Gillmor dkg at fifthhorseman.net
Wed May 11 08:38:11 UTC 2016


This is an automated email from the git hooks/post-receive script.

dkg pushed a commit to branch experimental
in repository gnupg2.

commit 9b28b82e7c40d1eacc446d5932cd613c56378ed8
Author: Werner Koch <wk at gnupg.org>
Date:   Sun Feb 14 15:50:12 2016 +0100

    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 at gnupg.org>
---
 g10/keyedit.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 g10/keygen.c  |  36 +++++++++++++-----
 g10/main.h    |   2 +
 3 files changed, 146 insertions(+), 11 deletions(-)

diff --git a/g10/keyedit.c b/g10/keyedit.c
index 30f52a4..19ddf29 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 0f7a6a0..7b5a35b 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 ec24426..863afa9 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);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git



More information about the Pkg-gnupg-commit mailing list