From d38a98208574e41af522be69d88b4a9ffdd39caf Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Wed, 15 Apr 2015 18:57:17 -0700 Subject: [PATCH] Use fingerprints instead of keyIDs 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. Change gpgme to use an equivalent crypt_fpr_or_lkeyid() function in a couple places too (for keylist generation and sign-as key selection). Update documentation to mention fingerprints and the --with-fingerprint option for gpg invocation. Change pgp_long_ids to default: yes, but add a note mentioning it's only used for the display of key IDs in a few places. --- crypt-gpgme.c | 29 ++++++++++++++++++++++++----- doc/manual.xml.head | 4 ++-- init.h | 15 +++++++++------ pgp.c | 25 +++++++++++++++++++++++-- pgp.h | 2 ++ pgpkey.c | 17 +++++++++-------- 6 files changed, 69 insertions(+), 23 deletions(-) diff --git a/crypt-gpgme.c b/crypt-gpgme.c index e165ab81a..9d00d4d17 100644 --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -219,6 +219,24 @@ static const char *crypt_fpr (crypt_key_t *k) 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) { @@ -2900,7 +2918,7 @@ static int _crypt_compare_address (const void *a, const void *b) if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid))) return r > 0; else - return mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)) > 0; + return mutt_strcasecmp (crypt_fpr_or_lkeyid (*s), crypt_fpr_or_lkeyid (*t)) > 0; } static int crypt_compare_address (const void *a, const void *b) @@ -2917,7 +2935,7 @@ static int _crypt_compare_keyid (const void *a, const void *b) crypt_key_t **t = (crypt_key_t **) b; int r; - if ((r = mutt_strcasecmp (crypt_keyid (*s), crypt_keyid (*t)))) + if ((r = mutt_strcasecmp (crypt_fpr_or_lkeyid (*s), crypt_fpr_or_lkeyid (*t)))) return r > 0; else return mutt_strcasecmp ((*s)->uid, (*t)->uid) > 0; @@ -2991,7 +3009,7 @@ static int _crypt_compare_trust (const void *a, const void *b) if ((r = mutt_strcasecmp ((*s)->uid, (*t)->uid))) return r > 0; - return (mutt_strcasecmp (crypt_keyid ((*s)), crypt_keyid ((*t)))) > 0; + return (mutt_strcasecmp (crypt_fpr_or_lkeyid ((*s)), crypt_fpr_or_lkeyid ((*t)))) > 0; } static int crypt_compare_trust (const void *a, const void *b) @@ -4432,7 +4450,7 @@ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode) } - keyID = crypt_fpr (k_info); + keyID = crypt_fpr_or_lkeyid (k_info); #if 0 if (k_info->flags & KEYFLAG_ISX509) @@ -4672,7 +4690,8 @@ static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime) 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); diff --git a/doc/manual.xml.head b/doc/manual.xml.head index 8a4601e2d..9b45cca91 100644 --- a/doc/manual.xml.head +++ b/doc/manual.xml.head @@ -3637,8 +3637,8 @@ key to be used when encrypting messages to a certain recipient. The meaning of keyid 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. diff --git a/init.h b/init.h index 92ede4811..9d938f75e 100644 --- a/init.h +++ b/init.h @@ -1742,7 +1742,7 @@ struct option_t MuttVars[] = { ** .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 @@ -1851,7 +1851,7 @@ struct option_t MuttVars[] = { ** 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 @@ -1867,7 +1867,7 @@ struct option_t MuttVars[] = { ** 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 @@ -1877,10 +1877,13 @@ struct option_t MuttVars[] = { ** possible \fCprintf(3)\fP-like sequences. ** (PGP only) */ - { "pgp_long_ids", DT_BOOL, R_NONE, OPTPGPLONGIDS, 0 }, + { "pgp_long_ids", DT_BOOL, R_NONE, OPTPGPLONGIDS, 1 }, /* ** .pp ** If \fIset\fP, use 64 bit PGP key IDs, if \fIunset\fP use the normal 32 bit key IDs. + ** NOTE: Internally, Mutt has transitioned to using fingerprints (or long key IDs + ** as a fallback). This option now only controls the display of key IDs + ** in the key selection menu and a few other places. ** (PGP only) */ { "pgp_mime_auto", DT_QUAD, R_NONE, OPT_PGPMIMEAUTO, M_ASKYES }, @@ -2155,8 +2158,8 @@ struct option_t MuttVars[] = { /* ** .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 diff --git a/pgp.c b/pgp.c index ddc1e35ce..dafd0ff9a 100644 --- a/pgp.c +++ b/pgp.c @@ -156,6 +156,27 @@ char *_pgp_keyid(pgp_key_t k) 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. */ @@ -1247,7 +1268,7 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode) return NULL; } - keyID = pgp_keyid (k_info); + keyID = pgp_fpr_or_lkeyid (k_info); bypass_selection: keylist_size += mutt_strlen (keyID) + 4; @@ -1690,7 +1711,7 @@ int pgp_send_menu (HEADER *msg, int *redraw) 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); diff --git a/pgp.h b/pgp.h index 46a54846b..9b2a09e61 100644 --- a/pgp.h +++ b/pgp.h @@ -37,6 +37,8 @@ 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); diff --git a/pgpkey.c b/pgpkey.c index 083e8c02e..2aaab9c8c 100644 --- a/pgpkey.c +++ b/pgpkey.c @@ -306,8 +306,8 @@ static int _pgp_compare_address (const void *a, const void *b) if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr))) return r > 0; else - return (mutt_strcasecmp (_pgp_keyid ((*s)->parent), - _pgp_keyid ((*t)->parent)) > 0); + return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), + pgp_fpr_or_lkeyid ((*t)->parent)) > 0); } static int pgp_compare_address (const void *a, const void *b) @@ -325,8 +325,8 @@ static int _pgp_compare_keyid (const void *a, const void *b) pgp_uid_t **s = (pgp_uid_t **) a; pgp_uid_t **t = (pgp_uid_t **) b; - if ((r = mutt_strcasecmp (_pgp_keyid ((*s)->parent), - _pgp_keyid ((*t)->parent)))) + if ((r = mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), + pgp_fpr_or_lkeyid ((*t)->parent)))) return r > 0; else return (mutt_strcasecmp ((*s)->addr, (*t)->addr)) > 0; @@ -373,8 +373,8 @@ static int _pgp_compare_trust (const void *a, const void *b) return r < 0; if ((r = mutt_strcasecmp ((*s)->addr, (*t)->addr))) return r > 0; - return (mutt_strcasecmp (_pgp_keyid ((*s)->parent), - _pgp_keyid ((*t)->parent))) > 0; + return (mutt_strcasecmp (pgp_fpr_or_lkeyid ((*s)->parent), + pgp_fpr_or_lkeyid ((*t)->parent))) > 0; } static int pgp_compare_trust (const void *a, const void *b) @@ -562,7 +562,8 @@ static pgp_key_t pgp_select_key (pgp_key_t keys, 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) @@ -725,7 +726,7 @@ BODY *pgp_make_key_attachment (char *tempf) 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) -- 2.50.1