]> granicus.if.org Git - neomutt/commitdiff
Allow short and long key ID user input in pgp_getkeybystr()
authorEike Rathke <erack@erack.de>
Sun, 18 Jan 2015 16:45:41 +0000 (17:45 +0100)
committerEike Rathke <erack@erack.de>
Sun, 18 Jan 2015 16:45:41 +0000 (17:45 +0100)
The following did not work, e.g. when leaving a key list, and at the "Sign as"
or "Encrypt to" prompt attempting to enter a key ID:
* set pgp_long_ids=no
  * enter a long key ID, with or without leading 0x
* set pgp_long_ids=yes
  * enter a short key ID without leading 0x

Specifically entering a long key ID should always be possible as evil32.com
has shown.

This also cleans up the logic used to determine the matching condition, which
was quite convoluted.. it even slightly speeds up the loop as less string
operations are involved in the inner condition.

This only changes how the result obtained from the pgp_* command line
interface is filtered.

pgp.c
pgp.h
pgpkey.c

diff --git a/pgp.c b/pgp.c
index c0a5d8fa8e9083c116c82d853b9dcf0f16de086a..c8ac07fdb44fabcb5f88a251c985bdd3db74643a 100644 (file)
--- a/pgp.c
+++ b/pgp.c
@@ -117,11 +117,32 @@ int pgp_use_gpg_agent (void)
   return 1;
 }
 
-char *pgp_keyid(pgp_key_t k)
+static pgp_key_t _pgp_parent(pgp_key_t k)
 {
   if((k->flags & KEYFLAG_SUBKEY) && k->parent && option(OPTPGPIGNORESUB))
     k = k->parent;
 
+  return k;
+}
+
+char *pgp_long_keyid(pgp_key_t k)
+{
+  k = _pgp_parent(k);
+
+  return k->keyid;
+}
+
+char *pgp_short_keyid(pgp_key_t k)
+{
+  k = _pgp_parent(k);
+
+  return k->keyid + 8;
+}
+
+char *pgp_keyid(pgp_key_t k)
+{
+  k = _pgp_parent(k);
+
   return _pgp_keyid(k);
 }
 
diff --git a/pgp.h b/pgp.h
index 2d98e14edc2712df6b77fdd310c15a35cb1d69fd..7b60e1b3f8307aae60caa17f4149dc889b5d46ff 100644 (file)
--- a/pgp.h
+++ b/pgp.h
@@ -35,6 +35,8 @@ 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);
 
 
 int mutt_check_pgp (HEADER * h);
index dcc8c76cb479c84891e6625fc23cfc1c6f617b7f..26be753b6957d715e6437010340cbf1560249cc0 100644 (file)
--- a/pgpkey.c
+++ b/pgpkey.c
@@ -932,6 +932,7 @@ pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
   pgp_uid_t *a;
   short match;
   size_t l;
+  const char *ps, *pl;
 
   if ((l = mutt_strlen (p)) && p[l-1] == '!')
     p[l-1] = 0;
@@ -945,6 +946,19 @@ pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
   if (!keys)
     goto out;
 
+  /* User input may be short or long key ID, independent of OPTPGPLONGIDS.
+   * pgp_key_t->keyid should always contain a long key ID without 0x.
+   * Strip leading "0x" before loops so it doesn't have to be done over and
+   * over again, and prepare pl and ps to simplify logic in the loop's inner
+   * condition.
+   */
+  pl = (!mutt_strncasecmp (p, "0x", 2) ? p + 2 : p);
+  ps = (mutt_strlen (pl) == 16 ? pl + 8 : pl);
+
+  /* If ps != pl it means a long ID (or name of 16 characters) was given, do
+   * not attempt to match short IDs then. Also, it is unnecessary to try to
+   * match pl against long IDs if ps == pl as pl could not be a long ID. */
+
   for (k = keys; k; k = kn)
   {
     kn = k->next;
@@ -956,11 +970,10 @@ pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
     for (a = k->address; a; a = a->next)
     {
       dprint (5, (debugfile, "pgp_getkeybystr: matching \"%s\" against key %s, \"%s\": ",
-                 p, pgp_keyid (k), NONULL (a->addr)));
-      if (!*p || mutt_strcasecmp (p, pgp_keyid (k)) == 0 ||
-         (!mutt_strncasecmp (p, "0x", 2) && !mutt_strcasecmp (p + 2, pgp_keyid (k))) ||
-         (option (OPTPGPLONGIDS) && !mutt_strncasecmp (p, "0x", 2) &&
-          !mutt_strcasecmp (p + 2, k->keyid + 8)) ||
+                  p, pgp_long_keyid (k), NONULL (a->addr)));
+      if (!*p ||
+          (ps != pl && mutt_strcasecmp (pl, pgp_long_keyid (k)) == 0) ||
+          (ps == pl && mutt_strcasecmp (ps, pgp_short_keyid (k)) == 0) ||
          mutt_stristr (a->addr, p))
       {
        dprint (5, (debugfile, "match.\n"));