[git] GpgOL - branch, master, updated. gpgol-2.2.0-8-gc8f4655

by Andre Heinecke cvs at cvs.gnupg.org
Thu Jun 21 11:17:45 CEST 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG extension for MS Outlook".

The branch, master has been updated
       via  c8f46557da704d863052709d5b627970450a0d1d (commit)
      from  630844dc453ac59cbd73beb225548b40d7d1b239 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit c8f46557da704d863052709d5b627970450a0d1d
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Jun 21 10:40:39 2018 +0200

    Implement auto secure feature
    
    * src/common_indep.h (opt): Add autosecure.
    * src/cryptcontroller.cpp (CryptController::CryptController): Adopt
    new API.
    * src/keycache.cpp (do_locate, do_locate_secret): Fix broken handling
    of args.
    (locate_secret): Add check for empty mbox. Otherwise it could
    select the first secret key if the sender address could not be
    resolved.
    (KeyCache::startLocate): Take recipients as vector.
    (KeyCache::isMailResolvable): New. Check if all keys are found
    in the cache.
    * src/keycache.h: Update accordingly.
    * src/mail.cpp (m_cached_recipients): Use a vector instead of
    a carray.
    (m_first_autoresolve_check): Track state of autoresolve.
    (Mail::~Mail): No need to free cached recipients.
    (Mail::update_oom_data): Use vector for cached recipients.
    (Mail::locate_keys): Adapt to new recipients API. Do
    autoresolve_check.
    (Mail::take_cached_recipients): Removed.
    (Mail::get_cached_recipents): New. Get a copy of the recipients.
    (Mail::decrement_locate_count): Trigger autoresolve check.
    (Mail::autoresolve_check_s): New. Check if mail is resolvable.
    * src/mail.h: Update accordingly.
    * src/mailitem-events.cpp (RecipientAdded): Handle opt.autosecure.
    * src/main.c (read_options): Read autosecure.
    * src/ribbon-callbacks.cpp (mark_mime_action): Use more modern
    style. Mark if crypto state was set manually.
    * src/windowmessages.cpp (DO_AUTO_SECURE, DONT_AUTO_SECURE): New
    messages to set state.
    
    --
    This is a first implementation of opportunistic encryption
    in GpgOL. If we have enough keys with marginal validity
    or if the keys come from WKD we can select "secure" automatically.
    
    GnuPG-Bug-Id: T3999

diff --git a/src/common_indep.h b/src/common_indep.h
index f1805a9..285ab42 100644
--- a/src/common_indep.h
+++ b/src/common_indep.h
@@ -192,6 +192,7 @@ struct
   int prefer_html;           /* Prefer html in html/text alternatives. */
   int inline_pgp;            /* Only for Addin. Use Inline PGP by default. */
   int autoresolve;           /* Autresolve keys with --locate-keys. */
+  int autosecure;             /* Autmatically encrypt if locate returns enough validity. */
   int reply_crypt;           /* Only for Addin. Encrypt / Sign based on cryptostatus. */
   int smime_html_warn_shown; /* Flag to save if unsigned smime warning was shown */
 
diff --git a/src/cryptcontroller.cpp b/src/cryptcontroller.cpp
index 7f701b2..df5366c 100644
--- a/src/cryptcontroller.cpp
+++ b/src/cryptcontroller.cpp
@@ -70,7 +70,7 @@ CryptController::CryptController (Mail *mail, bool encrypt, bool sign,
 {
   log_debug ("%s:%s: CryptController ctor for %p encrypt %i sign %i inline %i.",
              SRCNAME, __func__, mail, encrypt, sign, mail->do_pgp_inline ());
-  m_recipient_addrs = mail->take_cached_recipients ();
+  m_recipient_addrs = vector_to_cArray (mail->get_cached_recipients ());
 }
 
 CryptController::~CryptController()
diff --git a/src/keycache.cpp b/src/keycache.cpp
index 277f461..742046f 100644
--- a/src/keycache.cpp
+++ b/src/keycache.cpp
@@ -362,8 +362,10 @@ do_locate (LPVOID arg)
     {
       return 0;
     }
-  std::string addr = (char*) arg;
-  xfree (arg);
+
+  auto args = std::unique_ptr<LocateArgs> ((LocateArgs *) arg);
+
+  const auto addr = args->m_mbox;
 
   log_mime_parser ("%s:%s searching key for addr: \"%s\"",
                    SRCNAME, __func__, addr.c_str());
@@ -437,7 +439,7 @@ do_locate (LPVOID arg)
 }
 
 static void
-locate_secret (char *addr, GpgME::Protocol proto)
+locate_secret (const char *addr, GpgME::Protocol proto)
 {
   auto ctx = std::unique_ptr<GpgME::Context> (
                       GpgME::Context::createForProtocol (proto));
@@ -453,6 +455,13 @@ locate_secret (char *addr, GpgME::Protocol proto)
     }
   const auto mbox = GpgME::UserID::addrSpecFromString (addr);
 
+  if (mbox.empty())
+    {
+      log_debug ("%s:%s: Empty mbox for addr %s",
+                 SRCNAME, __func__, addr);
+      return;
+    }
+
   // We need to validate here to fetch CRL's
   ctx->setKeyListMode (GpgME::KeyListMode::Local |
                        GpgME::KeyListMode::Validate);
@@ -502,33 +511,27 @@ locate_secret (char *addr, GpgME::Protocol proto)
 static DWORD WINAPI
 do_locate_secret (LPVOID arg)
 {
-  char *addr = (char*) arg;
+  auto args = std::unique_ptr<LocateArgs> ((LocateArgs *) arg);
 
   log_mime_parser ("%s:%s searching secret key for addr: \"%s\"",
-                   SRCNAME, __func__, addr);
+                   SRCNAME, __func__, args->m_mbox.c_str ());
 
-  locate_secret (addr, GpgME::OpenPGP);
+  locate_secret (args->m_mbox.c_str(), GpgME::OpenPGP);
   if (opt.enable_smime)
     {
-      locate_secret (addr, GpgME::CMS);
+      locate_secret (args->m_mbox.c_str(), GpgME::CMS);
     }
-  xfree (addr);
   log_debug ("%s:%s locator sthread thread done",
              SRCNAME, __func__);
   return 0;
 }
 
 void
-KeyCache::startLocate (char **recipients, Mail *mail) const
+KeyCache::startLocate (const std::vector<std::string> &addrs, Mail *mail) const
 {
-  if (!recipients)
-    {
-      TRACEPOINT;
-      return;
-    }
-  for (int i = 0; recipients[i]; i++)
+  for (const auto &addr: addrs)
     {
-      startLocate (recipients[i], mail);
+      startLocate (addr.c_str(), mail);
     }
 }
 
@@ -617,3 +620,56 @@ KeyCache::setPgpKeySecret(const std::string &mbox, const GpgME::Key &key)
 {
   d->setPgpKeySecret(mbox, key);
 }
+
+int
+KeyCache::isMailResolvable(Mail *mail)
+{
+  /* Get the data from the mail. */
+  const auto sender = mail->get_cached_sender();
+  auto recps = mail->get_cached_recipients();
+
+  if (sender.empty() || recps.empty())
+    {
+      log_debug ("%s:%s: Mail has no sender or no recipients.",
+                 SRCNAME, __func__);
+      return 0;
+    }
+
+  /* Include sender for encryption */
+  recps.push_back (sender);
+
+  GpgME::Key sigKey = getSigningKey (sender.c_str(), GpgME::OpenPGP);
+  std::vector<GpgME::Key> encKeys = getEncryptionKeys (recps,
+                                                       GpgME::OpenPGP);
+
+  int pgpState = 0;
+  if (!encKeys.empty())
+    {
+      pgpState = 1;
+    }
+  if (!sigKey.isNull())
+    {
+      pgpState += 2;
+    }
+
+  if (pgpState == 3 /* all good */ || !opt.enable_smime)
+    {
+      return pgpState;
+    }
+
+  /* Check S/MIME instead */
+  sigKey = getSigningKey (sender.c_str(), GpgME::CMS);
+  encKeys = getEncryptionKeys (recps, GpgME::CMS);
+
+  int cmsState = 0;
+  if (!encKeys.empty())
+    {
+      cmsState = 1;
+    }
+  if (!sigKey.isNull())
+    {
+      cmsState += 2;
+    }
+
+  return (cmsState > pgpState) ? cmsState : pgpState;
+}
diff --git a/src/keycache.h b/src/keycache.h
index 0364ab1..7c4b4be 100644
--- a/src/keycache.h
+++ b/src/keycache.h
@@ -59,13 +59,12 @@ public:
                                                GpgME::Protocol proto) const;
 
     /* Start a key location in a background thread filling
-       the key cache. cArray is a null terminated array
-       of address strings.
+       the key cache.
 
        The mail argument is used to add / remove the
        locator thread counter.
        */
-    void startLocate (char **cArray, Mail *mail) const;
+    void startLocate (const std::vector<std::string> &addrs, Mail *mail) const;
 
     /* Look for a secret key for the addr. */
     void startLocateSecret (const char *addr, Mail *mail) const;
@@ -74,6 +73,12 @@ public:
        the key cache. */
     void startLocate (const char *addr, Mail *mail) const;
 
+    /* Check that a mail is resolvable through the keycache.
+     *
+     * Returns the usual int with sign = 2 and encrypt = 1
+     **/
+    int isMailResolvable (Mail *mail);
+
     // Internal for thread
     void setSmimeKey(const std::string &mbox, const GpgME::Key &key);
     void setPgpKey(const std::string &mbox, const GpgME::Key &key);
diff --git a/src/mail.cpp b/src/mail.cpp
index d61d22b..f02f127 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -87,7 +87,6 @@ Mail::Mail (LPDISPATCH mailitem) :
     m_crypto_flags(0),
     m_cached_html_body(nullptr),
     m_cached_plain_body(nullptr),
-    m_cached_recipients(nullptr),
     m_type(MSGTYPE_UNKNOWN),
     m_do_inline(false),
     m_is_gsuite(false),
@@ -99,6 +98,7 @@ Mail::Mail (LPDISPATCH mailitem) :
     m_is_send_again(false),
     m_disable_att_remove_warning(false),
     m_manual_crypto_opts(false),
+    m_first_autosecure_check(true),
     m_locate_count(0)
 {
   if (get_mail_for_item (mailitem))
@@ -183,7 +183,6 @@ Mail::~Mail()
   gpgol_release(m_mailitem);
   xfree (m_cached_html_body);
   xfree (m_cached_plain_body);
-  release_cArray (m_cached_recipients);
   if (!m_uuid.empty())
     {
       log_oom_extra ("%s:%s: destroyed: %p uuid: %s",
@@ -1519,8 +1518,9 @@ Mail::update_oom_data ()
       xfree (m_cached_plain_body);
       m_cached_plain_body = get_oom_string (m_mailitem, "Body");
 
-      release_cArray (m_cached_recipients);
-      m_cached_recipients = get_recipients ();
+      char **recipients = get_recipients ();
+      m_cached_recipients = cArray_to_vector ((const char **)recipients);
+      xfree (recipients);
     }
   /* For some reason outlook may store the recipient address
      in the send using account field. If we have SMTP we prefer
@@ -2675,11 +2675,11 @@ Mail::locate_keys()
 
   // First update oom data to have recipients and sender updated.
   update_oom_data ();
-  char ** recipients = take_cached_recipients ();
   KeyCache::instance()->startLocateSecret (get_sender ().c_str (), this);
   KeyCache::instance()->startLocate (get_sender ().c_str (), this);
-  KeyCache::instance()->startLocate (recipients, this);
-  release_cArray (recipients);
+  KeyCache::instance()->startLocate (get_cached_recipients (), this);
+  autoresolve_check_s ();
+
   locate_in_progress = false;
 }
 
@@ -2723,12 +2723,10 @@ Mail::needs_encrypt() const
   return m_needs_encrypt;
 }
 
-char **
-Mail::take_cached_recipients()
+std::vector<std::string>
+Mail::get_cached_recipients()
 {
-  char **ret = m_cached_recipients;
-  m_cached_recipients = nullptr;
-  return ret;
+  return m_cached_recipients;
 }
 
 void
@@ -3232,4 +3230,70 @@ void
 Mail::decrement_locate_count()
 {
   m_locate_count--;
+
+  if (m_locate_count < 0)
+    {
+      log_error ("%s:%s: locate count mismatch.",
+                 SRCNAME, __func__);
+      m_locate_count = 0;
+    }
+  if (!m_locate_count)
+    {
+      autoresolve_check_s ();
+    }
+}
+
+void
+Mail::autoresolve_check_s()
+{
+  if (!opt.autoresolve || m_manual_crypto_opts)
+    {
+      return;
+    }
+  int ret = KeyCache::instance()->isMailResolvable (this);
+
+  log_debug ("%s:%s: status %i",
+             SRCNAME, __func__, ret);
+
+  /* As we are safe to call at any time, because we need
+   * to be triggered by the locator threads finishing we
+   * need to actually set the draft info flags in
+   * the ui thread. */
+  if (ret == 3)
+    {
+      do_in_ui_thread (DO_AUTO_SECURE, this);
+    }
+  else
+    {
+      do_in_ui_thread (DONT_AUTO_SECURE, this);
+    }
+  return;
+}
+
+void
+Mail::set_do_autosecure_mapi(bool value)
+{
+  TRACEPOINT;
+  LPMESSAGE msg = get_oom_base_message (m_mailitem);
+
+  if (!msg)
+    {
+      TRACEPOINT;
+    }
+  int old_flags = get_gpgol_draft_info_flags (msg);
+  if (old_flags && m_first_autosecure_check)
+    {
+      /* They were set explicily before us. This can be
+       * because they were a draft (which is bad) or
+       * because they are a reply/forward to a crypto mail
+       * or because there are conflicting settings. */
+      log_debug ("%s:%s: Mail %p had already flags set.",
+                 SRCNAME, __func__, m_mailitem);
+      m_first_autosecure_check = false;
+      m_manual_crypto_opts = true;
+      return;
+    }
+  m_first_autosecure_check = false;
+  set_gpgol_draft_info_flags (msg, value ? 3 : 0);
+  gpgoladdin_invalidate_ui();
 }
diff --git a/src/mail.h b/src/mail.h
index 7e6ea21..afd8d09 100644
--- a/src/mail.h
+++ b/src/mail.h
@@ -384,10 +384,8 @@ public:
   */
   char *take_cached_plain_body ();
 
-  /** Get the cached recipients. It is updated in update_oom_data.
-      Caller takes ownership of the list and has to free it.
-  */
-  char **take_cached_recipients ();
+  /** Get the cached recipients. It is updated in update_oom_data.*/
+  std::vector<std::string> get_cached_recipients ();
 
   /** Returns 1 if the mail was encrypted, 2 if signed, 3 if both.
       Only valid after decrypt_verify.
@@ -539,9 +537,21 @@ public:
 
   /* To be called when a resolver thread is done. If there are no running
      resolver threads we can check the recipients to see if we should
-     toggle / untoggle the secure state. */
+     toggle / untoggle the secure state.
+     */
   void decrement_locate_count ();
 
+  /* Check if the keys can be resolved automatically and trigger
+   * setting the crypto flags accordingly.
+   */
+  void autoresolve_check_s ();
+
+  /* Set if a mail should be secured (encrypted and signed)
+   *
+   * Only save to call from a place that may access mapi.
+   */
+  void set_do_autosecure_mapi (bool value);
+
 private:
   void update_categories ();
   void update_sigstate ();
@@ -564,7 +574,7 @@ private:
   std::string m_sender;
   char *m_cached_html_body; /* Cached html body. */
   char *m_cached_plain_body; /* Cached plain body. */
-  char **m_cached_recipients;
+  std::vector<std::string> m_cached_recipients;
   msgtype_t m_type; /* Our messagetype as set in mapi */
   std::shared_ptr <ParseController> m_parser;
   std::shared_ptr <CryptController> m_crypter;
@@ -587,6 +597,7 @@ private:
   bool m_disable_att_remove_warning; /* Should not warn about attachment removal. */
   bool m_block_html; /* Force blocking of html content. e.g for unsigned S/MIME mails. */
   bool m_manual_crypto_opts; /* Crypto options (sign/encrypt) have been set manually. */
+  bool m_first_autosecure_check; /* This is the first autoresolve check */
   int m_locate_count; /* The number of key locates pending for this mail. */
 };
 #endif // MAIL_H
diff --git a/src/mailitem-events.cpp b/src/mailitem-events.cpp
index b499966..51006f6 100644
--- a/src/mailitem-events.cpp
+++ b/src/mailitem-events.cpp
@@ -248,7 +248,7 @@ EVENT_SINK_INVOKE(MailItemEvents)
                   Testing shows that Outlook always sends these three in a row
                   */)
                 {
-                  if ((m_mail->needs_crypto() & 1))
+                  if (opt.autosecure || (m_mail->needs_crypto() & 1))
                     {
                       /* XXX Racy race. This is a fix for crashes
                          that happend if a resolved recipient is copied an pasted.
diff --git a/src/main.c b/src/main.c
index 02c53df..2d3590e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -331,6 +331,9 @@ read_options (void)
   load_extension_value ("smimeHtmlWarnShown", &val);
   opt.smime_html_warn_shown = val == NULL || *val != '1'? 0 : 1;
   xfree (val); val = NULL;
+  load_extension_value ("autosecure", &val);
+  opt.autosecure = val == NULL ? 1 : *val != '1' ? 0 : 1;
+  xfree (val); val = NULL;
   /* Note, that on purpose these flags are only Registry changeable.
      The format of the entry is a string of of "0" and "1" digits; see
      the switch below for a description. */
diff --git a/src/ribbon-callbacks.cpp b/src/ribbon-callbacks.cpp
index 450bc02..87ceab6 100644
--- a/src/ribbon-callbacks.cpp
+++ b/src/ribbon-callbacks.cpp
@@ -170,40 +170,71 @@ getIcon (int id, VARIANT* result)
 HRESULT
 mark_mime_action (LPDISPATCH ctrl, int flags, bool is_explorer)
 {
-  HRESULT hr;
-  HRESULT rc = E_FAIL;
-  LPDISPATCH context = NULL,
-             mailitem = NULL;
   LPMESSAGE message = NULL;
   int oldflags,
       newflags;
 
   log_debug ("%s:%s: enter", SRCNAME, __func__);
-  hr = getContext (ctrl, &context);
-  if (FAILED(hr))
-      return hr;
+  LPDISPATCH context = NULL;
+  if (FAILED(getContext (ctrl, &context)))
+    {
+      TRACEPOINT;
+      return E_FAIL;
+    }
 
-  mailitem = get_oom_object (context, is_explorer ? "ActiveInlineResponse" :
-                                                    "CurrentItem");
+  LPDISPATCH mailitem = get_oom_object (context,
+                                        is_explorer ? "ActiveInlineResponse" :
+                                                      "CurrentItem");
+  gpgol_release (context);
 
   if (!mailitem)
     {
       log_error ("%s:%s: Failed to get mailitem.",
                  SRCNAME, __func__);
-      goto done;
+      return E_FAIL;
+    }
+
+  /* Get the uid of this item. */
+  char *uid = get_unique_id (mailitem, 0, nullptr);
+  if (!uid)
+    {
+      LPMESSAGE msg = get_oom_base_message (mailitem);
+      uid = mapi_get_uid (msg);
+      gpgol_release (msg);
+      if (!uid)
+        {
+          log_debug ("%s:%s: Failed to get uid for %p",
+                   SRCNAME, __func__, mailitem);
+        }
+    }
+  Mail *mail = nullptr;
+  if (uid)
+    {
+      mail = Mail::get_mail_for_uuid (uid);
+      xfree (uid);
+    }
+
+  if (mail)
+    {
+      mail->set_crypto_selected_manually (true);
+    }
+  else
+    {
+      log_debug ("%s:%s: Failed to get mail object.",
+                 SRCNAME, __func__);
     }
 
   message = get_oom_base_message (mailitem);
+  gpgol_release (mailitem);
 
   if (!message)
     {
       log_error ("%s:%s: Failed to get message.",
                  SRCNAME, __func__);
-      goto done;
+      return S_OK;
     }
 
   oldflags = get_gpgol_draft_info_flags (message);
-
   if (flags == 3 && oldflags != 3)
     {
       // If only one sub button is active activate
@@ -220,8 +251,7 @@ mark_mime_action (LPDISPATCH ctrl, int flags, bool is_explorer)
       log_error ("%s:%s: Failed to set draft flags.",
                  SRCNAME, __func__);
     }
-
-  rc = S_OK;
+  gpgol_release (message);
 
   /*  We need to invalidate the UI to update the toggle
       states of the subbuttons and the top button. Yeah,
@@ -233,12 +263,7 @@ mark_mime_action (LPDISPATCH ctrl, int flags, bool is_explorer)
       Mail::locate_all_crypto_recipients ();
     }
 
-done:
-  gpgol_release (context);
-  gpgol_release (mailitem);
-  gpgol_release (message);
-
-  return rc;
+  return S_OK;
 }
 
 /* Get the state of encrypt / sign toggle buttons.
diff --git a/src/windowmessages.cpp b/src/windowmessages.cpp
index 36c0631..082dfa8 100644
--- a/src/windowmessages.cpp
+++ b/src/windowmessages.cpp
@@ -195,6 +195,30 @@ gpgol_window_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
               mail->remove_all_attachments ();
               break;
             }
+          case (DO_AUTO_SECURE):
+            {
+              auto mail = (Mail*) ctx->data;
+              if (!Mail::is_valid_ptr (mail))
+                {
+                  log_debug ("%s:%s: DO_AUTO_SECURE for mail which is gone.",
+                             SRCNAME, __func__);
+                  break;
+                }
+              mail->set_do_autosecure_mapi (true);
+              break;
+            }
+          case (DONT_AUTO_SECURE):
+            {
+              auto mail = (Mail*) ctx->data;
+              if (!Mail::is_valid_ptr (mail))
+                {
+                  log_debug ("%s:%s: DO_AUTO_SECURE for mail which is gone.",
+                             SRCNAME, __func__);
+                  break;
+                }
+              mail->set_do_autosecure_mapi (false);
+              break;
+            }
           default:
             log_debug ("%s:%s: Unknown msg %x",
                        SRCNAME, __func__, ctx->wmsg_type);
diff --git a/src/windowmessages.h b/src/windowmessages.h
index dcc372c..6a96a13 100644
--- a/src/windowmessages.h
+++ b/src/windowmessages.h
@@ -53,6 +53,8 @@ typedef enum _gpgol_wmsg_type
   INVALIDATE_LAST_MAIL,
   REVERT_MAIL,
   CLEAR_REPLY_FORWARD,
+  DO_AUTO_SECURE,
+  DONT_AUTO_SECURE,
 } gpgol_wmsg_type;
 
 typedef struct

-----------------------------------------------------------------------

Summary of changes:
 src/common_indep.h       |  1 +
 src/cryptcontroller.cpp  |  2 +-
 src/keycache.cpp         | 88 +++++++++++++++++++++++++++++++++++++++---------
 src/keycache.h           | 11 ++++--
 src/mail.cpp             | 88 +++++++++++++++++++++++++++++++++++++++++-------
 src/mail.h               | 23 +++++++++----
 src/mailitem-events.cpp  |  2 +-
 src/main.c               |  3 ++
 src/ribbon-callbacks.cpp | 65 ++++++++++++++++++++++++-----------
 src/windowmessages.cpp   | 24 +++++++++++++
 src/windowmessages.h     |  2 ++
 11 files changed, 250 insertions(+), 59 deletions(-)


hooks/post-receive
-- 
GnuPG extension for MS Outlook
http://git.gnupg.org




More information about the Gnupg-commits mailing list