Now that we have fingerprint in the pgp_key_t structure, this patch
switches to using the fingerprint where available (and the long key-id
otherwise) for things like pgp-command invocations.

I'll probably wait until the oppenc series is committed to push this
one, because the two patches step on each other a bit.  But I wanted to
send this out for review and comments.

-Kevin
# HG changeset patch
# User Kevin McCarthy <[email protected]>
# Date 1424896437 28800
#      Wed Feb 25 12:33:57 2015 -0800
# Node ID af05d4354d4884987a2dc558d2e6747719a5c107
# Parent  71f12fef8c6f9d4ae3f8eb8db081bfacd8838869
Use fingerprints instead of keyid internally. (see #3695)

Add a helper function, pgp_fpr_or_lkeyid(), that returns the fingerprint
if available, otherwise falls back to the long key id.  Convert Mutt to
use that value for pgp command invocation.

Update documentation to mention and recommend fingerprints.

Change gpgme to use an equivalent crypt_fpr_or_lkeyid() function in a
couple places too (for keylist generation and sign-as key selection).

diff --git a/crypt-gpgme.c b/crypt-gpgme.c
--- a/crypt-gpgme.c
+++ b/crypt-gpgme.c
@@ -214,16 +214,34 @@
   const char *s = "";
 
   if (k->kobj && k->kobj->subkeys)
     s = k->kobj->subkeys->fpr;
 
   return s;
 }
 
+/* Returns the fingerprint if available, otherwise
+ * returns the long keyid.
+ */
+static const char *crypt_fpr_or_lkeyid(crypt_key_t *k)
+{
+  const char *s = "????????????????";
+
+  if (k->kobj && k->kobj->subkeys)
+  {
+    if (k->kobj->subkeys->fpr)
+      s = k->kobj->subkeys->fpr;
+    else
+      s = k->kobj->subkeys->keyid;
+  }
+
+  return s;
+}
+
 /* Parse FLAGS and return a statically allocated(!) string with them. */
 static char *crypt_key_abilities (int flags)
 {
   static char buff[3];
 
   if (!(flags & KEYFLAG_CANENCRYPT))
     buff[0] = '-';
   else if (flags & KEYFLAG_PREFER_SIGNING)
@@ -4406,17 +4424,17 @@
               rfc822_free_address (&addr);
               return NULL;
             }
         }
       else
         key = k_info;
 
       {
-        const char *s = crypt_fpr (key);
+        const char *s = crypt_fpr_or_lkeyid (key);
 
 #if 0
         if (key->flags & KEYFLAG_ISX509)
           *r_application &= ~APPLICATION_PGP;
         if (!(key->flags & KEYFLAG_ISX509))
           *r_application &= ~APPLICATION_SMIME;
 #endif
       
@@ -4591,17 +4609,18 @@
     break;
 
   case 3: /* sign (a)s */
 /*      unset_option(OPTCRYPTCHECKTRUST); */
     if ((p = crypt_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
                                 is_smime? APPLICATION_SMIME:APPLICATION_PGP,
                                 NULL)))
     {
-      snprintf (input_signas, sizeof (input_signas), "0x%s", crypt_keyid (p));
+      snprintf (input_signas, sizeof (input_signas), "0x%s",
+          crypt_fpr_or_lkeyid (p));
       mutt_str_replace (is_smime? &SmimeDefaultKey : &PgpSignAs, input_signas);
       crypt_free_key (&p); 
       
       msg->security |= (is_smime? SMIMESIGN:PGPSIGN);
     }
 #if 0
     else
     {
diff --git a/doc/manual.xml.head b/doc/manual.xml.head
--- a/doc/manual.xml.head
+++ b/doc/manual.xml.head
@@ -3630,18 +3630,18 @@
 destination address, or because, for some reasons, you need to override
 the key Mutt would normally use.  The <command>crypt-hook</command>
 command provides a method by which you can specify the ID of the public
 key to be used when encrypting messages to a certain recipient.
 </para>
 
 <para>
 The meaning of <emphasis>keyid</emphasis> is to be taken broadly in this
-context: You can either put a numerical key ID here, an e-mail address,
-or even just a real name.
+context: You can either put a numerical key ID or fingerprint here, an
+e-mail address, or even just a real name.
 </para>
 
 </sect1>
 
 <sect1 id="push">
 <title>Adding Key Sequences to the Keyboard Buffer</title>
 
 <para>Usage:</para>
diff --git a/init.h b/init.h
--- a/init.h
+++ b/init.h
@@ -1716,17 +1716,17 @@
   ** The PGP command formats have their own set of \fCprintf(3)\fP-like 
sequences:
   ** .dl
   ** .dt %p .dd Expands to PGPPASSFD=0 when a pass phrase is needed, to an 
empty
   **            string otherwise. Note: This may be used with a %? construct.
   ** .dt %f .dd Expands to the name of a file containing a message.
   ** .dt %s .dd Expands to the name of a file containing the signature part
   ** .          of a \fCmultipart/signed\fP attachment when verifying it.
   ** .dt %a .dd The value of $$pgp_sign_as.
-  ** .dt %r .dd One or more key IDs.
+  ** .dt %r .dd One or more key IDs (or fingerprints if available).
   ** .de
   ** .pp
   ** For examples on how to configure these formats for the various versions
   ** of PGP which are floating around, see the pgp and gpg sample 
configuration files in
   ** the \fCsamples/\fP subdirectory which has been installed on your system
   ** alongside the documentation.
   ** (PGP only)
   */
@@ -1825,33 +1825,33 @@
   ** (PGP only)
   */
   { "pgp_list_pubring_command", DT_STR, R_NONE, UL &PgpListPubringCommand, 0},
   /*
   ** .pp
   ** This command is used to list the public key ring's contents.  The
   ** output format must be analogous to the one used by
   ** .ts
-  ** gpg --list-keys --with-colons
+  ** gpg --list-keys --with-colons --with-fingerprint
   ** .te
   ** .pp
   ** This format is also generated by the \fCpgpring\fP utility which comes
   ** with mutt.
   ** .pp
   ** This is a format string, see the $$pgp_decode_command command for
   ** possible \fCprintf(3)\fP-like sequences.
   ** (PGP only)
   */
   { "pgp_list_secring_command",        DT_STR, R_NONE, UL 
&PgpListSecringCommand, 0},
   /*
   ** .pp
   ** This command is used to list the secret key ring's contents.  The
   ** output format must be analogous to the one used by:
   ** .ts
-  ** gpg --list-keys --with-colons
+  ** gpg --list-keys --with-colons --with-fingerprint
   ** .te
   ** .pp
   ** This format is also generated by the \fCpgpring\fP utility which comes
   ** with mutt.
   ** .pp
   ** This is a format string, see the $$pgp_decode_command command for
   ** possible \fCprintf(3)\fP-like sequences.
   ** (PGP only)
@@ -1916,17 +1916,18 @@
   ** have been marked as ``disabled'' by the user.
   ** (PGP only)
   */
   { "pgp_sign_as",     DT_STR,  R_NONE, UL &PgpSignAs, 0 },
   /*
   ** .pp
   ** If you have more than one key pair, this option allows you to specify
   ** which of your private keys to use.  It is recommended that you use the
-  ** keyid form to specify your key (e.g. \fC0x00112233\fP).
+  ** fingerprint form to specify your key
+  ** (e.g. \fC0x0001020304050607080910111213141516171819\fP).
   ** (PGP only)
   */
   { "pgp_sign_command",                DT_STR, R_NONE, UL &PgpSignCommand, 0},
   /*
   ** .pp
   ** This command is used to create the detached PGP signature for a
   ** \fCmultipart/signed\fP PGP/MIME body part.
   ** .pp
@@ -2129,18 +2130,18 @@
   ** When \fIset\fP, postponed messages that are marked for encryption will be
   ** encrypted using the key in $$postpone_encrypt_as before saving.
   ** (Crypto only)
   */
   { "postpone_encrypt_as", DT_STR,  R_NONE, UL &PostponeEncryptAs, 0 },
   /*
   ** .pp
   ** This is the key used to encrypt postponed messages.  It should be in
-  ** keyid form (e.g. 0x00112233 for PGP or the hash-value that OpenSSL
-  ** generates for S/MIME).
+  ** keyid or fingerprint form (e.g. 0x00112233 for PGP or the
+  ** hash-value that OpenSSL generates for S/MIME).
   ** (Crypto only)
   */
 #ifdef USE_SOCKET
   { "preconnect",      DT_STR, R_NONE, UL &Preconnect, UL 0},
   /*
   ** .pp
   ** If \fIset\fP, a shell command to be executed if mutt fails to establish
   ** a connection to the server. This is useful for setting up secure
diff --git a/pgp.c b/pgp.c
--- a/pgp.c
+++ b/pgp.c
@@ -150,16 +150,37 @@
 char *_pgp_keyid(pgp_key_t k)
 {
   if(option(OPTPGPLONGIDS))
     return k->keyid;
   else
     return (k->keyid + 8);
 }
 
+char *pgp_fingerprint(pgp_key_t k)
+{
+  k = _pgp_parent(k);
+
+  return k->fingerprint;
+}
+
+/* Grab the longest key identifier available: fingerprint or else
+ * the long keyid.
+ *
+ * The longest available should be used for internally identifying
+ * the key and for invoking pgp commands.
+ */
+char *pgp_fpr_or_lkeyid(pgp_key_t k)
+{
+  char *fingerprint;
+
+  fingerprint = pgp_fingerprint (k);
+  return fingerprint ? fingerprint : pgp_long_keyid (k);
+}
+
 /* ----------------------------------------------------------------------------
  * Routines for handing PGP input.
  */
 
 
 
 /* Copy PGP output messages and look for signs of a good signature */
 
@@ -1257,17 +1278,17 @@
        rfc822_free_address (&tmp);
        rfc822_free_address (&addr);
        return NULL;
       }
     }
     else
       key = k_info;
 
-    keyID = pgp_keyid (key);
+    keyID = pgp_fpr_or_lkeyid (key);
     
   bypass_selection:
     keylist_size += mutt_strlen (keyID) + 4;
     safe_realloc (&keylist, keylist_size);
     sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "",        
/* __SPRINTF_CHECKED__ */
             keyID);
     keylist_used = mutt_strlen (keylist);
 
@@ -1645,17 +1666,17 @@
       pgp_key_t p;
       char input_signas[SHORT_STRING];
 
       unset_option(OPTPGPCHECKTRUST);
 
       if ((p = pgp_ask_for_key (_("Sign as: "), NULL, 0, PGP_SECRING)))
       {
        snprintf (input_signas, sizeof (input_signas), "0x%s",
-           pgp_keyid (p));
+           pgp_fpr_or_lkeyid (p));
        mutt_str_replace (&PgpSignAs, input_signas);
        pgp_free_key (&p);
 
        msg->security |= SIGN;
 
        crypt_pgp_void_passphrase ();  /* probably need a different passphrase 
*/
       }
 #if 0
diff --git a/pgp.h b/pgp.h
--- a/pgp.h
+++ b/pgp.h
@@ -32,16 +32,18 @@
 BODY *pgp_decrypt_part (BODY *, STATE *, FILE *, BODY *);
 BODY *pgp_make_key_attachment (char *);
 const char *pgp_micalg (const char *fname);
 
 char *_pgp_keyid (pgp_key_t);
 char *pgp_keyid (pgp_key_t);
 char *pgp_short_keyid (pgp_key_t);
 char *pgp_long_keyid (pgp_key_t);
+char *pgp_fingerprint (pgp_key_t k);
+char *pgp_fpr_or_lkeyid (pgp_key_t k);
 
 
 int mutt_check_pgp (HEADER * h);
 
 int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **);
 
 /* int pgp_string_matches_hint (const char *s, LIST * hints); */
 
diff --git a/pgpkey.c b/pgpkey.c
--- a/pgpkey.c
+++ b/pgpkey.c
@@ -557,17 +557,18 @@
       {
        safe_fclose (&devnull);
        mutt_perror _("Can't create temporary file");
        break;
       }
 
       mutt_message _("Invoking PGP...");
 
-      snprintf (tmpbuf, sizeof (tmpbuf), "0x%s", pgp_keyid (pgp_principal_key 
(KeyTable[menu->current]->parent)));
+      snprintf (tmpbuf, sizeof (tmpbuf), "0x%s",
+          pgp_fpr_or_lkeyid (pgp_principal_key 
(KeyTable[menu->current]->parent)));
 
       if ((thepid = pgp_invoke_verify_key (NULL, NULL, NULL, -1,
                    fileno (fp), fileno (devnull), tmpbuf)) == -1)
       {
        mutt_perror _("Can't create filter");
        unlink (tempfile);
        safe_fclose (&fp);
        safe_fclose (&devnull);
@@ -720,17 +721,17 @@
   pid_t thepid;
   pgp_key_t key;
   unset_option (OPTPGPCHECKTRUST);
 
   key = pgp_ask_for_key (_("Please enter the key ID: "), NULL, 0, PGP_PUBRING);
 
   if (!key)    return NULL;
 
-  snprintf (tmp, sizeof (tmp), "0x%s", pgp_keyid (pgp_principal_key (key)));
+  snprintf (tmp, sizeof (tmp), "0x%s", pgp_fpr_or_lkeyid (pgp_principal_key 
(key)));
   pgp_free_key (&key);
 
   if (!tempf)
   {
     mutt_mktemp (tempfb, sizeof (tempfb));
     tempf = tempfb;
   }
 

Attachment: signature.asc
Description: PGP signature

Reply via email to