[git] GpgOL - branch, async-enc, updated. gpgol-2.0.6-4-ge789048

by Andre Heinecke cvs at cvs.gnupg.org
Tue Jan 30 14:22:08 CET 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, async-enc has been updated
       via  e789048f47fccab444df477f6e82ece69fa2a8b4 (commit)
       via  e133064eb799de9a1138f23afc5cd13d1b053fdf (commit)
      from  bec715ab3f57709db1fbf4759b0b0593055b5b04 (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 e789048f47fccab444df477f6e82ece69fa2a8b4
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Jan 30 14:19:42 2018 +0100

    Make inline encryption work in the new way
    
    * src/cryptcontroller.cpp (CryptController::resolve_keys):
    Dummy. Should resolve keys in the future.
    (CryptController::do_crypto): Do something.
    (CryptController::get_inline_data): Take data as string.
    * src/cryptcontroller.h Update accordingly.
    * src/mail.cpp (Mail::append_to_inline_body): Use cryptcontroller.

diff --git a/src/cryptcontroller.cpp b/src/cryptcontroller.cpp
index f12957f..ebb18bb 100644
--- a/src/cryptcontroller.cpp
+++ b/src/cryptcontroller.cpp
@@ -26,6 +26,10 @@
 #include "mapihelp.h"
 #include "mimemaker.h"
 
+#include <gpgme++/context.h>
+#include <gpgme++/signingresult.h>
+#include <gpgme++/encryptionresult.h>
+
 #ifdef HAVE_W32_SYSTEM
 #include "common.h"
 /* We use UTF-8 internally. */
@@ -54,6 +58,7 @@ CryptController::CryptController (Mail *mail, bool encrypt, bool sign,
     m_encrypt (encrypt),
     m_sign (sign),
     m_inline (doInline),
+    m_crypto_success (false),
     m_proto (proto)
 {
   log_debug ("%s:%s: CryptController ctor for %p encrypt %i sign %i inline %i.",
@@ -115,6 +120,8 @@ CryptController::collect_data ()
       log_debug ("%s:%s: PGP Inline. Using cached body as input.",
                  SRCNAME, __func__);
       gpgol_release (message);
+      /* Set the input buffer to start. */
+      m_input.seek (0, SEEK_SET);
       return 0;
     }
 
@@ -144,10 +151,127 @@ CryptController::collect_data ()
 }
 
 int
+CryptController::resolve_keys ()
+{
+  m_recipients.clear();
+
+  /*XXX Temporary hack part do key resolution here. */
+  GpgME::Error err;
+  auto ctx = std::shared_ptr<GpgME::Context> (GpgME::Context::createForProtocol(GpgME::OpenPGP));
+  const auto key = ctx->key ("EB4C5A5B7AD6C8527F050BAF1ED4F0BC6CFBC912", err, true);
+
+  if (key.isNull())
+    {
+      log_error ("%s:%s: Failure to resolve keys.",
+                 SRCNAME, __func__);
+      return -1;
+    }
+
+  m_recipients.push_back(key);
+  m_signer_key = key;
+  return 0;
+}
+
+int
 CryptController::do_crypto ()
 {
+  // TODO get recipients and sender and protocol.
+
   log_debug ("%s:%s:",
              SRCNAME, __func__);
+  auto ctx = std::shared_ptr<GpgME::Context> (GpgME::Context::createForProtocol(GpgME::OpenPGP));
+
+  if (!ctx)
+    {
+      log_error ("%s:%s: Failure to create context.",
+                 SRCNAME, __func__);
+      return -1;
+    }
+
+  if (resolve_keys ())
+    {
+      log_debug ("%s:%s: Failure to resolve keys.",
+                 SRCNAME, __func__);
+      return -2;
+    }
+
+  if (!m_signer_key.isNull())
+    {
+      ctx->addSigningKey (m_signer_key);
+    }
+
+  ctx->setTextMode (true);
+  ctx->setArmor (true);
+
+  if (m_encrypt && m_sign)
+    {
+      const auto result_pair = ctx->signAndEncrypt (m_recipients,
+                                                    m_input,
+                                                    m_output,
+                                                    GpgME::Context::AlwaysTrust);
+
+      if (result_pair.first.error() || result_pair.second.error())
+        {
+          log_error ("%s:%s: Encrypt / Sign error %s %s.",
+                     SRCNAME, __func__, result_pair.first.error().asString(),
+                     result_pair.second.error().asString());
+          return -1;
+        }
+
+      if (result_pair.first.error().isCanceled() || result_pair.second.error().isCanceled())
+        {
+          log_debug ("%s:%s: User cancled",
+                     SRCNAME, __func__);
+          return -2;
+        }
+    }
+  else if (m_encrypt)
+    {
+      const auto result = ctx->encrypt (m_recipients, m_input,
+                                        m_output,
+                                        GpgME::Context::AlwaysTrust);
+      if (result.error())
+        {
+          log_error ("%s:%s: Encryption error %s.",
+                     SRCNAME, __func__, result.error().asString());
+          return -1;
+        }
+      if (result.error().isCanceled())
+        {
+          log_debug ("%s:%s: User cancled",
+                     SRCNAME, __func__);
+          return -2;
+        }
+    }
+  else if (m_sign)
+    {
+      const auto result = ctx->sign (m_input, m_output,
+                                     m_inline ? GpgME::Clearsigned :
+                                     GpgME::Detached);
+      if (result.error())
+        {
+          log_error ("%s:%s: Signing error %s.",
+                     SRCNAME, __func__, result.error().asString());
+          return -1;
+        }
+      if (result.error().isCanceled())
+        {
+          log_debug ("%s:%s: User cancled",
+                     SRCNAME, __func__);
+          return -2;
+        }
+    }
+  else
+    {
+      // ???
+      log_error ("%s:%s: unreachable code reached.",
+                 SRCNAME, __func__);
+    }
+
+
+  log_debug ("%s:%s: Crypto done sucessfuly.",
+             SRCNAME, __func__);
+  m_crypto_success = true;
   return 0;
 }
 
@@ -157,3 +281,21 @@ CryptController::update_mail_mapi ()
   log_debug ("%s:%s:", SRCNAME, __func__);
   return 0;
 }
+
+std::string
+CryptController::get_inline_data ()
+{
+  std::string ret;
+  if (!m_inline)
+    {
+      return ret;
+    }
+  m_output.seek (0, SEEK_SET);
+  char buf[4096];
+  size_t nread;
+  while ((nread = m_output.read (buf, 4096)) > 0)
+    {
+      ret += std::string (buf, nread);
+    }
+  return ret;
+}
diff --git a/src/cryptcontroller.h b/src/cryptcontroller.h
index f28c567..193c8cc 100644
--- a/src/cryptcontroller.h
+++ b/src/cryptcontroller.h
@@ -55,11 +55,19 @@ public:
     the result. */
   int update_mail_mapi ();
 
+  /** @brief Get an inline body as std::string. */
+  std::string get_inline_data ();
+
+private:
+  int resolve_keys ();
+
 private:
   Mail *m_mail;
   GpgME::Data m_input, m_output;
-  bool m_encrypt, m_sign, m_inline;
+  bool m_encrypt, m_sign, m_inline, m_crypto_success;
   GpgME::Protocol m_proto;
+  GpgME::Key m_signer_key;
+  std::vector<GpgME::Key> m_recipients;
 };
 
 #endif
diff --git a/src/mail.cpp b/src/mail.cpp
index c0feb78..27ec8ff 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -2487,12 +2487,21 @@ Mail::append_to_inline_body (const std::string &data)
 int
 Mail::inline_body_to_body()
 {
-  if (m_inline_body.empty())
+  if (!m_crypter)
+    {
+      log_error ("%s:%s: No crypter.",
+                 SRCNAME, __func__);
+      return -1;
+    }
+
+  const auto body = m_crypter->get_inline_data ();
+  if (body.empty())
     {
       return 0;
     }
-  int ret = put_oom_string (m_mailitem, "Body", m_inline_body.c_str ());
-  m_inline_body = std::string();
+
+  int ret = put_oom_string (m_mailitem, "Body",
+                            body.c_str ());
   return ret;
 }
 
@@ -2533,6 +2542,7 @@ Mail::update_crypt_oom()
       return;
     }
 
+  // We are in MIME land. Wipe the body.
   if (wipe (true))
     {
       log_debug ("%s:%s: Cancel send for %p.",

commit e133064eb799de9a1138f23afc5cd13d1b053fdf
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Jan 30 11:59:56 2018 +0100

    Continue work on async encrypt
    
    * src/mail.cpp (do_crypt): Sleep as a dummy.
    (Mail::update_crypt_oom): Add some code.
    * src/mailitem-events.cpp (EVENT_SINK_INVOKE): Move some code
    to update_crypt_oom.

diff --git a/src/mail.cpp b/src/mail.cpp
index a48d1e2..c0feb78 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -765,6 +765,7 @@ do_crypt (LPVOID arg)
 
   /* This can take a while */
   int rc = crypter->do_crypto();
+  Sleep(3000);
 
   gpgrt_lock_lock (&dtor_lock);
   if (!Mail::is_valid_ptr (mail))
@@ -783,7 +784,7 @@ do_crypt (LPVOID arg)
       return rc;
     }
 
-  mail->set_crypt_state (Mail::NeedsUpdateInMAPI);
+  mail->set_crypt_state (Mail::NeedsUpdateInOOM);
 
   do_in_ui_thread (CRYPTO_DONE, arg);
   gpgrt_lock_unlock (&dtor_lock);
@@ -2498,7 +2499,7 @@ Mail::inline_body_to_body()
 void
 Mail::update_crypt_mapi()
 {
-  log_debug ("%s:%s: Update crypt oom",
+  log_debug ("%s:%s: Update crypt mapi",
              SRCNAME, __func__);
   m_crypt_state = WantsSend;
 }
@@ -2506,7 +2507,49 @@ Mail::update_crypt_mapi()
 void
 Mail::update_crypt_oom()
 {
-  log_debug ("%s:%s: Update crypt oom",
-             SRCNAME, __func__);
+  log_debug ("%s:%s: Update crypt oom for %p",
+             SRCNAME, __func__, this);
+  if (m_crypt_state != NeedsUpdateInOOM)
+    {
+      log_debug ("%s:%s: invalid state %i",
+                 SRCNAME, __func__, m_crypt_state);
+      return;
+    }
+
+  if (should_inline_crypt ())
+    {
+      if (inline_body_to_body ())
+        {
+          log_debug ("%s:%s: Inline body to body failed %p.",
+                     SRCNAME, __func__, this);
+        }
+    }
+  const auto body = get_body();
+  if (body.size() > 10 && !strncmp (body.c_str(), "-----BEGIN", 10))
+    {
+      log_debug ("%s:%s: Looks like inline body. You can pass %p.",
+                 SRCNAME, __func__, this);
+      m_crypt_state = NeedsSecondAfterWrite;
+      return;
+    }
+
+  if (wipe (true))
+    {
+      log_debug ("%s:%s: Cancel send for %p.",
+                 SRCNAME, __func__, this);
+      wchar_t *title = utf8_to_wchar (_("GpgOL: Encryption not possible!"));
+      wchar_t *msg = utf8_to_wchar (_(
+                                      "Outlook returned an error when trying to send the encrypted mail.\n\n"
+                                      "Please restart Outlook and try again.\n\n"
+                                      "If it still fails consider using an encrypted attachment or\n"
+                                      "switching to PGP/Inline in GpgOL's options."));
+      MessageBoxW (get_active_hwnd(), msg, title,
+                   MB_ICONERROR | MB_OK);
+      xfree (msg);
+      xfree (title);
+      m_crypt_state = NoCryptMail;
+      return;
+    }
   m_crypt_state = NeedsSecondAfterWrite;
+  return;
 }
diff --git a/src/mail.h b/src/mail.h
index 389c6e2..8616a1e 100644
--- a/src/mail.h
+++ b/src/mail.h
@@ -55,6 +55,7 @@ public:
       NeedsActualCrypt,
       NeedsUpdateInOOM,
       NeedsSecondAfterWrite,
+      NeedsUpdateInMAPI,
       WantsSend
     };
 
@@ -373,6 +374,11 @@ public:
   void update_crypt_mapi ();
 
   /** Update OOM data after encryption. */
+  /** Update OOM data after encryption.
+
+    Checks for plain text leaks and
+    does not advance crypt state if body can't be cleaned.
+  */
   void update_crypt_oom ();
 
 private:
diff --git a/src/mailitem-events.cpp b/src/mailitem-events.cpp
index 4f1d65f..de06e47 100644
--- a/src/mailitem-events.cpp
+++ b/src/mailitem-events.cpp
@@ -357,6 +357,8 @@ EVENT_SINK_INVOKE(MailItemEvents)
               m_mail->update_oom_data ();
               m_mail->set_crypt_state (Mail::NeedsFirstAfterWrite);
 
+             log_debug ("%s:%s: Send event for crypto mail %p saving and starting.",
+                        SRCNAME, __func__, m_mail);
               // Save the Mail
               invoke_oom_method (m_object, "Save", NULL);
 
@@ -365,118 +367,72 @@ EVENT_SINK_INVOKE(MailItemEvents)
 
               // Cancel send
               *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
-            }
-
-          if (m_mail->crypt_state () == Mail::NeedsUpdateInOOM)
-            {
-              m_mail->update_crypt_oom ();
+              break;
             }
 
           if (m_mail->crypt_state () == Mail::WantsSend)
             {
-              /* Fishy behavior catcher: Sometimes the save does not clean
-                 out the body. Weird. Happened at least for one user.
-                 The following code checks for plain text leaks and
-                 prevents send in case the body can't be wiped. */
-              if (!m_mail->get_body().empty() || !m_mail->get_html_body().empty())
+#if 0
+              /* Now we adress T3656 if Outlooks internal S/MIME is somehow
+               * mixed in (even if it is enabled and then disabled) it might
+               * cause strange behavior in that it sends the plain message
+               * and not the encrypted message. Tests have shown that we can
+               * bypass that by calling submit message on our base
+               * message.
+               *
+               * We do this conditionally as our other way of using OOM
+               * to send is proven to work and we don't want to mess
+               * with it.
+               */
+              // Get the Message class.
+              HRESULT hr;
+              LPSPropValue propval = NULL;
+
+              // It's important we use the _not_ base message here.
+              LPMESSAGE message = get_oom_message (m_object);
+              hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
+              gpgol_release (message);
+              if (FAILED (hr))
                 {
-                  log_debug ("%s:%s: Body found after encryption %p.",
-                            SRCNAME, __func__, m_object);
-                  if (m_mail->should_inline_crypt ())
-                    {
-                      if (m_mail->inline_body_to_body ())
-                        {
-                          log_debug ("%s:%s: Inline body to body failed %p.",
-                                    SRCNAME, __func__, m_object);
-                        }
-                    }
-                  const auto body = m_mail->get_body();
-                  if (body.size() > 10 && !strncmp (body.c_str(), "-----BEGIN", 10))
-                    {
-                      log_debug ("%s:%s: Looks like inline body. You can pass %p.",
-                                SRCNAME, __func__, m_object);
-                      break;
-                    }
-
-                  if (m_mail->wipe (true))
-                    {
-                      log_debug ("%s:%s: Cancel send for %p.",
-                                SRCNAME, __func__, m_object);
-                      wchar_t *title = utf8_to_wchar (_("GpgOL: Encryption not possible!"));
-                      wchar_t *msg = utf8_to_wchar (_(
-                      "Outlook returned an error when trying to send the encrypted mail.\n\n"
-                      "Please restart Outlook and try again.\n\n"
-                      "If it still fails consider using an encrypted attachment or\n"
-                      "switching to PGP/Inline in GpgOL's options."));
-                      MessageBoxW (get_active_hwnd(), msg, title,
-                                   MB_ICONERROR | MB_OK);
-                      xfree (msg);
-                      xfree (title);
-                      *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
-                      return S_OK;
-                    }
-                    {
-                      /* Now we adress T3656 if Outlooks internal S/MIME is somehow
-                       * mixed in (even if it is enabled and then disabled) it might
-                       * cause strange behavior in that it sends the plain message
-                       * and not the encrypted message. Tests have shown that we can
-                       * bypass that by calling submit message on our base
-                       * message.
-                       *
-                       * We do this conditionally as our other way of using OOM
-                       * to send is proven to work and we don't want to mess
-                       * with it.
-                       */
-                      // Get the Message class.
-                      HRESULT hr;
-                      LPSPropValue propval = NULL;
-
-                      // It's important we use the _not_ base message here.
-                      LPMESSAGE message = get_oom_message (m_object);
-                      hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
-                      gpgol_release (message);
-                      if (FAILED (hr))
-                        {
-                          log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
-                                     SRCNAME, __func__, hr);
-                          gpgol_release (message);
-                          break;
-                        }
-                      if (propval->Value.lpszA && !strstr (propval->Value.lpszA, "GpgOL"))
-                        {
-                          // Does not have a message class by us.
-                          log_debug ("%s:%s: Message %p - No GpgOL Message class after encryption.",
-                                    SRCNAME, __func__, m_object);
-                          log_debug ("%s:%s: Message %p - Activating T3656 Workaround",
-                                    SRCNAME, __func__, m_object);
-                          message = get_oom_base_message (m_object);
-                          // It's important we use the _base_ message here.
-                          mapi_save_changes (message, KEEP_OPEN_READWRITE | FORCE_SAVE);
-                          message->SubmitMessage(0);
-                          gpgol_release (message);
-
-                          // Cancel send
-                          *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
-
-                          // Close the composer and trigger unloads
-                          CloseHandle(CreateThread (NULL, 0, close_mail, (LPVOID) m_mail, 0,
-                                                    NULL));
-                        }
-                      MAPIFreeBuffer (propval);
-                    }
-
-                  if (*(parms->rgvarg[0].pboolVal) == VARIANT_TRUE)
-                    {
-                      break;
-                    }
+                  log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
+                             SRCNAME, __func__, hr);
+                  gpgol_release (message);
+                  break;
+                }
+              if (propval->Value.lpszA && !strstr (propval->Value.lpszA, "GpgOL"))
+                {
+                  // Does not have a message class by us.
+                  log_debug ("%s:%s: Message %p - No GpgOL Message class after encryption.",
+                             SRCNAME, __func__, m_object);
+                  log_debug ("%s:%s: Message %p - Activating T3656 Workaround",
+                             SRCNAME, __func__, m_object);
+                  message = get_oom_base_message (m_object);
+                  // It's important we use the _base_ message here.
+                  mapi_save_changes (message, KEEP_OPEN_READWRITE | FORCE_SAVE);
+                  message->SubmitMessage(0);
+                  gpgol_release (message);
+
+                  // Cancel send
+                  *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
+
+                  // Close the composer and trigger unloads
+                  CloseHandle(CreateThread (NULL, 0, close_mail, (LPVOID) m_mail, 0,
+                                            NULL));
+                }
+              MAPIFreeBuffer (propval);
+              if (*(parms->rgvarg[0].pboolVal) == VARIANT_TRUE)
+                {
+                  break;
                 }
+#endif
               log_debug ("%s:%s: Passing send event for message %p.",
                          SRCNAME, __func__, m_object);
               break;
             }
           else
             {
-              log_debug ("%s:%s: Message %p cancelling send - crypto failed.",
+              log_debug ("%s:%s: Message %p cancelling send - "
+                         "crypto or second save failed.",
                          SRCNAME, __func__, m_object);
               *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
             }
@@ -524,8 +480,6 @@ EVENT_SINK_INVOKE(MailItemEvents)
               *(parms->rgvarg[0].pboolVal) = VARIANT_TRUE;
             }
 
-          log_debug ("%s:%s: Passing write event. Subject: %s Body: %s MsgCls: %s",
-                     SRCNAME, __func__, m_mail->get_subject().c_str(), m_mail->get_body().c_str(), get_oom_string (m_object, "MessageClass"));
           log_debug ("%s:%s: Passing write event.",
                      SRCNAME, __func__);
           m_mail->set_needs_save (false);
diff --git a/src/windowmessages.cpp b/src/windowmessages.cpp
index 815c217..fdb6ef0 100644
--- a/src/windowmessages.cpp
+++ b/src/windowmessages.cpp
@@ -98,15 +98,15 @@ gpgol_window_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                   break;
                 }
               // modify the mail.
-              if (mail->crypt_state (Mail::NeedsUpdateInOOM))
+              if (mail->crypt_state () == Mail::NeedsUpdateInOOM)
                 {
+                  // Save the Mail
+                  log_debug ("%s:%s: Crypto done for %p updating oom.",
+                             SRCNAME, __func__, mail);
                   mail->update_crypt_oom();
                 }
-              if (mail->crypt_state (Mail::NeedsSecondAfterWrite))
+              if (mail->crypt_state () == Mail::NeedsSecondAfterWrite)
                 {
-                  // Save the Mail
-                  log_debug ("%s:%s: Crypto done for %p Invoking second save.",
-                             SRCNAME, __func__, mail);
                   invoke_oom_method (mail->item (), "Save", NULL);
                   log_debug ("%s:%s: Second save done for %p Invoking second send.",
                              SRCNAME, __func__, mail);
@@ -115,7 +115,8 @@ gpgol_window_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
               invoke_oom_method (mail->item (), "Send", NULL);
             }
           default:
-            log_debug ("Unknown msg");
+            log_debug ("%s:%s: Unknown msg %x",
+                       SRCNAME, __func__, ctx->wmsg_type);
         }
         return DefWindowProc(hWnd, message, wParam, lParam);
     }

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

Summary of changes:
 src/cryptcontroller.cpp | 142 +++++++++++++++++++++++++++++++++++++++++++
 src/cryptcontroller.h   |  10 ++-
 src/mail.cpp            |  67 +++++++++++++++++---
 src/mail.h              |   6 ++
 src/mailitem-events.cpp | 158 +++++++++++++++++-------------------------------
 src/windowmessages.cpp  |  13 ++--
 6 files changed, 280 insertions(+), 116 deletions(-)


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




More information about the Gnupg-commits mailing list