Add minimalistic protected-headers support
[gpgol.git] / src / mimedataprovider.cpp
1 /* mimedataprover.cpp - GpgME dataprovider for mime data
2  * Copyright (C) 2016 by Bundesamt für Sicherheit in der Informationstechnik
3  * Software engineering by Intevation GmbH
4  *
5  * This file is part of GpgOL.
6  *
7  * GpgOL is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * GpgOL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 #include "config.h"
21 #include "common_indep.h"
22 #include "xmalloc.h"
23 #include <string.h>
24 #include <vector>
25 #include <sstream>
26
27 #include "mimedataprovider.h"
28 #include "rfc822parse.h"
29 #include "rfc2047parse.h"
30 #include "attachment.h"
31 #include "cpphelp.h"
32
33 #ifndef HAVE_W32_SYSTEM
34 #define stricmp strcasecmp
35 #endif
36
37 /* The maximum length of a line we are able to process.  RFC822 allows
38    only for 1000 bytes; thus 2000 seems to be a reasonable value. */
39 #define LINEBUFSIZE 2000
40
41 /* How much data is read at once in collect */
42 #define BUFSIZE 8192
43
44 #include <gpgme++/error.h>
45
46 /* To keep track of the MIME message structures we use a linked list
47    with each item corresponding to one part. */
48 struct mimestruct_item_s;
49 typedef struct mimestruct_item_s *mimestruct_item_t;
50 struct mimestruct_item_s
51 {
52   mimestruct_item_t next;
53   unsigned int level;   /* Level in the hierarchy of that part.  0
54                            indicates the outer body.  */
55   char *filename;       /* Malloced filename or NULL.  */
56   char *cid;            /* Malloced content id or NULL. */
57   char *charset;        /* Malloced charset or NULL.  */
58   char content_type[1]; /* String with the content type. */
59 };
60
61 /* The context object we use to track information. */
62 struct mime_context
63 {
64   rfc822parse_t msg;  /* The handle of the RFC822 parser. */
65
66   int verify_mode;    /* True if we want to verify a signature. */
67
68   int nesting_level;  /* Current MIME nesting level. */
69   int in_data;        /* We are currently in data (body or attachment). */
70   int body_seen;      /* True if we have seen a part we consider the
71                          body of the message.  */
72
73   std::shared_ptr<Attachment> current_attachment; /* A pointer to the current
74                                                      attachment */
75   int collect_body;       /* True if we are collcting the body */
76   int collect_html_body;  /* True if we are collcting the html body */
77   int collect_crypto_data; /* True if we are collecting the signed data. */
78   int collect_signature;  /* True if we are collecting a signature.  */
79   int pgp_marker_checked; /* Checked if the first body line is pgp marker*/
80   int is_encrypted;       /* True if we are working on an encrypted mail. */
81   int start_hashing;      /* Flag used to start collecting signed data. */
82   int hashing_level;      /* MIME level where we started hashing. */
83   int is_qp_encoded;      /* Current part is QP encoded. */
84   int is_base64_encoded;  /* Current part is base 64 encoded. */
85   int is_body;            /* The current part belongs to the body.  */
86   protocol_t protocol;    /* The detected crypto protocol.  */
87
88   int part_counter;       /* Counts the number of processed parts. */
89   int any_boundary;       /* Indicates whether we have seen any
90                              boundary which means that we are actually
91                              working on a MIME message and not just on
92                              plain rfc822 message.  */
93
94   /* A linked list describing the structure of the mime message.  This
95      list gets build up while parsing the message.  */
96   mimestruct_item_t mimestruct;
97   mimestruct_item_t *mimestruct_tail;
98   mimestruct_item_t mimestruct_cur;
99
100   int any_attachments_created;  /* True if we created a new atatchment.  */
101
102   b64_state_t base64;     /* The state of the Base-64 decoder.  */
103
104   gpg_error_t parser_error;   /* Indicates that we encountered a error from
105                                  the parser. */
106 };
107 typedef struct mime_context *mime_context_t;
108
109 /* Print the message event EVENT. */
110 static void
111 debug_message_event (rfc822parse_event_t event)
112 {
113   const char *s;
114
115   switch (event)
116     {
117     case RFC822PARSE_OPEN: s= "Open"; break;
118     case RFC822PARSE_CLOSE: s= "Close"; break;
119     case RFC822PARSE_CANCEL: s= "Cancel"; break;
120     case RFC822PARSE_T2BODY: s= "T2Body"; break;
121     case RFC822PARSE_FINISH: s= "Finish"; break;
122     case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break;
123     case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break;
124     case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break;
125     case RFC822PARSE_BOUNDARY: s= "Boundary"; break;
126     case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break;
127     case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break;
128     case RFC822PARSE_PREAMBLE: s= "Preamble"; break;
129     case RFC822PARSE_EPILOGUE: s= "Epilogue"; break;
130     default: s= "[unknown event]"; break;
131     }
132   log_data ("%s: rfc822 event %s\n", SRCNAME, s);
133 }
134
135 /* returns true if the BER encoded data in BUFFER is CMS signed data.
136    LENGTH gives the length of the buffer, for correct detection LENGTH
137    should be at least about 24 bytes.  */
138 #if 0
139 static int
140 is_cms_signed_data (const char *buffer, size_t length)
141 {
142   TSTART;
143   const char *p = buffer;
144   size_t n = length;
145   tlvinfo_t ti;
146
147   if (parse_tlv (&p, &n, &ti))
148     {
149       TRETURN 0;
150     }
151   if (!(ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_SEQUENCE
152         && ti.is_cons) )
153     TRETURN 0;
154   if (parse_tlv (&p, &n, &ti))
155     {
156       TRETURN 0;
157     }
158   if (!(ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_OBJECT_ID
159         && !ti.is_cons && ti.length) || ti.length > n)
160     TRETURN 0;
161   if (ti.length == 9 && !memcmp (p, "\x2A\x86\x48\x86\xF7\x0D\x01\x07\x02", 9))
162     {
163       TRETURN 1;
164     }
165   TRETURN 0;
166 }
167 #endif
168
169 /* Process the transition to body event.
170
171    This means we have received the empty line indicating the body and
172    should now check the headers to see what to do about this part.
173
174    This is mostly a C style function because it was based on the old
175    c mimeparser.
176 */
177 static int
178 t2body (MimeDataProvider *provider, rfc822parse_t msg)
179 {
180   TSTART;
181   rfc822parse_field_t field;
182   mime_context_t ctx = provider->mime_context ();
183   const char *ctmain, *ctsub;
184   const char *s;
185   size_t off;
186   char *p;
187   int is_text = 0;
188   int is_text_attachment = 0;
189   int is_protected_headers = 0;
190   char *filename = NULL;
191   char *cid = NULL;
192   char *charset = NULL;
193   bool ignore_cid = false;
194
195   /* Figure out the encoding.  */
196   ctx->is_qp_encoded = 0;
197   ctx->is_base64_encoded = 0;
198   p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off);
199   if (p)
200     {
201       if (!stricmp (p+off, "quoted-printable"))
202         ctx->is_qp_encoded = 1;
203       else if (!stricmp (p+off, "base64"))
204         {
205           ctx->is_base64_encoded = 1;
206           b64_init (&ctx->base64);
207         }
208       xfree (p);
209     }
210
211   /* Get the filename from the header.  */
212   field = rfc822parse_parse_field (msg, "Content-Disposition", -1);
213   if (field)
214     {
215       s = rfc822parse_query_parameter (field, "filename", 0);
216       if (s)
217         filename = rfc2047_parse (s);
218       s = rfc822parse_query_parameter (field, NULL, 1);
219
220       if (s && strstr (s, "attachment"))
221         {
222           log_debug ("%s:%s: Found Content-Disposition attachment."
223                      " Ignoring content-id to avoid hiding.",
224                      SRCNAME, __func__);
225           ignore_cid = true;
226         }
227
228       /* This is a bit of a taste matter how to treat inline
229          attachments. Outlook does not show them inline so we
230          should not put it in the body either as we have
231          no way to show that it was actually an attachment.
232          For something like an inline patch it is better
233          to add it as an attachment instead of just putting
234          it in the body.
235
236          The handling in the old parser was:
237
238          if (s && strcmp (s, "inline"))
239            not_inline_text = 1;
240        */
241       if (ctx->body_seen)
242         {
243           /* Some MUA's like kontact e3.5 send the body as
244              an inline text attachment. So if we have not
245              seen the body yet we treat the first text/plain
246              element as the body and not as an inline attachment. */
247           is_text_attachment = 1;
248         }
249       rfc822parse_release_field (field);
250     }
251
252   /* Process the Content-type and all its parameters.  */
253   ctmain = ctsub = NULL;
254   field = rfc822parse_parse_field (msg, "Content-Type", -1);
255   if (field)
256     ctmain = rfc822parse_query_media_type (field, &ctsub);
257   if (!ctmain)
258     {
259       /* Either there is no content type field or it is faulty; in
260          both cases we fall back to text/plain.  */
261       ctmain = "text";
262       ctsub  = "plain";
263     }
264
265   log_data ("%s:%s: ctx=%p, ct=`%s/%s'\n",
266                    SRCNAME, __func__, ctx, ctmain, ctsub);
267
268   s = rfc822parse_query_parameter (field, "charset", 0);
269   if (s)
270     charset = xstrdup (s);
271
272   if (!filename)
273     {
274       /* Check for Content-Type name if Content-Disposition filename
275          was not found */
276       s = rfc822parse_query_parameter (field, "name", 0);
277       if (s)
278         filename = rfc2047_parse (s);
279     }
280
281   /* Parse a Content Id header */
282   if (!ignore_cid)
283     {
284       p = rfc822parse_get_field (msg, "Content-Id", -1, &off);
285       if (p)
286         {
287            cid = xstrdup (p+off);
288            xfree (p);
289         }
290     }
291   /* Update our idea of the entire MIME structure.  */
292   {
293     mimestruct_item_t ms;
294
295     ms = (mimestruct_item_t) xmalloc (sizeof *ms + strlen (ctmain) + 1 + strlen (ctsub));
296     ctx->mimestruct_cur = ms;
297     *ctx->mimestruct_tail = ms;
298     ctx->mimestruct_tail = &ms->next;
299     ms->next = NULL;
300     strcpy (stpcpy (stpcpy (ms->content_type, ctmain), "/"), ctsub);
301     ms->level = ctx->nesting_level;
302     ms->filename = filename;
303     ms->cid = cid;
304     filename = NULL;
305     ms->charset = charset;
306     charset = NULL;
307   }
308
309   if (!strcmp (ctmain, "multipart"))
310     {
311       /* We don't care about the top level multipart layer but wait
312          until it comes to the actual parts which then will get stored
313          as attachments.
314
315          For now encapsulated signed or encrypted containers are not
316          processed in a special way as they should.  Except for the
317          simple verify mode. */
318       if (!provider->signature()
319           && !strcmp (ctsub, "signed")
320           && (s = rfc822parse_query_parameter (field, "protocol", 0)))
321         {
322           if (!strcmp (s, "application/pgp-signature"))
323             ctx->protocol = PROTOCOL_OPENPGP;
324           else if (!strcmp (s, "application/pkcs7-signature")
325                    || !strcmp (s, "application/x-pkcs7-signature"))
326             ctx->protocol = PROTOCOL_SMIME;
327           else
328             ctx->protocol = PROTOCOL_UNKNOWN;
329
330           /* Need to start the hashing after the next boundary. */
331           ctx->start_hashing = 1;
332         }
333       else if (!strcmp (ctsub, "encrypted") &&
334                (s = rfc822parse_query_parameter (field, "protocol", 0)))
335         {
336            if (!strcmp (s, "application/pgp-encrypted"))
337              ctx->protocol = PROTOCOL_OPENPGP;
338            /* We expect an encrypted mime part. */
339            ctx->is_encrypted = 1;
340         }
341     }
342   else if (!strcmp (ctmain, "text"))
343     {
344       is_text = !strcmp (ctsub, "html")? 2:1;
345       is_protected_headers = (!strcmp (ctsub, "rfc822-headers") &&
346                               rfc822parse_query_parameter (field,
347                                                     "protected-headers", -1));
348       if (is_protected_headers)
349         {
350           log_data ("%s:%s: Found protected headers.",
351                            SRCNAME, __func__);
352           provider->m_had_protected_headers = true;
353         }
354     }
355   else if (ctx->nesting_level == 1 && !provider->signature()
356            && !strcmp (ctmain, "application")
357            && ((ctx->protocol == PROTOCOL_OPENPGP
358                 && !strcmp (ctsub, "pgp-signature"))
359                || (ctx->protocol == PROTOCOL_SMIME
360                    && (!strcmp (ctsub, "pkcs7-signature")
361                        || !strcmp (ctsub, "x-pkcs7-signature")))))
362     {
363       /* This is the second part of a MOSS signature.  We only support
364          here full messages thus checking the nesting level is
365          sufficient.  We do this only for the first signature (i.e. if
366          sig_data has not been set yet).  We also do this only while
367          in verify mode because we don't want to write a full MUA.  */
368       ctx->collect_signature = 1;
369       log_data ("%s:%s: Collecting signature.",
370                        SRCNAME, __func__);
371     }
372   else if (ctx->nesting_level == 1 && ctx->is_encrypted
373            && !strcmp (ctmain, "application")
374            && (ctx->protocol == PROTOCOL_OPENPGP
375                && !strcmp (ctsub, "octet-stream")))
376     {
377       log_data ("%s:%s: Collecting encrypted PGP data.",
378                        SRCNAME, __func__);
379       ctx->collect_crypto_data = 1;
380     }
381   else /* Other type. */
382     {
383       /* Check whether this attachment is an opaque signed S/MIME
384          part.  We use a counter to later check that there is only one
385          such part. */
386       if (!strcmp (ctmain, "application")
387           && (!strcmp (ctsub, "pkcs7-mime")
388               || !strcmp (ctsub, "x-pkcs7-mime")))
389         {
390           log_data ("%s:%s: Collecting crypted S/MIME data.",
391                            SRCNAME, __func__);
392           ctx->collect_crypto_data = 1;
393         }
394     }
395   rfc822parse_release_field (field); /* (Content-type) */
396   if (!is_protected_headers)
397     {
398       ctx->in_data = 1;
399     }
400
401   log_data ("%s:%s: this body: nesting=%d partno=%d is_text=%d"
402                    " charset=\"%s\"\n body_seen=%d is_text_attachment=%d"
403                    " is_protected_headers=%d",
404                    SRCNAME, __func__,
405                    ctx->nesting_level, ctx->part_counter, is_text,
406                    ctx->mimestruct_cur->charset?ctx->mimestruct_cur->charset:"",
407                    ctx->body_seen, is_text_attachment, is_protected_headers);
408
409   /* If this is a text part, decide whether we treat it as one
410      of our bodies.
411      */
412   if ((is_text && !is_text_attachment))
413     {
414       if (is_text == 2)
415         {
416           ctx->body_seen = 2;
417           ctx->collect_html_body = 1;
418           ctx->collect_body = 0;
419           log_debug ("%s:%s: Collecting HTML body.",
420                      SRCNAME, __func__);
421           /* We need this crutch because of one liner html
422              mails which would not be collected by the line
423              collector if they dont have a linefeed at the
424              end. */
425           provider->set_has_html_body (true);
426         }
427       else
428         {
429           log_debug ("%s:%s: Collecting text body.",
430                      SRCNAME, __func__);
431           ctx->body_seen = 1;
432           ctx->collect_body = 1;
433           ctx->collect_html_body = 0;
434         }
435     }
436   else if (!ctx->collect_crypto_data && ctx->nesting_level >= 1)
437     {
438       /* Treat it as an attachment.  */
439       ctx->current_attachment = provider->create_attachment();
440       ctx->collect_body = 0;
441       ctx->collect_html_body = 0;
442       log_data ("%s:%s: Collecting attachment.",
443                        SRCNAME, __func__);
444     }
445
446   TRETURN 0;
447 }
448
449 static int
450 message_cb (void *opaque, rfc822parse_event_t event,
451             rfc822parse_t msg)
452 {
453   int retval = 0;
454
455   MimeDataProvider *provider = static_cast<MimeDataProvider*> (opaque);
456
457   mime_context_t ctx = provider->mime_context();
458
459   debug_message_event (event);
460
461   if (event == RFC822PARSE_BEGIN_HEADER || event == RFC822PARSE_T2BODY)
462     {
463       /* We need to check here whether to start collecting signed data
464          because attachments might come without header lines and thus
465          we won't see the BEGIN_HEADER event. */
466       if (ctx->start_hashing == 1)
467         {
468           ctx->start_hashing = 2;
469           ctx->hashing_level = ctx->nesting_level;
470           ctx->collect_crypto_data = 1;
471         }
472     }
473
474
475   switch (event)
476     {
477     case RFC822PARSE_T2BODY:
478       retval = t2body (provider, msg);
479       break;
480
481     case RFC822PARSE_LEVEL_DOWN:
482       ctx->nesting_level++;
483       break;
484
485     case RFC822PARSE_LEVEL_UP:
486       if (ctx->nesting_level)
487         ctx->nesting_level--;
488       else
489         {
490           log_error ("%s: ctx=%p, invalid structure: bad nesting level\n",
491                      SRCNAME, ctx);
492           ctx->parser_error = gpg_error (GPG_ERR_GENERAL);
493         }
494       break;
495
496     case RFC822PARSE_BOUNDARY:
497     case RFC822PARSE_LAST_BOUNDARY:
498       ctx->any_boundary = 1;
499       ctx->in_data = 0;
500       ctx->collect_body = 0;
501
502       if (ctx->start_hashing == 2 && ctx->hashing_level == ctx->nesting_level)
503         {
504           ctx->start_hashing = 3; /* Avoid triggering it again. */
505           ctx->collect_crypto_data = 0;
506         }
507       break;
508
509     case RFC822PARSE_BEGIN_HEADER:
510       ctx->part_counter++;
511       break;
512
513     default:  /* Ignore all other events. */
514       break;
515     }
516
517   return retval;
518 }
519
520 MimeDataProvider::MimeDataProvider(bool no_headers) :
521   m_signature(nullptr),
522   m_has_html_body(false),
523   m_collect_everything(no_headers)
524 {
525   TSTART;
526   memdbg_ctor ("MimeDataProvider");
527   m_mime_ctx = (mime_context_t) xcalloc (1, sizeof *m_mime_ctx);
528   m_mime_ctx->msg = rfc822parse_open (message_cb, this);
529   m_mime_ctx->mimestruct_tail = &m_mime_ctx->mimestruct;
530   TRETURN;
531 }
532
533 #ifdef HAVE_W32_SYSTEM
534 MimeDataProvider::MimeDataProvider(LPSTREAM stream, bool no_headers):
535   MimeDataProvider(no_headers)
536 {
537   TSTART;
538   if (stream)
539     {
540       stream->AddRef ();
541       memdbg_addRef (stream);
542     }
543   else
544     {
545       log_error ("%s:%s called without stream ", SRCNAME, __func__);
546       TRETURN;
547     }
548   log_data ("%s:%s Collecting data.", SRCNAME, __func__);
549   collect_data (stream);
550   log_data ("%s:%s Data collected.", SRCNAME, __func__);
551   gpgol_release (stream);
552   TRETURN;
553 }
554 #endif
555
556 MimeDataProvider::MimeDataProvider(FILE *stream, bool no_headers):
557   MimeDataProvider(no_headers)
558 {
559   TSTART;
560   log_data ("%s:%s Collecting data from file.", SRCNAME, __func__);
561   collect_data (stream);
562   log_data ("%s:%s Data collected.", SRCNAME, __func__);
563   TRETURN;
564 }
565
566 MimeDataProvider::~MimeDataProvider()
567 {
568   TSTART;
569   memdbg_dtor ("MimeDataProvider");
570   log_debug ("%s:%s", SRCNAME, __func__);
571   while (m_mime_ctx->mimestruct)
572     {
573       mimestruct_item_t tmp = m_mime_ctx->mimestruct->next;
574       xfree (m_mime_ctx->mimestruct->filename);
575       xfree (m_mime_ctx->mimestruct->charset);
576       xfree (m_mime_ctx->mimestruct->cid);
577       xfree (m_mime_ctx->mimestruct);
578       m_mime_ctx->mimestruct = tmp;
579     }
580   rfc822parse_close (m_mime_ctx->msg);
581   m_mime_ctx->current_attachment = NULL;
582   xfree (m_mime_ctx);
583   if (m_signature)
584     {
585       delete m_signature;
586     }
587   TRETURN;
588 }
589
590 bool
591 MimeDataProvider::isSupported(GpgME::DataProvider::Operation op) const
592 {
593   return op == GpgME::DataProvider::Read ||
594          op == GpgME::DataProvider::Seek ||
595          op == GpgME::DataProvider::Write ||
596          op == GpgME::DataProvider::Release;
597 }
598
599 ssize_t
600 MimeDataProvider::read(void *buffer, size_t size)
601 {
602   TSTART;
603   log_data ("%s:%s: Reading: " SIZE_T_FORMAT "Bytes",
604                  SRCNAME, __func__, size);
605   ssize_t bRead = m_crypto_data.read (buffer, size);
606   if ((opt.enable_debug & DBG_DATA) && bRead)
607     {
608       std::string buf ((char *)buffer, bRead);
609
610       if (!is_binary (buf))
611         {
612           log_data ("%s:%s: Data: \n------\n%s\n------",
613                            SRCNAME, __func__, buf.c_str());
614         }
615       else
616         {
617           log_data ("%s:%s: Hex Data: \n------\n%s\n------",
618                            SRCNAME, __func__,
619                            string_to_hex (buf).c_str ());
620         }
621     }
622   TRETURN bRead;
623 }
624
625 /* Split some raw data into lines and handle them accordingly.
626    Returns the amount of bytes not taken from the input buffer.
627 */
628 size_t
629 MimeDataProvider::collect_input_lines(const char *input, size_t insize)
630 {
631   TSTART;
632   char linebuf[LINEBUFSIZE];
633   const char *s = input;
634   size_t pos = 0;
635   size_t nleft = insize;
636   size_t not_taken = nleft;
637   size_t len = 0;
638
639   /* Split the raw data into lines */
640   for (; nleft; nleft--, s++)
641     {
642       if (pos >= LINEBUFSIZE)
643         {
644           log_error ("%s:%s: rfc822 parser failed: line too long\n",
645                      SRCNAME, __func__);
646           GpgME::Error::setSystemError (GPG_ERR_EIO);
647           TRETURN not_taken;
648         }
649       if (*s != '\n')
650         linebuf[pos++] = *s;
651       else
652         {
653           /* Got a complete line.  Remove the last CR.  */
654           not_taken -= pos + 1; /* Pos starts at 0 so + 1 for it */
655           if (pos && linebuf[pos-1] == '\r')
656             {
657               pos--;
658             }
659
660           log_data ("%s:%s: Parsing line=`%.*s'\n",
661                          SRCNAME, __func__, (int)pos, linebuf);
662           /* Check the next state */
663           if (rfc822parse_insert (m_mime_ctx->msg,
664                                   (unsigned char*) linebuf,
665                                   pos))
666             {
667               log_error ("%s:%s: rfc822 parser failed: %s\n",
668                          SRCNAME, __func__, strerror (errno));
669               TRETURN not_taken;
670             }
671
672           /* Check if the first line of the body is actually
673              a PGP Inline message. If so treat it as crypto data. */
674           if (!m_mime_ctx->pgp_marker_checked && m_mime_ctx->collect_body == 2)
675             {
676               m_mime_ctx->pgp_marker_checked = true;
677               if (pos >= 27 && !strncmp ("-----BEGIN PGP MESSAGE-----", linebuf, 27))
678                 {
679                   log_debug ("%s:%s: Found PGP Message in body.",
680                              SRCNAME, __func__);
681                   m_mime_ctx->collect_body = 0;
682                   m_mime_ctx->collect_crypto_data = 1;
683                   m_mime_ctx->start_hashing = 1;
684                   m_collect_everything = true;
685                 }
686             }
687
688           /* If we are currently in a collecting state actually
689              collect that line */
690           if (m_mime_ctx->collect_crypto_data && m_mime_ctx->start_hashing)
691             {
692               /* Save the signed data.  Note that we need to delay
693                  the CR/LF because the last line ending belongs to the
694                  next boundary. */
695               if (m_mime_ctx->collect_crypto_data == 2)
696                 {
697                   m_crypto_data.write ("\r\n", 2);
698                 }
699               log_data ("Writing raw crypto data: %.*s",
700                                (int)pos, linebuf);
701               m_crypto_data.write (linebuf, pos);
702               m_mime_ctx->collect_crypto_data = 2;
703             }
704           if (m_mime_ctx->in_data && !m_mime_ctx->collect_signature &&
705               !m_mime_ctx->collect_crypto_data)
706             {
707               /* We are inside of an attachment part.  Write it out. */
708               if (m_mime_ctx->in_data == 1)  /* Skip the first line. */
709                 m_mime_ctx->in_data = 2;
710
711               int slbrk = 0;
712               if (m_mime_ctx->is_qp_encoded)
713                 len = qp_decode (linebuf, pos, &slbrk);
714               else if (m_mime_ctx->is_base64_encoded)
715                 len = b64_decode (&m_mime_ctx->base64, linebuf, pos);
716               else
717                 len = pos;
718
719               if (m_mime_ctx->collect_body)
720                 {
721                   if (m_mime_ctx->collect_body == 2)
722                     {
723                       m_body += std::string(linebuf, len);
724                       if (!m_mime_ctx->is_base64_encoded && !slbrk)
725                         {
726                           m_body += "\r\n";
727                         }
728                     }
729                   if (m_body_charset.empty())
730                     {
731                       m_body_charset = m_mime_ctx->mimestruct_cur->charset ?
732                                        m_mime_ctx->mimestruct_cur->charset : "";
733                     }
734                   m_mime_ctx->collect_body = 2;
735                 }
736               else if (m_mime_ctx->collect_html_body)
737                 {
738                   if (m_mime_ctx->collect_html_body == 2)
739                     {
740                       m_html_body += std::string(linebuf, len);
741                       if (!m_mime_ctx->is_base64_encoded && !slbrk)
742                         {
743                           m_html_body += "\r\n";
744                         }
745                     }
746                   if (m_html_charset.empty())
747                     {
748                       m_html_charset = m_mime_ctx->mimestruct_cur->charset ?
749                                        m_mime_ctx->mimestruct_cur->charset : "";
750                     }
751                   m_mime_ctx->collect_html_body = 2;
752                 }
753               else if (m_mime_ctx->current_attachment && len)
754                 {
755                   m_mime_ctx->current_attachment->get_data().write(linebuf, len);
756                   if (!m_mime_ctx->is_base64_encoded && !slbrk)
757                     {
758                       m_mime_ctx->current_attachment->get_data().write("\r\n", 2);
759                     }
760                 }
761               else
762                 {
763                   log_data ("%s:%s Collecting ended / failed.",
764                                    SRCNAME, __func__);
765                 }
766             }
767           else if (m_mime_ctx->in_data && m_mime_ctx->collect_signature)
768             {
769               /* We are inside of a signature attachment part.  */
770               if (m_mime_ctx->collect_signature == 1)  /* Skip the first line. */
771                 m_mime_ctx->collect_signature = 2;
772               else
773                 {
774                   int slbrk = 0;
775
776                   if (m_mime_ctx->is_qp_encoded)
777                     len = qp_decode (linebuf, pos, &slbrk);
778                   else if (m_mime_ctx->is_base64_encoded)
779                     len = b64_decode (&m_mime_ctx->base64, linebuf, pos);
780                   else
781                     len = pos;
782                   if (!m_signature)
783                     {
784                       m_signature = new GpgME::Data();
785                     }
786                   if (len)
787                     m_signature->write(linebuf, len);
788                   if (!m_mime_ctx->is_base64_encoded && !slbrk)
789                     m_signature->write("\r\n", 2);
790                 }
791             }
792           else if (m_mime_ctx->in_data && !m_mime_ctx->start_hashing)
793             {
794               /* We are inside the data.  That should be the actual
795                  ciphertext in the given encoding. */
796               int slbrk = 0;
797
798               if (m_mime_ctx->is_qp_encoded)
799                 len = qp_decode (linebuf, pos, &slbrk);
800               else if (m_mime_ctx->is_base64_encoded)
801                 len = b64_decode (&m_mime_ctx->base64, linebuf, pos);
802               else
803                 len = pos;
804               log_data ("Writing crypto data: %.*s",
805                          (int)pos, linebuf);
806               if (len)
807                 m_crypto_data.write(linebuf, len);
808               if (!m_mime_ctx->is_base64_encoded && !slbrk)
809                 m_crypto_data.write("\r\n", 2);
810             }
811           /* Continue with next line. */
812           pos = 0;
813         }
814     }
815   TRETURN not_taken;
816 }
817
818 #ifdef HAVE_W32_SYSTEM
819 void
820 MimeDataProvider::collect_data(LPSTREAM stream)
821 {
822   TSTART;
823   if (!stream)
824     {
825       TRETURN;
826     }
827   HRESULT hr;
828   char buf[BUFSIZE];
829   ULONG bRead;
830   bool first_read = true;
831   bool is_pgp_message = false;
832   size_t allRead = 0;
833   while ((hr = stream->Read (buf, BUFSIZE, &bRead)) == S_OK ||
834          hr == S_FALSE)
835     {
836       if (!bRead)
837         {
838           log_data ("%s:%s: Input stream at EOF.",
839                            SRCNAME, __func__);
840           break;
841         }
842       log_data ("%s:%s: Read %lu bytes.",
843                        SRCNAME, __func__, bRead);
844       allRead += bRead;
845       if (first_read)
846         {
847           if (bRead > 12 && strncmp ("MIME-Version", buf, 12) == 0)
848             {
849               /* Fun! In case we have exchange or sent messages created by us
850                  we get the mail attachment like it is before the MAPI to MIME
851                  conversion. So it has our MIME structure. In that case
852                  we have to expect MIME data even if the initial data check
853                  suggests that we don't.
854
855                  Checking if the content starts with MIME-Version appears
856                  to be a robust way to check if we try to parse MIME data. */
857               m_collect_everything = false;
858               log_debug ("%s:%s: Found MIME-Version marker."
859                          "Expecting headers even if type suggested not to.",
860                          SRCNAME, __func__);
861
862             }
863           else if (bRead > 12 && !strncmp ("Content-Type:", buf, 13))
864             {
865               /* Similar as above but we messed with the order of the headers
866                  for some s/mime mails. So also check for content type.
867
868                  Want some cheese with that hack?
869               */
870               m_collect_everything = false;
871               log_debug ("%s:%s: Found Content-Type header."
872                          "Expecting headers even if type suggested not to.",
873                          SRCNAME, __func__);
874
875             }
876           /* check for the PGP MESSAGE marker to see if we have it. */
877           if (bRead && m_collect_everything)
878             {
879               std::string tmp (buf, bRead);
880               std::size_t found = tmp.find ("-----BEGIN PGP MESSAGE-----");
881               if (found != std::string::npos)
882                 {
883                   log_debug ("%s:%s: found PGP Message marker,",
884                              SRCNAME, __func__);
885                   is_pgp_message = true;
886                 }
887             }
888         }
889       first_read = false;
890
891       if (m_collect_everything)
892         {
893           /* For S/MIME, Clearsigned, PGP MESSAGES we just pass everything
894              on. Only the Multipart classes need parsing. And the output
895              of course. */
896           log_data ("%s:%s: Just copying data.",
897                            SRCNAME, __func__);
898           m_crypto_data.write ((void*)buf, (size_t) bRead);
899           continue;
900         }
901       m_rawbuf += std::string (buf, bRead);
902       size_t not_taken = collect_input_lines (m_rawbuf.c_str(),
903                                               m_rawbuf.size());
904
905       if (not_taken == m_rawbuf.size())
906         {
907           log_error ("%s:%s: Collect failed to consume anything.\n"
908                      "Buffer too small?",
909                      SRCNAME, __func__);
910           break;
911         }
912       log_data ("%s:%s: Consumed: " SIZE_T_FORMAT " bytes",
913                        SRCNAME, __func__, m_rawbuf.size() - not_taken);
914       m_rawbuf.erase (0, m_rawbuf.size() - not_taken);
915     }
916
917
918   if (is_pgp_message && allRead < (1024 * 100))
919     {
920       /* Sometimes received PGP Messsages contain extra whitespace /
921          newlines. To also accept such messages we fix up pgp inline
922          messages here. We only do this for messages which are smaller
923          then a hundred KByte for performance. */
924       log_debug ("%s:%s: Fixing up a possible broken message.",
925                  SRCNAME, __func__);
926       /* Copy crypto data to string */
927       std::string data = m_crypto_data.toString();
928       m_crypto_data = GpgME::Data();
929       std::istringstream iss (data);
930       // Now parse it by line.
931       std::string line;
932       while (std::getline (iss, line))
933         {
934           trim (line);
935           if (line == "-----BEGIN PGP MESSAGE-----")
936             {
937               /* Finish an armor header */
938               line += "\n\n";
939               m_crypto_data.write (line.c_str (), line.size ());
940               continue;
941             }
942           /* Remove empty lines */
943           if (line.empty())
944             {
945               continue;
946             }
947           if (line.find (':') != std::string::npos)
948             {
949               log_data ("%s:%s: Removing comment '%s'.",
950                                SRCNAME, __func__, line.c_str ());
951               continue;
952             }
953           line += '\n';
954           m_crypto_data.write (line.c_str (), line.size ());
955         }
956     }
957   TRETURN;
958 }
959 #endif
960
961 void
962 MimeDataProvider::collect_data(FILE *stream)
963 {
964   TSTART;
965   if (!stream)
966     {
967       TRETURN;
968     }
969   char buf[BUFSIZE];
970   size_t bRead;
971   while ((bRead = fread (buf, 1, BUFSIZE, stream)) > 0)
972     {
973       log_data ("%s:%s: Read " SIZE_T_FORMAT " bytes.",
974                        SRCNAME, __func__, bRead);
975
976       if (m_collect_everything)
977         {
978           /* For S/MIME, Clearsigned, PGP MESSAGES we just pass everything
979              on. Only the Multipart classes need parsing. And the output
980              of course. */
981           log_data ("%s:%s: Making verbatim copy" SIZE_T_FORMAT " bytes.",
982                            SRCNAME, __func__, bRead);
983           m_crypto_data.write ((void*)buf, bRead);
984           continue;
985         }
986       m_rawbuf += std::string (buf, bRead);
987       size_t not_taken = collect_input_lines (m_rawbuf.c_str(),
988                                               m_rawbuf.size());
989
990       if (not_taken == m_rawbuf.size())
991         {
992           log_error ("%s:%s: Collect failed to consume anything.\n"
993                      "Buffer too small?",
994                      SRCNAME, __func__);
995           TRETURN;
996         }
997       log_data ("%s:%s: Consumed: " SIZE_T_FORMAT " bytes",
998                        SRCNAME, __func__, m_rawbuf.size() - not_taken);
999       m_rawbuf.erase (0, m_rawbuf.size() - not_taken);
1000     }
1001   TRETURN;
1002 }
1003
1004 ssize_t MimeDataProvider::write(const void *buffer, size_t bufSize)
1005 {
1006   TSTART;
1007   if (m_collect_everything)
1008     {
1009       /* Writing with collect everything one means that we are outputprovider.
1010          In this case for inline messages we want to collect everything. */
1011       log_data ("%s:%s: Using complete input as body " SIZE_T_FORMAT " bytes.",
1012                        SRCNAME, __func__, bufSize);
1013       m_body += std::string ((const char *) buffer, bufSize);
1014       TRETURN bufSize;
1015     }
1016   m_rawbuf += std::string ((const char*)buffer, bufSize);
1017   size_t not_taken = collect_input_lines (m_rawbuf.c_str(),
1018                                           m_rawbuf.size());
1019
1020   if (not_taken == m_rawbuf.size())
1021     {
1022       log_error ("%s:%s: Write failed to consume anything.\n"
1023                  "Buffer too small? or no newlines in text?",
1024                  SRCNAME, __func__);
1025       TRETURN bufSize;
1026     }
1027   log_data ("%s:%s: Write Consumed: " SIZE_T_FORMAT " bytes",
1028                    SRCNAME, __func__, m_rawbuf.size() - not_taken);
1029   m_rawbuf.erase (0, m_rawbuf.size() - not_taken);
1030   TRETURN bufSize;
1031 }
1032
1033 off_t
1034 MimeDataProvider::seek(off_t offset, int whence)
1035 {
1036   return m_crypto_data.seek (offset, whence);
1037 }
1038
1039 GpgME::Data *
1040 MimeDataProvider::signature() const
1041 {
1042   TSTART;
1043   TRETURN m_signature;
1044 }
1045
1046 std::shared_ptr<Attachment>
1047 MimeDataProvider::create_attachment()
1048 {
1049   TSTART;
1050   log_data ("%s:%s: Creating attachment.",
1051                    SRCNAME, __func__);
1052
1053   auto attach = std::shared_ptr<Attachment> (new Attachment());
1054   attach->set_attach_type (ATTACHTYPE_FROMMOSS);
1055   m_mime_ctx->any_attachments_created = 1;
1056
1057   /* And now for the real name.  We avoid storing the name "smime.p7m"
1058      because that one is used at several places in the mapi conversion
1059      functions.  */
1060   if (m_mime_ctx->mimestruct_cur && m_mime_ctx->mimestruct_cur->filename)
1061     {
1062       if (!strcmp (m_mime_ctx->mimestruct_cur->filename, "smime.p7m"))
1063         {
1064           attach->set_display_name ("x-smime.p7m");
1065         }
1066       else
1067         {
1068           log_data ("%s:%s: Attachment filename: %s",
1069                            SRCNAME, __func__, m_mime_ctx->mimestruct_cur->filename);
1070           attach->set_display_name (m_mime_ctx->mimestruct_cur->filename);
1071         }
1072     }
1073   if (m_mime_ctx->mimestruct_cur && m_mime_ctx->mimestruct_cur->cid)
1074     {
1075       attach->set_content_id (m_mime_ctx->mimestruct_cur->cid);
1076       log_data ("%s:%s: content-id: %s",
1077                 SRCNAME, __func__, m_mime_ctx->mimestruct_cur->cid);
1078     }
1079   if (m_mime_ctx->mimestruct_cur && m_mime_ctx->mimestruct_cur->content_type)
1080     {
1081       attach->set_content_type (m_mime_ctx->mimestruct_cur->content_type);
1082       log_data ("%s:%s: content-type: %s",
1083                 SRCNAME, __func__, m_mime_ctx->mimestruct_cur->content_type);
1084     }
1085   m_attachments.push_back (attach);
1086
1087   TRETURN attach;
1088   /* TODO handle encoding */
1089 }
1090
1091 void MimeDataProvider::finalize ()
1092 {
1093   TSTART;
1094
1095   if (m_had_protected_headers)
1096     {
1097       const char *subject = rfc822parse_get_field (m_mime_ctx->msg,
1098                                                    "Subject", -1,
1099                                                    nullptr);
1100       if (subject)
1101         {
1102           log_debug ("%s:%s: Found subject %s", SRCNAME, __func__, subject);
1103           if (strlen (subject) <= strlen ("Subject: "))
1104             {
1105               STRANGEPOINT;
1106             }
1107           else
1108             {
1109               m_internal_subject = subject + strlen ("Subject: ");
1110             }
1111         }
1112     }
1113   if (m_rawbuf.size ())
1114     {
1115       m_rawbuf += "\r\n";
1116       size_t not_taken = collect_input_lines (m_rawbuf.c_str(),
1117                                               m_rawbuf.size());
1118       m_rawbuf.erase (0, m_rawbuf.size() - not_taken);
1119       if (m_rawbuf.size ())
1120         {
1121           log_error ("%s:%s: Collect left data in buffer.\n",
1122                      SRCNAME, __func__);
1123         }
1124     }
1125   TRETURN;
1126 }
1127
1128 const std::string &MimeDataProvider::get_body ()
1129 {
1130   TSTART;
1131   TRETURN m_body;
1132 }
1133
1134 const std::string &MimeDataProvider::get_html_body ()
1135 {
1136   TSTART;
1137   TRETURN m_html_body;
1138 }
1139
1140 const std::string &MimeDataProvider::get_html_charset() const
1141 {
1142   TSTART;
1143   TRETURN m_html_charset;
1144 }
1145
1146 const std::string &MimeDataProvider::get_body_charset() const
1147 {
1148   TSTART;
1149   TRETURN m_body_charset;
1150 }
1151
1152 const std::string &MimeDataProvider::get_internal_subject () const
1153 {
1154   TSTART;
1155   TRETURN m_internal_subject;
1156 }