Fix S/MIME encryption with latest Exchange 2016
authorAndre Heinecke <aheinecke@intevation.de>
Wed, 28 Mar 2018 09:12:10 +0000 (11:12 +0200)
committerAndre Heinecke <aheinecke@intevation.de>
Wed, 28 Mar 2018 09:12:10 +0000 (11:12 +0200)
* src/cryptcontroller.cpp (CryptController::update_mail_mapi):
Set overrideMimeTag to application/pkcs7-mime for smime enc.
* src/mimemaker.cpp (create_mapi_attachmend): Add overrideMimeTag
paramenter.
(create_top_encryption_header): Rearrange header for S/MIME enc.

--
Comparing outlooks own S/MIME mails with GpgOL mails lead to this.
Tests show that this way the mails do pass the exchange
server. With only slight variations we get errors.

GnuPG-Bug-Id: T3853

src/cryptcontroller.cpp
src/mimemaker.cpp
src/mimemaker.h

index 34b3af3..eddc9f7 100644 (file)
@@ -889,7 +889,18 @@ CryptController::update_mail_mapi ()
   sink->cb_data = &m_input;
   sink->writefnc = sink_data_write;
 
-  LPATTACH attach = create_mapi_attachment (message, sink);
+  // For S/MIME encrypted mails we have to use the multipart/encrypted
+  // content type. Otherwise newer (2016) exchange servers will throw
+  // an M2MCVT.StorageError.Exeption (See GnuPG-Bug-Id: T3853 )
+  std::string overrideMimeTag;
+  if (m_proto == GpgME::CMS && m_encrypt)
+    {
+      overrideMimeTag = "application/pkcs7-mime";
+    }
+
+  LPATTACH attach = create_mapi_attachment (message, sink,
+                                            overrideMimeTag.empty() ? nullptr :
+                                            overrideMimeTag.c_str());
   if (!attach)
     {
       log_error ("%s:%s: Failed to create moss attach.",
index 2108230..a7e9959 100644 (file)
@@ -153,7 +153,8 @@ check_protocol (protocol_t protocol)
    returned.  The caller needs to call SaveChanges.  Returns NULL on
    failure in which case STREAM will be set to NULL.  */
 LPATTACH
-create_mapi_attachment (LPMESSAGE message, sink_t sink)
+create_mapi_attachment (LPMESSAGE message, sink_t sink,
+                        const char *overrideMimeTag)
 {
   HRESULT hr;
   ULONG pos;
@@ -217,7 +218,13 @@ create_mapi_attachment (LPMESSAGE message, sink_t sink)
   if (!hr)
     {
       prop.ulPropTag = PR_ATTACH_MIME_TAG_A;
-      prop.Value.lpszA = strdup("multipart/signed");
+      prop.Value.lpszA = overrideMimeTag ? strdup (overrideMimeTag) :
+                         strdup ("multipart/signed");
+      if (overrideMimeTag)
+        {
+          log_debug ("%s:%s: using override mimetag: %s\n",
+                     SRCNAME, __func__, overrideMimeTag);
+        }
       hr = HrSetOneProp ((LPMAPIPROP)att, &prop);
       xfree (prop.Value.lpszA);
     }
@@ -1909,11 +1916,12 @@ create_top_encryption_header (sink_t sink, protocol_t protocol, char *boundary,
     {
       *boundary = 0;
       rc = write_multistring (sink,
-                              "MIME-Version: 1.0\r\n"
-                              "Content-Type: application/pkcs7-mime;\r\n"
-                              "\tsmime-type=enveloped-data;\r\n"
+                              "Content-Type: application/pkcs7-mime; "
+                              "smime-type=enveloped-data;\r\n"
                               "\tname=\"smime.p7m\"\r\n"
+                              "Content-Disposition: attachment; filename=\"smime.p7m\"\r\n"
                               "Content-Transfer-Encoding: base64\r\n"
+                              "MIME-Version: 1.0\r\n"
                               "\r\n",
                               NULL);
     }
index 32415fb..4758bfd 100644 (file)
@@ -83,7 +83,8 @@ int create_top_encryption_header (sink_t sink, protocol_t protocol, char *bounda
    will be written as well.  */
 int write_boundary (sink_t sink, const char *boundary, int lastone);
 
-LPATTACH create_mapi_attachment (LPMESSAGE message, sink_t sink);
+LPATTACH create_mapi_attachment (LPMESSAGE message, sink_t sink,
+                                 const char *overrideMimeTag = nullptr);
 int close_mapi_attachment (LPATTACH *attach, sink_t sink);
 int finalize_message (LPMESSAGE message, mapi_attach_item_t *att_table,
                       protocol_t protocol, int encrypt, bool is_inline = false);