]> granicus.if.org Git - neomutt/commitdiff
Implement oppenc_mode in the find_keys methods.
authorKevin McCarthy <kevin@8t8.us>
Mon, 30 Mar 2015 22:45:52 +0000 (15:45 -0700)
committerKevin McCarthy <kevin@8t8.us>
Mon, 30 Mar 2015 22:45:52 +0000 (15:45 -0700)
oppenc_mode is used by crypt_opportunistic_encrypt to determine whether
there are valid keys for all recipients of a message, without prompting
the user.

The patch wraps around prompts, and makes getkeybyaddr methods return a
valid address-matching key without prompting.

The patch also fixes a small problem with gpgme's getkeybyaddr.  When
determining if there were multiple strong matches, it was comparing the
crypt_key_t instead of its kobj member (gpgme_key_t).

The patch also enables a call to crypt_is_numerical_keyid() in
find_keys(), so that crypt-hooks can actually be checked without
prompting when gpgme is enabled.  (The addition was patterned off of the
pgp_findKeys() function).

crypt-gpgme.c
pgp.c
pgp.h
pgpkey.c
smime.c

index 1aa96d4a3483543db84386271b0932d9baab7c63..78b4a967beaacc73468b1e333ad9b9e1767590e7 100644 (file)
@@ -4052,21 +4052,25 @@ static crypt_key_t *crypt_select_key (crypt_key_t *keys,
 }
 
 static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
-                                       unsigned int app, int *forced_valid)
+                                       unsigned int app, int *forced_valid,
+                                       int oppenc_mode)
 {
   ADDRESS *r, *p;
   LIST *hints = NULL;
 
   int weak    = 0;
   int invalid = 0;
+  int addr_match = 0;
   int multi   = 0;
   int this_key_has_strong;
+  int this_key_has_addr_match;
   int this_key_has_weak;
   int this_key_has_invalid;
   int match;
 
   crypt_key_t *keys, *k;
-  crypt_key_t *the_valid_key = NULL;
+  crypt_key_t *the_strong_valid_key = NULL;
+  crypt_key_t *a_valid_addrmatch_key = NULL;
   crypt_key_t *matches = NULL;
   crypt_key_t **matches_endp = &matches;
   
@@ -4077,7 +4081,8 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
   if (a && a->personal)
     hints = crypt_add_string_to_hints (hints, a->personal);
 
-  mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
+  if (! oppenc_mode )
+    mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) );
 
   mutt_free_list (&hints);
@@ -4103,6 +4108,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
       this_key_has_weak    = 0;        /* weak but valid match   */
       this_key_has_invalid = 0;   /* invalid match          */
       this_key_has_strong  = 0;        /* strong and valid match */
+      this_key_has_addr_match = 0;
       match                = 0;   /* any match                   */
 
       r = rfc822_parse_adrlist (NULL, k->uid);
@@ -4111,25 +4117,29 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
           int validity = crypt_id_matches_addr (a, p, k);
               
           if (validity & CRYPT_KV_MATCH)       /* something matches */
+          {
             match = 1;
 
-          /* is this key a strong candidate? */
-          if ((validity & CRYPT_KV_VALID)
-              && (validity & CRYPT_KV_STRONGID) 
-              && (validity & CRYPT_KV_ADDR))
+            if (validity & CRYPT_KV_VALID)
             {
-              if (the_valid_key && the_valid_key != k)
-                multi             = 1;
-              the_valid_key       = k;
-              this_key_has_strong = 1;
+              if (validity & CRYPT_KV_ADDR)
+              {
+                if (validity & CRYPT_KV_STRONGID)
+                {
+                  if (the_strong_valid_key
+                      && the_strong_valid_key->kobj != k->kobj)
+                    multi             = 1;
+                  this_key_has_strong = 1;
+                }
+                else
+                  this_key_has_addr_match = 1;
+              }
+              else
+                this_key_has_weak = 1;
             }
-          else if ((validity & CRYPT_KV_MATCH)
-                   && !(validity & CRYPT_KV_VALID))
-            this_key_has_invalid = 1;
-          else if ((validity & CRYPT_KV_MATCH) 
-                   && (!(validity & CRYPT_KV_STRONGID)
-                       || !(validity & CRYPT_KV_ADDR)))
-            this_key_has_weak    = 1;
+            else
+              this_key_has_invalid = 1;
+          }
         }
       rfc822_free_address (&r);
       
@@ -4137,14 +4147,20 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
         {
           crypt_key_t *tmp;
 
-          if (!this_key_has_strong && this_key_has_invalid)
-            invalid = 1;
-          if (!this_key_has_strong && this_key_has_weak)
-            weak = 1;
-
           *matches_endp = tmp = crypt_copy_key (k);
           matches_endp = &tmp->next;
-         the_valid_key = tmp;
+
+          if (this_key_has_strong)
+            the_strong_valid_key = tmp;
+          else if (this_key_has_addr_match)
+          {
+            addr_match = 1;
+            a_valid_addrmatch_key = tmp;
+          }
+          else if (this_key_has_invalid)
+            invalid = 1;
+          else if (this_key_has_weak)
+            weak = 1;
         }
     }
   
@@ -4152,7 +4168,16 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
   
   if (matches)
     {
-      if (the_valid_key && !multi && !weak 
+      if (oppenc_mode)
+        {
+          if (the_strong_valid_key)
+            k = crypt_copy_key (the_strong_valid_key);
+          else if (a_valid_addrmatch_key)
+            k = crypt_copy_key (a_valid_addrmatch_key);
+          else
+            k = NULL;
+        }
+      else if (the_strong_valid_key && !multi && !weak && !addr_match
           && !(invalid && option (OPTPGPSHOWUNUSABLE)))
         {      
           /* 
@@ -4162,7 +4187,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
            * 
            * Proceed without asking the user.
            */
-          k = crypt_copy_key (the_valid_key);
+          k = crypt_copy_key (the_strong_valid_key);
         }
       else 
         {
@@ -4171,6 +4196,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
            */
           k = crypt_select_key (matches, a, NULL, app, forced_valid);
         }
+
       crypt_free_key (&matches);
     }
   else 
@@ -4180,7 +4206,7 @@ static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
 }
 
 
-static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
+static crypt_key_t *crypt_getkeybystr (const char *p, short abilities,
                                       unsigned int app, int *forced_valid)
 {
   LIST *hints = NULL;
@@ -4310,12 +4336,13 @@ static crypt_key_t *crypt_ask_for_key (char *tag,
    prompting will be used.  */
 static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode)
 {
-  char *keyID, *keylist = NULL, *t;
+  const char *keyID = NULL;
+  char *keylist = NULL, *t;
   size_t keylist_size = 0;
   size_t keylist_used = 0;
   ADDRESS *addr = NULL;
   ADDRESS *p, *q;
-  crypt_key_t *k_info, *key;
+  crypt_key_t *k_info;
   const char *fqdn = mutt_fqdn (1);
 
 #if 0
@@ -4332,11 +4359,22 @@ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode)
       
       if ((keyID = mutt_crypt_hook (p)) != NULL)
         {
-          int r;
-          snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
-                    keyID, p->mailbox);
-          if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
+          int r = M_NO;
+          if (! oppenc_mode)
+            {
+              snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
+                        keyID, p->mailbox);
+              r = mutt_yesorno (buf, M_YES);
+            }
+          if (oppenc_mode || (r == M_YES))
             {
+              if (crypt_is_numerical_keyid (keyID))
+                {
+                  if (strncmp (keyID, "0x", 2) == 0)
+                    keyID += 2;
+                  goto bypass_selection;                /* you don't see this. */
+                }
+
               /* check for e-mail address */
               if ((t = strchr (keyID, '@')) && 
                   (addr = rfc822_parse_adrlist (NULL, keyID)))
@@ -4345,7 +4383,7 @@ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode)
                     rfc822_qualify (addr, fqdn);
                   q = addr;
                 }
-              else
+              else if (! oppenc_mode)
                {
 #if 0            
                  k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, 
@@ -4364,48 +4402,52 @@ static char *find_keys (ADDRESS *adrlist, unsigned int app, int oppenc_mode)
             }
         }
 
-      if (k_info == NULL
-          && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
-                                           app, &forced_valid)) == NULL)
+      if (k_info == NULL)
+        {
+          k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
+                                       app, &forced_valid, oppenc_mode);
+        }
+
+      if ((k_info == NULL) && (! oppenc_mode))
         {
           snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
           
-          if ((key = crypt_ask_for_key (buf, q->mailbox,
-                                        KEYFLAG_CANENCRYPT,
+          k_info = crypt_ask_for_key (buf, q->mailbox,
+                                      KEYFLAG_CANENCRYPT,
 #if 0
-                                        *r_application,
+                                      *r_application,
 #else
-                                       app,
+                                      app,
 #endif
-                                       &forced_valid)) == NULL)
-            {
-              FREE (&keylist);
-              rfc822_free_address (&addr);
-              return NULL;
-            }
+                                      &forced_valid);
+        }
+
+      if (k_info == NULL)
+        {
+          FREE (&keylist);
+          rfc822_free_address (&addr);
+          return NULL;
         }
-      else
-        key = k_info;
 
-      {
-        const char *s = crypt_fpr (key);
+
+      keyID = crypt_fpr (k_info);
 
 #if 0
-        if (key->flags & KEYFLAG_ISX509)
-          *r_application &= ~APPLICATION_PGP;
-        if (!(key->flags & KEYFLAG_ISX509))
-          *r_application &= ~APPLICATION_SMIME;
+      if (k_info->flags & KEYFLAG_ISX509)
+        *r_application &= ~APPLICATION_PGP;
+      if (!(k_info->flags & KEYFLAG_ISX509))
+        *r_application &= ~APPLICATION_SMIME;
 #endif
       
-        keylist_size += mutt_strlen (s) + 4 + 1;
-        safe_realloc (&keylist, keylist_size);
-        sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
-                 keylist_used ? " " : "",  s,
-                 forced_valid? "!":"");
-      }
+  bypass_selection:
+      keylist_size += mutt_strlen (keyID) + 4 + 1;
+      safe_realloc (&keylist, keylist_size);
+      sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
+               keylist_used ? " " : "",  keyID,
+               forced_valid? "!":"");
       keylist_used = mutt_strlen (keylist);
         
-      crypt_free_key (&key);
+      crypt_free_key (&k_info);
       rfc822_free_address (&addr);
     }
   return (keylist);
diff --git a/pgp.c b/pgp.c
index 5d022bed9e888c31255a63588f5d257a12ed04ad..665fb3f24bccb84c3bb20d4283afdb9b93051a84 100644 (file)
--- a/pgp.c
+++ b/pgp.c
@@ -1179,7 +1179,7 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode)
   size_t keylist_used = 0;
   ADDRESS *addr = NULL;
   ADDRESS *p, *q;
-  pgp_key_t k_info = NULL, key = NULL;
+  pgp_key_t k_info = NULL;
 
   const char *fqdn = mutt_fqdn (1);
 
@@ -1192,9 +1192,13 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode)
 
     if ((keyID = mutt_crypt_hook (p)) != NULL)
     {
-      int r;
-      snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
-      if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
+      int r = M_NO;
+      if (! oppenc_mode)
+      {
+        snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
+        r = mutt_yesorno (buf, M_YES);
+      }
+      if (oppenc_mode || (r == M_YES))
       {
        if (crypt_is_numerical_keyid (keyID))
        {
@@ -1210,8 +1214,10 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode)
          if (fqdn) rfc822_qualify (addr, fqdn);
          q = addr;
        }
-       else
+       else if (! oppenc_mode)
+       {
          k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
+       }
       }
       else if (r == -1)
       {
@@ -1222,24 +1228,26 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode)
     }
 
     if (k_info == NULL)
+    {
       pgp_invoke_getkeys (q);
+      k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING, oppenc_mode);
+    }
 
-    if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
+    if ((k_info == NULL) && (! oppenc_mode))
     {
       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
+      k_info = pgp_ask_for_key (buf, q->mailbox,
+                             KEYFLAG_CANENCRYPT, PGP_PUBRING);
+    }
 
-      if ((key = pgp_ask_for_key (buf, q->mailbox,
-                                 KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
-      {
-       FREE (&keylist);
-       rfc822_free_address (&addr);
-       return NULL;
-      }
+    if (k_info == NULL)
+    {
+      FREE (&keylist);
+      rfc822_free_address (&addr);
+      return NULL;
     }
-    else
-      key = k_info;
 
-    keyID = pgp_keyid (key);
+    keyID = pgp_keyid (k_info);
     
   bypass_selection:
     keylist_size += mutt_strlen (keyID) + 4;
@@ -1248,7 +1256,7 @@ char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode)
             keyID);
     keylist_used = mutt_strlen (keylist);
 
-    pgp_free_key (&key);
+    pgp_free_key (&k_info);
     rfc822_free_address (&addr);
 
   }
diff --git a/pgp.h b/pgp.h
index ab874045590a63231e1b577913b612e3d71f3cda..46a54846b2a68a3ce449bff73cf60033c7f29954 100644 (file)
--- a/pgp.h
+++ b/pgp.h
@@ -48,7 +48,7 @@ int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **);
 /* pgp_key_t gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *); */
 pgp_key_t pgp_ask_for_key (char *, char *, short, pgp_ring_t);
 pgp_key_t pgp_get_candidates (pgp_ring_t, LIST *);
-pgp_key_t pgp_getkeybyaddr (ADDRESS *, short, pgp_ring_t);
+pgp_key_t pgp_getkeybyaddr (ADDRESS *, short, pgp_ring_t, int);
 pgp_key_t pgp_getkeybystr (char *, short, pgp_ring_t);
 
 char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode);
index b21620f6d2e261b5fd2b1094958a3bd5fb49ec7a..083e8c02ece288be833ed09a271a356edc62f6b8 100644 (file)
--- a/pgpkey.c
+++ b/pgpkey.c
@@ -812,7 +812,8 @@ static pgp_key_t *pgp_get_lastp (pgp_key_t p)
   return NULL;
 }
 
-pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
+pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring,
+                            int oppenc_mode)
 {
   ADDRESS *r, *p;
   LIST *hints = NULL;
@@ -821,7 +822,8 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
   int match;
 
   pgp_key_t keys, k, kn;
-  pgp_key_t the_valid_key = NULL;
+  pgp_key_t the_strong_valid_key = NULL;
+  pgp_key_t a_valid_addrmatch_key = NULL;
   pgp_key_t matches = NULL;
   pgp_key_t *last = &matches;
   pgp_uid_t *q;
@@ -831,7 +833,8 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
   if (a && a->personal)
     hints = pgp_add_string_to_hints (hints, a->personal);
 
-  mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
+  if (! oppenc_mode )
+    mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
   keys = pgp_get_candidates (keyring, hints);
 
   mutt_free_list (&hints);
@@ -870,14 +873,20 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
        if (validity & PGP_KV_MATCH)    /* something matches */
          match = 1;
 
-       /* is this key a strong candidate? */
-       if ((validity & PGP_KV_VALID) && (validity & PGP_KV_STRONGID) 
-           && (validity & PGP_KV_ADDR))
-       {
-         if (the_valid_key && the_valid_key != k)
-           multi             = 1;
-         the_valid_key       = k;
-       }
+        if ((validity & PGP_KV_VALID)
+            && (validity & PGP_KV_ADDR))
+        {
+          if (validity & PGP_KV_STRONGID)
+          {
+            if (the_strong_valid_key && the_strong_valid_key != k)
+              multi = 1;
+            the_strong_valid_key = k;
+          }
+          else
+          {
+            a_valid_addrmatch_key = k;
+          }
+        }
       }
 
       rfc822_free_address (&r);
@@ -895,16 +904,30 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
 
   if (matches)
   {
-    if (the_valid_key && !multi)
+    if (oppenc_mode)
+    {
+      if (the_strong_valid_key)
+      {
+        pgp_remove_key (&matches, the_strong_valid_key);
+        k = the_strong_valid_key;
+      }
+      else if (a_valid_addrmatch_key)
+      {
+        pgp_remove_key (&matches, a_valid_addrmatch_key);
+        k = a_valid_addrmatch_key;
+      }
+      else
+        k = NULL;
+    }
+    else if (the_strong_valid_key && !multi)
     {
       /*
        * There was precisely one strong match on a valid ID.
        * 
        * Proceed without asking the user.
        */
-      pgp_remove_key (&matches, the_valid_key);
-      pgp_free_key (&matches);
-      k = the_valid_key;
+      pgp_remove_key (&matches, the_strong_valid_key);
+      k = the_strong_valid_key;
     }
     else 
     {
@@ -913,9 +936,10 @@ pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
        */
       if ((k = pgp_select_key (matches, a, NULL)))
        pgp_remove_key (&matches, k);
-      pgp_free_key (&matches);
     }
 
+    pgp_free_key (&matches);
+
     return k;
   }
 
diff --git a/smime.c b/smime.c
index 00099459786ef7d92a235fc79affdf89451e6266..b7e17cd5c68e7b65b93799012e171f90ed352f32 100644 (file)
--- a/smime.c
+++ b/smime.c
@@ -746,7 +746,8 @@ char *smime_findKeys (ADDRESS *adrlist, int oppenc_mode)
 
     q = p;
 
-    if ((keyID = smime_get_field_from_db (q->mailbox, NULL, 1, 1)) == NULL)
+    keyID = smime_get_field_from_db (q->mailbox, NULL, 1, !oppenc_mode);
+    if ((keyID == NULL) && (! oppenc_mode))
     {
       snprintf(buf, sizeof(buf),
               _("Enter keyID for %s: "),
@@ -755,7 +756,8 @@ char *smime_findKeys (ADDRESS *adrlist, int oppenc_mode)
     }
     if(!keyID)
     {
-      mutt_message (_("No (valid) certificate found for %s."), q->mailbox);
+      if (! oppenc_mode)
+        mutt_message (_("No (valid) certificate found for %s."), q->mailbox);
       FREE (&keylist);
       return NULL;
     }