91f291aa615fca30fcd1c28267a802774fc4f840
[gpgol.git] / src / mimeparser.c
1 /* mimeparser.c - Parse multipart MIME message
2  *      Copyright (C) 2005, 2007, 2008 g10 Code GmbH
3  *
4  * This file is part of GpgOL.
5  * 
6  * GpgOL is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  * 
11  * GpgOL is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  * 
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <string.h>
29
30 #define COBJMACROS
31 #include <windows.h>
32 #include <objidl.h> /* For IStream. */
33
34 #include <gpgme.h>
35
36 #include "mymapi.h"
37 #include "mymapitags.h"
38
39 #include "rfc822parse.h"
40 #include "common.h"
41 #include "engine.h"
42 #include "mapihelp.h"
43 #include "serpent.h"
44 #include "mimeparser.h"
45
46 /* Define the next to get extra debug message for the MIME parser.  */
47 #define DEBUG_PARSER 1
48
49 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
50                                      SRCNAME, __func__, __LINE__); \
51                         } while (0)
52
53 static const char oid_mimetag[] =
54     {0x2A, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x03, 0x0a, 0x04};
55
56
57
58 /* The maximum length of a line we are able to process.  RFC822 allows
59    only for 1000 bytes; thus 2000 seems to be a reasonable value. */
60 #define LINEBUFSIZE 2000
61
62
63
64 /* To keep track of the MIME message structures we use a linked list
65    with each item corresponding to one part. */
66 struct mimestruct_item_s;
67 typedef struct mimestruct_item_s *mimestruct_item_t;
68 struct mimestruct_item_s
69 {
70   mimestruct_item_t next;
71   unsigned int level;   /* Level in the hierarchy of that part.  0
72                            indicates the outer body.  */
73   char *filename;       /* Malloced fileanme or NULL.  */
74   char *charset;        /* Malloced charset or NULL.  */
75   char content_type[1]; /* String with the content type. */
76 };
77
78
79
80
81 /* The context object we use to track information. */
82 struct mime_context
83 {
84   HWND hwnd;          /* A window handle to be used for message boxes etc. */
85   rfc822parse_t msg;  /* The handle of the RFC822 parser. */
86
87   int preview;        /* Do only decryption and pop up no  message bozes.  */
88   
89   int protect_mode;   /* Encrypt all attachments etc. (cf. SYMENC). */
90   int verify_mode;    /* True if we want to verify a signature. */
91
92   int nesting_level;  /* Current MIME nesting level. */
93   int in_data;        /* We are currently in data (body or attachment). */
94   int body_seen;      /* True if we have seen a part we consider the
95                          body of the message.  */
96
97   gpgme_data_t signed_data;/* NULL or the data object used to collect
98                               the signed data. It would be better to
99                               just hash it but there is no support in
100                               gpgme for this yet. */
101   gpgme_data_t sig_data;  /* NULL or data object to collect the
102                              signature attachment which should be a
103                              signature then.  */
104   
105   int collect_attachment; /* True if we are collecting an attachment
106                              or the body. */
107   int collect_signeddata; /* True if we are collecting the signed data. */
108   int collect_signature;  /* True if we are collecting a signature.  */
109   int start_hashing;      /* Flag used to start collecting signed data. */
110   int hashing_level;      /* MIME level where we started hashing. */
111   int is_qp_encoded;      /* Current part is QP encoded. */
112   int is_base64_encoded;  /* Current part is base 64 encoded. */
113   int is_body;            /* The current part belongs to the body.  */
114   protocol_t protocol;    /* The detected crypto protocol.  */
115
116   int part_counter;       /* Counts the number of processed parts. */
117   int any_boundary;       /* Indicates whether we have seen any
118                              boundary which means that we are actually
119                              working on a MIME message and not just on
120                              plain rfc822 message.  */
121   
122   engine_filter_t outfilter; /* Fiter as used by ciphertext_handler.  */
123
124   /* A linked list describing the structure of the mime message.  This
125      list gets build up while parsing the message.  */
126   mimestruct_item_t mimestruct;
127   mimestruct_item_t *mimestruct_tail;
128   mimestruct_item_t mimestruct_cur;
129
130   LPMESSAGE mapi_message; /* The MAPI message object we are working on.  */
131   LPSTREAM outstream;     /* NULL or a stream to write a part to. */
132   LPATTACH mapi_attach;   /* The attachment object we are writing.  */
133   symenc_t symenc;        /* NULL or the context used to protect
134                              an attachment. */
135   struct {
136     LPSTREAM outstream;   /* Saved stream used to continue a body
137                              part. */
138     LPATTACH mapi_attach; /* Saved attachment used to continue a body part.  */
139     symenc_t symenc;      /* Saved encryption context used to continue
140                              a body part.  */
141   } body_saved;
142   int any_attachments_created;  /* True if we created a new atatchment.  */
143
144   b64_state_t base64;     /* The state of the Base-64 decoder.  */
145
146   int line_too_long;  /* Indicates that a received line was too long. */
147   int parser_error;   /* Indicates that we encountered a error from
148                          the parser. */
149
150   /* Buffer used to constructed complete files. */
151   size_t linebufsize;   /* The allocated size of the buffer. */
152   size_t linebufpos;    /* The actual write posituion. */  
153   char linebuf[1];      /* The buffer. */
154 };
155 typedef struct mime_context *mime_context_t;
156
157
158 /* This function is a wrapper around gpgme_data_write to convert the
159    data to utf-8 first.  We assume Latin-1 here. */
160 /* static int */
161 /* latin1_data_write (gpgme_data_t data, const char *line, size_t len) */
162 /* { */
163 /*   const char *s; */
164 /*   char *buffer, *p; */
165 /*   size_t i, n; */
166 /*   int rc; */
167
168 /*   for (s=line, i=0, n=0 ; i < len; s++, i++ )  */
169 /*     { */
170 /*       n++; */
171 /*       if (*s & 0x80) */
172 /*         n++; */
173 /*     } */
174 /*   buffer = xmalloc (n + 1); */
175 /*   for (s=line, i=0, p=buffer; i < len; s++, i++ ) */
176 /*     { */
177 /*       if (*s & 0x80) */
178 /*         { */
179 /*           *p++ = 0xc0 | ((*s >> 6) & 3); */
180 /*           *p++ = 0x80 | (*s & 0x3f); */
181 /*         } */
182 /*       else */
183 /*         *p++ = *s; */
184 /*     } */
185 /*   assert (p-buffer == n); */
186 /*   rc = gpgme_data_write (data, buffer, n); */
187 /*   xfree (buffer); */
188 /*   return rc; */
189 /* } */
190
191
192 /* Print the message event EVENT. */
193 static void
194 debug_message_event (mime_context_t ctx, rfc822parse_event_t event)
195 {
196   const char *s;
197
198   switch (event)
199     {
200     case RFC822PARSE_OPEN: s= "Open"; break;
201     case RFC822PARSE_CLOSE: s= "Close"; break;
202     case RFC822PARSE_CANCEL: s= "Cancel"; break;
203     case RFC822PARSE_T2BODY: s= "T2Body"; break;
204     case RFC822PARSE_FINISH: s= "Finish"; break;
205     case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break;
206     case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break;
207     case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break;
208     case RFC822PARSE_BOUNDARY: s= "Boundary"; break;
209     case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break;
210     case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break;
211     case RFC822PARSE_PREAMBLE: s= "Preamble"; break;
212     case RFC822PARSE_EPILOGUE: s= "Epilogue"; break;
213     default: s= "[unknown event]"; break;
214     }
215 #ifdef DEBUG_PARSER
216   log_debug ("%s: ctx=%p, rfc822 event %s\n", SRCNAME, ctx, s);
217 #endif
218 }
219
220
221 /* Start a new atatchment.  With IS_BODY set, the attachment is
222    actually the body part of the message which is treated in a special
223    way. */
224 static int
225 start_attachment (mime_context_t ctx, int is_body)
226 {
227   int retval = -1;
228   HRESULT hr;
229   ULONG newpos;
230   SPropValue prop;
231   LPATTACH newatt = NULL;
232   LPSTREAM to = NULL;
233   LPUNKNOWN punk;
234
235 #ifdef DEBUG_PARSER
236   log_debug ("%s:%s: for ctx=%p is_body=%d", SRCNAME, __func__, ctx, is_body);
237 #endif
238
239   /* Just in case something has not been finished, do it here. */
240   if (ctx->outstream)
241     {
242       IStream_Release (ctx->outstream);
243       ctx->outstream = NULL;
244     }
245   if (ctx->mapi_attach)
246     {
247       IAttach_Release (ctx->mapi_attach);
248       ctx->mapi_attach = NULL;
249     }
250   if (ctx->symenc)
251     {
252       symenc_close (ctx->symenc);
253       ctx->symenc = NULL;
254     }
255   
256   /* Before we start with the first attachment we need to delete all
257      attachments which might have been created already by a past
258      parser run.  */
259   if (!ctx->any_attachments_created)
260     {
261       mapi_attach_item_t *table;
262       int i;
263       
264       table = mapi_create_attach_table (ctx->mapi_message, 1);
265       if (table)
266         {
267           for (i=0; !table[i].end_of_table; i++)
268             if (table[i].attach_type == ATTACHTYPE_FROMMOSS)
269               {
270                 hr = IMessage_DeleteAttach (ctx->mapi_message, 
271                                             table[i].mapipos,
272                                             0, NULL, 0);
273                 if (hr)
274                   log_error ("%s:%s: DeleteAttach failed: hr=%#lx\n",
275                              SRCNAME, __func__, hr); 
276               }
277           mapi_release_attach_table (table);
278         }
279       ctx->any_attachments_created = 1;
280     }
281   
282   /* Now create a new attachment.  */
283   hr = IMessage_CreateAttach (ctx->mapi_message, NULL, 0, &newpos, &newatt);
284   if (hr)
285     {
286       log_error ("%s:%s: can't create attachment: hr=%#lx\n",
287                  SRCNAME, __func__, hr); 
288       goto leave;
289     }
290
291   prop.ulPropTag = PR_ATTACH_METHOD;
292   prop.Value.ul = ATTACH_BY_VALUE;
293   hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
294   if (hr != S_OK)
295     {
296       log_error ("%s:%s: can't set attach method: hr=%#lx\n",
297                  SRCNAME, __func__, hr); 
298       goto leave;
299     }
300
301   /* Mark that attachment so that we know why it has been created.  */
302   if (get_gpgolattachtype_tag (ctx->mapi_message, &prop.ulPropTag) )
303     goto leave;
304   prop.Value.l = ATTACHTYPE_FROMMOSS;
305   hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);        
306   if (hr)
307     {
308       log_error ("%s:%s: can't set %s property: hr=%#lx\n",
309                  SRCNAME, __func__, "GpgOL Attach Type", hr); 
310       goto leave;
311     }
312
313   /* The body attachment is special and should not be shown in the list
314      of attachments.  */
315   if (is_body)
316     {
317       prop.ulPropTag = PR_ATTACHMENT_HIDDEN;
318       prop.Value.b = TRUE;
319       hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
320       if (hr)
321         {
322           log_error ("%s:%s: can't set hidden attach flag: hr=%#lx\n",
323                      SRCNAME, __func__, hr); 
324           goto leave;
325         }
326     }
327   ctx->is_body = is_body;
328
329   /* We need to insert a short filename .  Without it, the _displayed_
330      list of attachments won't get updated although the attachment has
331      been created. */
332   prop.ulPropTag = PR_ATTACH_FILENAME_A;
333   {
334     char buf[100];
335
336     if (is_body)
337       prop.Value.lpszA = is_body == 2? "gpgol000.htm":"gpgol000.txt";
338     else
339       {
340         snprintf (buf, 100, "gpgol%03d.dat", ctx->part_counter);
341         prop.Value.lpszA = buf;
342       }
343     hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
344   }
345   if (hr)
346     {
347       log_error ("%s:%s: can't set attach filename: hr=%#lx\n",
348                  SRCNAME, __func__, hr); 
349       goto leave;
350     }
351
352   /* And now for the real name.  */
353   if (ctx->mimestruct_cur && ctx->mimestruct_cur->filename)
354     {
355       prop.ulPropTag = PR_ATTACH_LONG_FILENAME_A;
356       prop.Value.lpszA = ctx->mimestruct_cur->filename;
357       hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
358       if (hr)
359         {
360           log_error ("%s:%s: can't set attach long filename: hr=%#lx\n",
361                      SRCNAME, __func__, hr); 
362           goto leave;
363         }
364     }
365
366   prop.ulPropTag = PR_ATTACH_TAG;
367   prop.Value.bin.cb  = sizeof oid_mimetag;
368   prop.Value.bin.lpb = (LPBYTE)oid_mimetag;
369   hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
370   if (hr)
371     {
372       log_error ("%s:%s: can't set attach tag: hr=%#lx\n",
373                  SRCNAME, __func__, hr); 
374       goto leave;
375     }
376
377   assert (ctx->mimestruct_cur && ctx->mimestruct_cur->content_type);
378   prop.ulPropTag = PR_ATTACH_MIME_TAG_A;
379   prop.Value.lpszA = ctx->mimestruct_cur->content_type;
380   hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);
381   if (hr)
382     {
383       log_error ("%s:%s: can't set attach mime tag: hr=%#lx\n",
384                  SRCNAME, __func__, hr); 
385       goto leave;
386     }
387
388   /* If we have the MIME info and a charset info and that is not
389      UTF-8, set our own Charset property.  */
390   if (ctx->mimestruct_cur)
391     {
392       const char *s = ctx->mimestruct_cur->charset;
393       if (s && strcmp (s, "utf-8") && strcmp (s, "UTF-8")
394           && strcmp (s, "utf8") && strcmp (s, "UTF8"))
395         mapi_set_gpgol_charset ((LPMESSAGE)newatt, s);
396     }
397
398
399   /* If we are in protect mode (i.e. working on a decrypted message,
400      we need to setup the symkey context to protect (encrypt) the
401      attachment in the MAPI.  */
402   if (ctx->protect_mode)
403     {
404       char *iv;
405
406       if (get_gpgolprotectiv_tag (ctx->mapi_message, &prop.ulPropTag) )
407         goto leave;
408
409       iv = create_initialization_vector (16);
410       if (!iv)
411         {
412           log_error ("%s:%s: error creating initialization vector",
413                      SRCNAME, __func__);
414           goto leave;
415         }
416       prop.Value.bin.cb = 16;
417       prop.Value.bin.lpb = iv;
418       hr = HrSetOneProp ((LPMAPIPROP)newatt, &prop);    
419       if (hr)
420         {
421           log_error ("%s:%s: can't set %s property: hr=%#lx\n",
422                      SRCNAME, __func__, "GpgOL Protect IV", hr); 
423           goto leave;
424         }
425
426       ctx->symenc = symenc_open (get_128bit_session_key (), 16, iv, 16);
427       xfree (iv);
428       if (!ctx->symenc)
429         {
430           log_error ("%s:%s: error creating cipher context",
431                      SRCNAME, __func__);
432           goto leave;
433         }
434     }
435
436  
437   punk = (LPUNKNOWN)to;
438   hr = IAttach_OpenProperty (newatt, PR_ATTACH_DATA_BIN, &IID_IStream, 0,
439                              MAPI_CREATE|MAPI_MODIFY, &punk);
440   if (FAILED (hr)) 
441     {
442       log_error ("%s:%s: can't create output stream: hr=%#lx\n",
443                  SRCNAME, __func__, hr); 
444       goto leave;
445     }
446   to = (LPSTREAM)punk;
447   
448   ctx->outstream = to;
449   to = NULL;
450   ctx->mapi_attach = newatt;
451   newatt = NULL;
452
453   if (ctx->symenc)
454     {
455       char tmpbuf[16];
456       /* Write an encrypted fixed 16 byte string which we need to
457          check at decryption time to see whether we have actually
458          encrypted it using this session key.  */
459       symenc_cfb_encrypt (ctx->symenc, tmpbuf, "GpgOL attachment", 16);
460       IStream_Write (ctx->outstream, tmpbuf, 16, NULL);
461     }
462   retval = 0; /* Success.  */
463
464  leave:
465   if (to)
466     {
467       IStream_Revert (to);
468       IStream_Release (to);
469     }
470   if (newatt)
471     IAttach_Release (newatt);
472   return retval;
473 }
474
475
476 static int
477 finish_attachment (mime_context_t ctx, int cancel)
478 {
479   HRESULT hr;
480   int retval = -1;
481
482 #ifdef DEBUG_PARSER
483   log_debug ("%s:%s: for ctx=%p cancel=%d", SRCNAME, __func__, ctx, cancel);
484 #endif
485
486   if (ctx->outstream && ctx->is_body && !ctx->body_saved.outstream)
487     {
488       ctx->body_saved.outstream = ctx->outstream;
489       ctx->outstream = NULL;
490       retval = 0;
491     }
492   else if (ctx->outstream)
493     {
494       IStream_Commit (ctx->outstream, 0);
495       IStream_Release (ctx->outstream);
496       ctx->outstream = NULL;
497
498       if (cancel)
499         retval = 0;
500       else if (ctx->mapi_attach)
501         {
502           hr = IAttach_SaveChanges (ctx->mapi_attach, 0);
503           if (hr)
504             {
505               log_error ("%s:%s: SaveChanges(attachment) failed: hr=%#lx\n",
506                          SRCNAME, __func__, hr); 
507             }
508           else
509             retval = 0; /* Success.  */
510         }
511     }
512
513   if (ctx->mapi_attach && ctx->is_body && !ctx->body_saved.mapi_attach)
514     {
515       ctx->body_saved.mapi_attach = ctx->mapi_attach;
516       ctx->mapi_attach = NULL;
517     }
518   else if (ctx->mapi_attach)
519     {
520       IAttach_Release (ctx->mapi_attach);
521       ctx->mapi_attach = NULL;
522     }
523
524   if (ctx->symenc && ctx->is_body && !ctx->body_saved.symenc)
525     {
526       ctx->body_saved.symenc = ctx->symenc;
527       ctx->symenc = NULL;
528     }
529   else if (ctx->symenc)
530     {
531       symenc_close (ctx->symenc);
532       ctx->symenc = NULL;
533     }
534
535   ctx->is_body = 0;
536   
537   return retval;
538 }
539
540
541 /* Finish the saved body part.  This is required because we delay the
542    finishing of body parts.  */
543 static int 
544 finish_saved_body (mime_context_t ctx, int cancel)
545 {
546   HRESULT hr;
547   int retval = -1;
548
549   if (ctx->body_saved.outstream)
550     {
551       IStream_Commit (ctx->body_saved.outstream, 0);
552       IStream_Release (ctx->body_saved.outstream);
553       ctx->body_saved.outstream = NULL;
554
555       if (cancel)
556         retval = 0;
557       else if (ctx->body_saved.mapi_attach)
558         {
559           hr = IAttach_SaveChanges (ctx->body_saved.mapi_attach, 0);
560           if (hr)
561             {
562               log_error ("%s:%s: SaveChanges(attachment) failed: hr=%#lx\n",
563                          SRCNAME, __func__, hr); 
564             }
565           else
566             retval = 0; /* Success.  */
567         }
568     }
569
570   if (ctx->body_saved.mapi_attach)
571     {
572       IAttach_Release (ctx->body_saved.mapi_attach);
573       ctx->body_saved.mapi_attach = NULL;
574     }
575
576   if (ctx->symenc)
577     {
578       symenc_close (ctx->body_saved.symenc);
579       ctx->body_saved.symenc = NULL;
580     }
581
582   return retval;
583 }
584
585
586
587 /* Create the MIME info string.  This is a LF delimited string
588    with one line per MIME part.  Each line is formatted this way:
589    LEVEL:ENCINFO:SIGINFO:CT:CHARSET:FILENAME
590    
591    LEVEL is the nesting level with 0 as the top (rfc822 header)
592    ENCINFO is one of
593       p   PGP/MIME encrypted
594       s   S/MIME encryptyed
595    SIGINFO is one of
596       pX  PGP/MIME signed (also used for clearsigned)
597       sX  S/MIME signed
598       With X being:
599         ?  unklnown status
600         -  Bad signature
601         ~  Good signature but with some problems
602         !  Good signature
603    CT ist the content type of this part
604    CHARSET is the charset used for this part
605    FILENAME is the file name.
606 */
607 static char *
608 build_mimeinfo (mimestruct_item_t mimestruct)
609 {
610   mimestruct_item_t ms;
611   size_t buflen, n;
612   char *buffer, *p;
613   char numbuf[20];
614
615   /* FIXME: We need to escape stuff so that there are no colons.  */
616   for (buflen=0, ms = mimestruct; ms; ms = ms->next)
617     {
618       buflen += sizeof numbuf;
619       buflen += strlen (ms->content_type);
620       buflen += ms->charset? strlen (ms->charset) : 0;
621       buflen += ms->filename? strlen (ms->filename) : 0;
622       buflen += 20;
623     }
624
625   p = buffer = xmalloc (buflen+1);
626   for (ms=mimestruct; ms; ms = ms->next)
627     {
628       snprintf (p, buflen, "%d:::%s:%s:%s:\n",
629                 ms->level, ms->content_type,
630                 ms->charset? ms->charset : "",
631                 ms->filename? ms->filename : "");
632       n = strlen (p);
633       assert (n < buflen);
634       buflen -= n;
635       p += n;
636     }
637
638   return buffer;
639 }
640
641
642 static int
643 finish_message (LPMESSAGE message, gpg_error_t err, int protect_mode, 
644                 mimestruct_item_t mimestruct)
645 {
646   HRESULT hr;
647   SPropValue prop;
648
649   /* If this was an encrypted message we save the session marker in a
650      speciat property so that we now that we already decrypted that
651      message within this session.  This is pretty useful when
652      scrolling through messages and preview decryption has been
653      enabled.  */
654   if (protect_mode)
655     {
656       char sesmrk[8];
657
658       if (get_gpgollastdecrypted_tag (message, &prop.ulPropTag) )
659         return -1;
660       if (err)
661         memset (sesmrk, 0, 8);
662       else
663         memcpy (sesmrk, get_64bit_session_marker (), 8);
664       prop.Value.bin.cb = 8;
665       prop.Value.bin.lpb = sesmrk;
666       hr = IMessage_SetProps (message, 1, &prop, NULL);
667       if (hr)
668         {
669           log_error ("%s:%s: can't set %s property: hr=%#lx\n",
670                      SRCNAME, __func__, "GpgOL Last Decrypted", hr); 
671           return -1;
672         }
673     }
674
675   /* Store the MIME structure away.  */
676   if (get_gpgolmimeinfo_tag (message, &prop.ulPropTag) )
677     return -1;
678   prop.Value.lpszA = build_mimeinfo (mimestruct);
679   hr = IMessage_SetProps (message, 1, &prop, NULL);
680   xfree (prop.Value.lpszA);
681   if (hr)
682     {
683       log_error_w32 (hr, "%s:%s: error setting the mime info",
684                      SRCNAME, __func__);
685       return -1;
686     }
687
688   hr = IMessage_SaveChanges (message, KEEP_OPEN_READWRITE|FORCE_SAVE);
689   if (hr)
690     {
691       log_error_w32 (hr, "%s:%s: SaveChanges to the message failed",
692                      SRCNAME, __func__); 
693       return -1;
694     }
695
696   return 0;
697 }
698
699
700
701 /* Process the transition to body event. 
702
703    This means we have received the empty line indicating the body and
704    should now check the headers to see what to do about this part.  */
705 static int
706 t2body (mime_context_t ctx, rfc822parse_t msg)
707 {
708   rfc822parse_field_t field;
709   const char *ctmain, *ctsub;
710   const char *s;
711   size_t off;
712   char *p;
713   int is_text = 0;
714   char *filename = NULL; 
715   char *charset = NULL;
716         
717
718   /* Figure out the encoding.  */
719   ctx->is_qp_encoded = 0;
720   ctx->is_base64_encoded = 0;
721   p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off);
722   if (p)
723     {
724       if (!stricmp (p+off, "quoted-printable"))
725         ctx->is_qp_encoded = 1;
726       else if (!stricmp (p+off, "base64"))
727         {
728           ctx->is_base64_encoded = 1;
729           b64_init (&ctx->base64);
730         }
731       free (p);
732     }
733
734   /* Get the filename from the header.  */
735   field = rfc822parse_parse_field (msg, "Content-Disposition", -1);
736   if (field)
737     {
738       s = rfc822parse_query_parameter (field, "filename", 0);
739       if (s)
740         filename = xstrdup (s);
741       rfc822parse_release_field (field);
742     }
743
744   /* Process the Content-type and all its parameters.  */
745   ctmain = ctsub = NULL;
746   field = rfc822parse_parse_field (msg, "Content-Type", -1);
747   if (field)
748     ctmain = rfc822parse_query_media_type (field, &ctsub);
749   if (!ctmain)
750     {
751       /* Either there is no content type field or it is faulty; in
752          both cases we fall back to text/plain.  */
753       ctmain = "text";
754       ctsub  = "plain";
755     }
756
757 #ifdef DEBUG_PARSER  
758   log_debug ("%s:%s: ctx=%p, ct=`%s/%s'\n",
759              SRCNAME, __func__, ctx, ctmain, ctsub);
760 #endif
761
762   s = rfc822parse_query_parameter (field, "charset", 0);
763   if (s)
764     charset = xstrdup (s);
765
766   /* Update our idea of the entire MIME structure.  */
767   {
768     mimestruct_item_t ms;
769
770     ms = xmalloc (sizeof *ms + strlen (ctmain) + 1 + strlen (ctsub));
771     ctx->mimestruct_cur = ms;
772     *ctx->mimestruct_tail = ms;
773     ctx->mimestruct_tail = &ms->next;
774     ms->next = NULL;
775     strcpy (stpcpy (stpcpy (ms->content_type, ctmain), "/"), ctsub);
776     ms->level = ctx->nesting_level;
777     ms->filename = filename;
778     filename = NULL;
779     ms->charset = charset;
780     charset = NULL;
781
782   }
783
784       
785   if (!strcmp (ctmain, "multipart"))
786     {
787       /* We don't care about the top level multipart layer but wait
788          until it comes to the actual parts which then will get stored
789          as attachments.
790
791          For now encapsulated signed or encrypted containers are not
792          processed in a special way as they should.  Except for the
793          simple verify mode. */
794       if (ctx->verify_mode && !ctx->signed_data
795           && !strcmp (ctsub, "signed")
796           && (s = rfc822parse_query_parameter (field, "protocol", 0)))
797         {
798           if (!strcmp (s, "application/pgp-signature"))
799             ctx->protocol = PROTOCOL_OPENPGP;
800           else if (!strcmp (s, "application/pkcs7-signature")
801                    || !strcmp (s, "application/x-pkcs7-signature"))
802             ctx->protocol = PROTOCOL_SMIME;
803           else
804             ctx->protocol = PROTOCOL_UNKNOWN;
805
806           /* Need to start the hashing after the next boundary. */
807           ctx->start_hashing = 1;
808         }
809     }
810   else if (!strcmp (ctmain, "text"))
811     {
812       is_text = !strcmp (ctsub, "html")? 2:1;
813     }
814   else if (ctx->verify_mode && ctx->nesting_level == 1 && !ctx->sig_data
815            && !strcmp (ctmain, "application")
816            && ((ctx->protocol == PROTOCOL_OPENPGP   
817                 && !strcmp (ctsub, "pgp-signature"))
818                || (ctx->protocol == PROTOCOL_SMIME   
819                    && (!strcmp (ctsub, "pkcs7-signature")
820                        || !strcmp (ctsub, "x-pkcs7-signature")))))
821     {
822       /* This is the second part of a MOSS signature.  We only support
823          here full messages thus checking the nesting level is
824          sufficient.  We do this only for the first signature (i.e. if
825          sig_data has not been set yet).  We also do this only while
826          in verify mode because we don't want to write a full MUA.  */
827       if (!ctx->preview && !gpgme_data_new (&ctx->sig_data))
828         ctx->collect_signature = 1;
829     }
830   else /* Other type. */
831     {
832       if (!ctx->preview)
833         ctx->collect_attachment = 1;
834     }
835   rfc822parse_release_field (field); /* (Content-type) */
836   ctx->in_data = 1;
837
838 #ifdef DEBUG_PARSER
839   log_debug ("%s: this body: nesting=%d partno=%d is_text=%d charset=\"%s\"\n",
840              SRCNAME, ctx->nesting_level, ctx->part_counter, is_text, 
841              ctx->mimestruct_cur->charset?ctx->mimestruct_cur->charset:"");
842 #endif
843
844   /* If this is a text part, decide whether we treat it as our body. */
845   if (is_text)
846     {
847       ctx->collect_attachment = 1;
848
849       /* If this is the first text part at all we will start to
850          collect it and use it later as the regular body.  */
851       if (!ctx->body_seen)
852         {
853           ctx->body_seen = 1;
854           if (start_attachment (ctx, 1))
855             return -1;
856           assert (ctx->outstream);
857         }
858       else if (!ctx->body_saved.outstream || !ctx->body_saved.mapi_attach)
859         {
860           /* Oops: We expected to continue a body but the state is not
861              correct.  Create a plain attachment instead.  */
862           log_debug ("%s:%s: ctx=%p, no saved outstream or mapi_attach (%p,%p)",
863                      SRCNAME, __func__, ctx, 
864                      ctx->body_saved.outstream, ctx->body_saved.mapi_attach);
865           if (start_attachment (ctx, 0))
866             return -1;
867           assert (ctx->outstream);
868         }
869       else if (ctx->outstream || ctx->mapi_attach || ctx->symenc)
870         {
871           /* We expected to continue a body but the last attachment
872              has not been properly closed.  Create a plain attachment
873              instead.  */
874           log_debug ("%s:%s: ctx=%p, outstream, mapi_attach or symenc not "
875                      "closed (%p,%p,%p)",
876                      SRCNAME, __func__, ctx, 
877                      ctx->outstream, ctx->mapi_attach, ctx->symenc);
878           if (start_attachment (ctx, 0))
879             return -1;
880           assert (ctx->outstream);
881         }
882       else 
883         {
884           /* We already got one body and thus we can continue that
885              last attachment.  */
886 #ifdef DEBUG_PARSER
887           log_debug ("%s:%s: continuing body part\n", SRCNAME, __func__);
888 #endif
889           ctx->is_body = 1;
890           ctx->outstream = ctx->body_saved.outstream;
891           ctx->mapi_attach = ctx->body_saved.mapi_attach;
892           ctx->symenc = ctx->body_saved.symenc;
893           ctx->body_saved.outstream = NULL;
894           ctx->body_saved.mapi_attach = NULL;
895           ctx->body_saved.symenc = NULL;
896         }
897     }
898   else if (ctx->collect_attachment)
899     {
900       /* Now that if we have an attachment prepare a new MAPI
901          attachment.  */
902       if (start_attachment (ctx, 0))
903         return -1;
904       assert (ctx->outstream);
905     }
906
907   return 0;
908 }
909
910
911 /* This routine gets called by the RFC822 parser for all kind of
912    events.  OPAQUE carries in our case an smime context.  Should
913    return 0 on success or -1 as well as setting errno on
914    failure.  */
915 static int
916 message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
917 {
918   int retval = 0;
919   mime_context_t ctx = opaque;
920
921   debug_message_event (ctx, event);
922
923   if (event == RFC822PARSE_BEGIN_HEADER || event == RFC822PARSE_T2BODY)
924     {
925       /* We need to check here whether to start collecting signed data
926          because attachments might come without header lines and thus
927          we won't see the BEGIN_HEADER event. */
928       if (ctx->start_hashing == 1)
929         {
930           ctx->start_hashing = 2;
931           ctx->hashing_level = ctx->nesting_level;
932           ctx->collect_signeddata = 1;
933           gpgme_data_new (&ctx->signed_data);
934         }
935     }
936
937
938   switch (event)
939     {
940     case RFC822PARSE_T2BODY:
941       retval = t2body (ctx, msg);
942       break;
943
944     case RFC822PARSE_LEVEL_DOWN:
945       ctx->nesting_level++;
946       break;
947
948     case RFC822PARSE_LEVEL_UP:
949       if (ctx->nesting_level)
950         ctx->nesting_level--;
951       else 
952         {
953           log_error ("%s: ctx=%p, invalid structure: bad nesting level\n",
954                      SRCNAME, ctx);
955           ctx->parser_error = 1;
956         }
957       break;
958     
959     case RFC822PARSE_BOUNDARY:
960     case RFC822PARSE_LAST_BOUNDARY:
961       ctx->any_boundary = 1;
962       ctx->in_data = 0;
963       ctx->collect_attachment = 0;
964       
965       finish_attachment (ctx, 0);
966       assert (!ctx->outstream);
967
968       if (ctx->start_hashing == 2 && ctx->hashing_level == ctx->nesting_level)
969         {
970           ctx->start_hashing = 3; /* Avoid triggering it again. */
971           ctx->collect_signeddata = 0;
972         }
973       break;
974     
975     case RFC822PARSE_BEGIN_HEADER:
976       ctx->part_counter++;
977       break;
978
979     default:  /* Ignore all other events. */
980       break;
981     }
982
983   return retval;
984 }
985
986
987
988 /* This handler is called by GPGME with the decrypted plaintext. */
989 static int
990 plaintext_handler (void *handle, const void *buffer, size_t size)
991 {
992   mime_context_t ctx = handle;
993   const char *s;
994   size_t nleft, pos, len;
995
996   s = buffer;
997   pos = ctx->linebufpos;
998   nleft = size;
999   for (; nleft ; nleft--, s++)
1000     {
1001       if (pos >= ctx->linebufsize)
1002         {
1003           log_error ("%s: ctx=%p, rfc822 parser failed: line too long\n",
1004                      SRCNAME, ctx);
1005           ctx->line_too_long = 1;
1006           return -1; /* Error. */
1007         }
1008       if (*s != '\n')
1009         ctx->linebuf[pos++] = *s;
1010       else
1011         { /* Got a complete line. Remove the last CR */
1012           if (pos && ctx->linebuf[pos-1] == '\r')
1013             pos--;
1014
1015           if (rfc822parse_insert (ctx->msg, ctx->linebuf, pos))
1016             {
1017               log_error ("%s: ctx=%p, rfc822 parser failed: %s\n",
1018                          SRCNAME, ctx, strerror (errno));
1019               ctx->parser_error = 1;
1020               return -1; /* Error. */
1021             }
1022
1023
1024           if (ctx->collect_signeddata && ctx->signed_data)
1025             {
1026               /* Save the signed data.  Note that we need to delay
1027                  the CR/LF because the last line ending belongs to the
1028                  next boundary. */
1029               if (ctx->collect_signeddata == 2)
1030                 gpgme_data_write (ctx->signed_data, "\r\n", 2);
1031               gpgme_data_write (ctx->signed_data, ctx->linebuf, pos);
1032               ctx->collect_signeddata = 2;
1033             }
1034
1035           if (ctx->in_data && ctx->collect_attachment)
1036             {
1037               /* We are inside of an attachment part.  Write it out. */
1038               if (ctx->collect_attachment == 1)  /* Skip the first line. */
1039                 ctx->collect_attachment = 2;
1040               else if (ctx->outstream)
1041                 {
1042                   HRESULT hr = 0;
1043
1044                   if (ctx->is_qp_encoded)
1045                     len = qp_decode (ctx->linebuf, pos);
1046                   else if (ctx->is_base64_encoded)
1047                     len = b64_decode (&ctx->base64, ctx->linebuf, pos);
1048                   else
1049                     len = pos;
1050                   if (len)
1051                     {
1052                       if (ctx->symenc)
1053                         symenc_cfb_encrypt (ctx->symenc, ctx->linebuf,
1054                                             ctx->linebuf, len);
1055                       hr = IStream_Write (ctx->outstream, ctx->linebuf,
1056                                           len, NULL);
1057                     }
1058                   if (!hr && !ctx->is_base64_encoded)
1059                     {
1060                       char tmp[3] = "\r\n";
1061
1062                       if (ctx->symenc)
1063                         symenc_cfb_encrypt (ctx->symenc, tmp, tmp, 2);
1064                       hr = IStream_Write (ctx->outstream, tmp, 2, NULL);
1065                     }
1066                   if (hr)
1067                     {
1068                       log_debug ("%s:%s: Write failed: hr=%#lx",
1069                                  SRCNAME, __func__, hr);
1070                       if (!ctx->preview)
1071                         MessageBox (ctx->hwnd, _("Error writing to stream"),
1072                                     _("I/O-Error"), MB_ICONERROR|MB_OK);
1073                       ctx->parser_error = 1;
1074                       return -1; /* Error. */
1075                     }
1076                 }
1077             }
1078           else if (ctx->in_data && ctx->collect_signature)
1079             {
1080               /* We are inside of a signature attachment part.  */
1081               if (ctx->collect_signature == 1)  /* Skip the first line. */
1082                 ctx->collect_signature = 2;
1083               else if (ctx->sig_data)
1084                 {
1085                   if (ctx->is_qp_encoded)
1086                     len = qp_decode (ctx->linebuf, pos);
1087                   else if (ctx->is_base64_encoded)
1088                     len = b64_decode (&ctx->base64, ctx->linebuf, pos);
1089                   else
1090                     len = pos;
1091                   if (len)
1092                     gpgme_data_write (ctx->sig_data, ctx->linebuf, len);
1093                   if (!ctx->is_base64_encoded)
1094                     gpgme_data_write (ctx->sig_data, "\r\n", 2);
1095                 }
1096             }
1097           
1098           /* Continue with next line. */
1099           pos = 0;
1100         }
1101     }
1102   ctx->linebufpos = pos;
1103
1104   return size;
1105 }
1106
1107
1108
1109 int
1110 mime_verify (protocol_t protocol, const char *message, size_t messagelen, 
1111              LPMESSAGE mapi_message, HWND hwnd, int preview_mode)
1112 {
1113   gpg_error_t err = 0;
1114   mime_context_t ctx;
1115   const char *s;
1116   size_t len;
1117   char *signature = NULL;
1118   size_t sig_len;
1119   engine_filter_t filter = NULL;
1120
1121   /* Note: PROTOCOL is not used here but figured out directly while
1122      collecting the message.  Eventually it might help use setup a
1123      proper verification context right at startup to avoid collecting
1124      all the stuff.  However there are a couple of problems with that
1125      - for example we don't know whether gpgsm behaves correctly by
1126      first reading all the data and only the reading the signature.  I
1127      guess it is the case but that needs to be checked first.  It is
1128      just a performance issue.  */
1129  
1130   ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
1131   ctx->linebufsize = LINEBUFSIZE;
1132   ctx->hwnd = hwnd;
1133   ctx->preview = preview_mode;
1134   ctx->verify_mode = 1;
1135   ctx->mapi_message = mapi_message;
1136   ctx->mimestruct_tail = &ctx->mimestruct;
1137
1138   ctx->msg = rfc822parse_open (message_cb, ctx);
1139   if (!ctx->msg)
1140     {
1141       err = gpg_error_from_syserror ();
1142       log_error ("%s:%s: failed to open the RFC822 parser: %s", 
1143                  SRCNAME, __func__, gpg_strerror (err));
1144       goto leave;
1145     }
1146
1147   /* Need to pass the data line by line to the handler. */
1148   while ( (s = memchr (message, '\n', messagelen)) )
1149     {
1150       len = s - message + 1;
1151 /*       log_debug ("passing '%.*s'\n", (int)len, message); */
1152       plaintext_handler (ctx, message, len);
1153       if (ctx->parser_error || ctx->line_too_long)
1154         {
1155           err = gpg_error (GPG_ERR_GENERAL);
1156           break;
1157         }
1158       message += len;
1159       assert (messagelen >= len);
1160       messagelen -= len;
1161     }
1162   /* Note: the last character should be a LF, if not we ignore such an
1163      incomplete last line.  */
1164   if (ctx->sig_data && gpgme_data_write (ctx->sig_data, "", 1) == 1)
1165     {
1166       signature = gpgme_data_release_and_get_mem (ctx->sig_data, &sig_len);
1167       ctx->sig_data = NULL; 
1168     }
1169
1170   /* Now actually verify the signature. */
1171   if (!err && ctx->signed_data && signature)
1172     {
1173       gpgme_data_seek (ctx->signed_data, 0, SEEK_SET);
1174       
1175       if ((err=engine_create_filter (&filter, NULL, NULL)))
1176         goto leave;
1177       if ((err=engine_verify_start (filter, hwnd, signature, sig_len,
1178                                     ctx->protocol)))
1179         goto leave;
1180
1181       /* Filter the data.  */
1182       do
1183         {
1184           int nread;
1185           char buffer[4096];
1186           
1187           nread = gpgme_data_read (ctx->signed_data, buffer, sizeof buffer);
1188           if (nread < 0)
1189             {
1190               err = gpg_error_from_syserror ();
1191               log_error ("%s:%s: gpgme_data_read failed: %s", 
1192                          SRCNAME, __func__, gpg_strerror (err));
1193             }
1194           else if (nread)
1195             {
1196               err = engine_filter (filter, buffer, nread);
1197             }
1198           else
1199             break; /* EOF */
1200         }
1201       while (!err);
1202       if (err)
1203         goto leave;
1204       
1205       /* Wait for the engine to finish.  */
1206       if ((err = engine_filter (filter, NULL, 0)))
1207         goto leave;
1208       if ((err = engine_wait (filter)))
1209         goto leave;
1210       filter = NULL;
1211     }
1212
1213
1214  leave:
1215   gpgme_free (signature);
1216   engine_cancel (filter);
1217   if (ctx)
1218     {
1219       /* Cancel any left open attachment.  */
1220       finish_attachment (ctx, 1); 
1221       /* Save the body atatchment. */
1222       finish_saved_body (ctx, 0);
1223       rfc822parse_close (ctx->msg);
1224       gpgme_data_release (ctx->signed_data);
1225       gpgme_data_release (ctx->sig_data);
1226       finish_message (mapi_message, err, ctx->protect_mode, ctx->mimestruct);
1227       while (ctx->mimestruct)
1228         {
1229           mimestruct_item_t tmp = ctx->mimestruct->next;
1230           xfree (ctx->mimestruct->filename);
1231           xfree (ctx->mimestruct->charset);
1232           xfree (ctx->mimestruct);
1233           ctx->mimestruct = tmp;
1234         }
1235       symenc_close (ctx->symenc);
1236       symenc_close (ctx->body_saved.symenc);
1237       xfree (ctx);
1238     }
1239   return err;
1240 }
1241
1242
1243 /* A special version of mime_verify which works only for S/MIME opaque
1244    signed messages.  The message is expected to be a binary data
1245    stream with a CMS signature.  This function passes the entire
1246    message to the crypto engine and then parses the (cleartext) output
1247    for rendering the data.  */
1248 int
1249 mime_verify_opaque (protocol_t protocol, LPSTREAM instream, 
1250                     LPMESSAGE mapi_message, HWND hwnd, int preview_mode)
1251 {
1252   gpg_error_t err = 0;
1253   mime_context_t ctx;
1254   engine_filter_t filter = NULL;
1255
1256   log_debug ("%s:%s: enter (protocol=%d)", SRCNAME, __func__, protocol);
1257
1258   if (protocol != PROTOCOL_SMIME)
1259     return gpg_error (GPG_ERR_INV_VALUE);
1260
1261   ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
1262   ctx->linebufsize = LINEBUFSIZE;
1263   ctx->hwnd = hwnd;
1264   ctx->preview = preview_mode;
1265   ctx->verify_mode = 0;
1266   ctx->mapi_message = mapi_message;
1267   ctx->mimestruct_tail = &ctx->mimestruct;
1268
1269   ctx->msg = rfc822parse_open (message_cb, ctx);
1270   if (!ctx->msg)
1271     {
1272       err = gpg_error_from_syserror ();
1273       log_error ("%s:%s: failed to open the RFC822 parser: %s", 
1274                  SRCNAME, __func__, gpg_strerror (err));
1275       goto leave;
1276     }
1277
1278   if ((err=engine_create_filter (&filter, plaintext_handler, ctx)))
1279     goto leave;
1280   if ((err=engine_verify_start (filter, hwnd, NULL, 0, protocol)))
1281     goto leave;
1282
1283   /* Filter the stream.  */
1284   do
1285     {
1286       HRESULT hr;
1287       ULONG nread;
1288       char buffer[4096];
1289       
1290       hr = IStream_Read (instream, buffer, sizeof buffer, &nread);
1291       if (hr)
1292         {
1293           log_error ("%s:%s: IStream::Read failed: hr=%#lx", 
1294                      SRCNAME, __func__, hr);
1295           err = gpg_error (GPG_ERR_EIO);
1296         }
1297       else if (nread)
1298         {
1299           err = engine_filter (filter, buffer, nread);
1300         }
1301       else
1302         break; /* EOF */
1303     }
1304   while (!err);
1305   if (err)
1306     goto leave;
1307
1308   /* Wait for the engine to finish.  */
1309   if ((err = engine_filter (filter, NULL, 0)))
1310     goto leave;
1311   if ((err = engine_wait (filter)))
1312     goto leave;
1313   filter = NULL;
1314
1315   if (ctx->parser_error || ctx->line_too_long)
1316     err = gpg_error (GPG_ERR_GENERAL);
1317
1318  leave:
1319   engine_cancel (filter);
1320   if (ctx)
1321     {
1322       /* Cancel any left over attachment which means that the MIME
1323          structure was not complete.  However if we have not seen any
1324          boundary the message is a non-MIME one but we may have
1325          started the body attachment (gpgol000.txt) - this one needs
1326          to be finished properly.  */
1327       finish_attachment (ctx, ctx->any_boundary? 1: 0);
1328       /* Save the body attachment. */
1329       finish_saved_body (ctx, 0);
1330       rfc822parse_close (ctx->msg);
1331       if (ctx->signed_data)
1332         gpgme_data_release (ctx->signed_data);
1333       if (ctx->sig_data)
1334         gpgme_data_release (ctx->sig_data);
1335       finish_message (mapi_message, err, ctx->protect_mode, ctx->mimestruct);
1336       while (ctx->mimestruct)
1337         {
1338           mimestruct_item_t tmp = ctx->mimestruct->next;
1339           xfree (ctx->mimestruct->filename);
1340           xfree (ctx->mimestruct->charset);
1341           xfree (ctx->mimestruct);
1342           ctx->mimestruct = tmp;
1343         }
1344       symenc_close (ctx->symenc);
1345       symenc_close (ctx->body_saved.symenc);
1346       xfree (ctx);
1347     }
1348   return err;
1349 }
1350
1351
1352
1353 /* Process the transition to body event in the decryption parser.
1354
1355    This means we have received the empty line indicating the body and
1356    should now check the headers to see what to do about this part.  */
1357 static int
1358 ciphermessage_t2body (mime_context_t ctx, rfc822parse_t msg)
1359 {
1360   rfc822parse_field_t field;
1361   const char *ctmain, *ctsub;
1362   size_t off;
1363   char *p;
1364   int is_text = 0;
1365         
1366   /* Figure out the encoding.  */
1367   ctx->is_qp_encoded = 0;
1368   ctx->is_base64_encoded = 0;
1369   p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off);
1370   if (p)
1371     {
1372       if (!stricmp (p+off, "quoted-printable"))
1373         ctx->is_qp_encoded = 1;
1374       else if (!stricmp (p+off, "base64"))
1375         {
1376           ctx->is_base64_encoded = 1;
1377           b64_init (&ctx->base64);
1378         }
1379       free (p);
1380     }
1381
1382   /* Process the Content-type and all its parameters.  */
1383   /* Fixme: Currently we don't make any use of it but consider all the
1384      content to be the encrypted data.  */
1385   ctmain = ctsub = NULL;
1386   field = rfc822parse_parse_field (msg, "Content-Type", -1);
1387   if (field)
1388     ctmain = rfc822parse_query_media_type (field, &ctsub);
1389   if (!ctmain)
1390     {
1391       /* Either there is no content type field or it is faulty; in
1392          both cases we fall back to text/plain.  */
1393       ctmain = "text";
1394       ctsub  = "plain";
1395     }
1396
1397 #ifdef DEBUG_PARSER  
1398   log_debug ("%s:%s: ctx=%p, ct=`%s/%s'\n",
1399              SRCNAME, __func__, ctx, ctmain, ctsub);
1400 #endif
1401   rfc822parse_release_field (field); /* (Content-type) */
1402   ctx->in_data = 1;
1403
1404 #ifdef DEBUG_PARSER
1405   log_debug ("%s:%s: this body: nesting=%d part_counter=%d is_text=%d\n",
1406              SRCNAME, __func__, 
1407              ctx->nesting_level, ctx->part_counter, is_text);
1408 #endif
1409
1410
1411   return 0;
1412 }
1413
1414 /* This routine gets called by the RFC822 decryption parser for all
1415    kind of events.  Should return 0 on success or -1 as well as
1416    setting errno on failure.  */
1417 static int
1418 ciphermessage_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
1419 {
1420   int retval = 0;
1421   mime_context_t decctx = opaque;
1422
1423   debug_message_event (decctx, event);
1424
1425   switch (event)
1426     {
1427     case RFC822PARSE_T2BODY:
1428       retval = ciphermessage_t2body (decctx, msg);
1429       break;
1430
1431     case RFC822PARSE_LEVEL_DOWN:
1432       decctx->nesting_level++;
1433       break;
1434
1435     case RFC822PARSE_LEVEL_UP:
1436       if (decctx->nesting_level)
1437         decctx->nesting_level--;
1438       else 
1439         {
1440           log_error ("%s: decctx=%p, invalid structure: bad nesting level\n",
1441                      SRCNAME, decctx);
1442           decctx->parser_error = 1;
1443         }
1444       break;
1445     
1446     case RFC822PARSE_BOUNDARY:
1447     case RFC822PARSE_LAST_BOUNDARY:
1448       decctx->any_boundary = 1;
1449       decctx->in_data = 0;
1450       break;
1451     
1452     case RFC822PARSE_BEGIN_HEADER:
1453       decctx->part_counter++;
1454       break;
1455
1456     default:  /* Ignore all other events. */
1457       break;
1458     }
1459
1460   return retval;
1461 }
1462
1463
1464 /* This handler is called by us with the MIME message containing the
1465    ciphertext. */
1466 static int
1467 ciphertext_handler (void *handle, const void *buffer, size_t size)
1468 {
1469   mime_context_t ctx = handle;
1470   const char *s;
1471   size_t nleft, pos, len;
1472   gpg_error_t err;
1473
1474   s = buffer;
1475   pos = ctx->linebufpos;
1476   nleft = size;
1477   for (; nleft ; nleft--, s++)
1478     {
1479       if (pos >= ctx->linebufsize)
1480         {
1481           log_error ("%s:%s: ctx=%p, rfc822 parser failed: line too long\n",
1482                      SRCNAME, __func__, ctx);
1483           ctx->line_too_long = 1;
1484           return -1; /* Error. */
1485         }
1486       if (*s != '\n')
1487         ctx->linebuf[pos++] = *s;
1488       else
1489         { /* Got a complete line.  Remove the last CR.  */
1490           if (pos && ctx->linebuf[pos-1] == '\r')
1491             pos--;
1492
1493           if (rfc822parse_insert (ctx->msg, ctx->linebuf, pos))
1494             {
1495               log_error ("%s:%s: ctx=%p, rfc822 parser failed: %s\n",
1496                          SRCNAME, __func__, ctx, strerror (errno));
1497               ctx->parser_error = 1;
1498               return -1; /* Error. */
1499             }
1500
1501           if (ctx->in_data)
1502             {
1503               /* We are inside the data.  That should be the actual
1504                  ciphertext in the given encoding.  Pass it on to the
1505                  crypto engine. */
1506               if (ctx->is_qp_encoded)
1507                 len = qp_decode (ctx->linebuf, pos);
1508               else if (ctx->is_base64_encoded)
1509                 len = b64_decode (&ctx->base64, ctx->linebuf, pos);
1510               else
1511                 len = pos;
1512               if (len)
1513                 err = engine_filter (ctx->outfilter, ctx->linebuf, len);
1514               else
1515                 err = 0;
1516               if (!err && !ctx->is_base64_encoded)
1517                 {
1518                   char tmp[3] = "\r\n";
1519                   err = engine_filter (ctx->outfilter, tmp, 2);
1520                 }
1521               if (err)
1522                 {
1523                   log_debug ("%s:%s: sending ciphertext to engine failed: %s",
1524                              SRCNAME, __func__, gpg_strerror (err));
1525                   ctx->parser_error = 1;
1526                   return -1; /* Error. */
1527                 }
1528             }
1529           
1530           /* Continue with next line. */
1531           pos = 0;
1532         }
1533     }
1534   ctx->linebufpos = pos;
1535
1536   return size;
1537 }
1538
1539
1540
1541 /* Decrypt the PGP or S/MIME message taken from INSTREAM.  HWND is the
1542    window to be used for message box and such.  In PREVIEW_MODE no
1543    verification will be done, no messages saved and no messages boxes
1544    will pop up.  If IS_RFC822 is set, the message is expected to be in
1545    rfc822 format.  */
1546 int
1547 mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
1548               int is_rfc822, HWND hwnd, int preview_mode)
1549 {
1550   gpg_error_t err;
1551   mime_context_t decctx, ctx;
1552   engine_filter_t filter = NULL;
1553
1554   log_debug ("%s:%s: enter (protocol=%d, is_rfc822=%d)",
1555              SRCNAME, __func__, protocol, is_rfc822);
1556
1557   if (is_rfc822)
1558     {
1559       decctx = xcalloc (1, sizeof *decctx + LINEBUFSIZE);
1560       decctx->linebufsize = LINEBUFSIZE;
1561       decctx->hwnd = hwnd;
1562     }
1563   else
1564     decctx = NULL;
1565
1566   ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
1567   ctx->linebufsize = LINEBUFSIZE;
1568   ctx->protect_mode = 1; 
1569   ctx->hwnd = hwnd;
1570   ctx->preview = preview_mode;
1571   ctx->mapi_message = mapi_message;
1572   ctx->mimestruct_tail = &ctx->mimestruct;
1573
1574   if (decctx)
1575     {
1576       decctx->msg = rfc822parse_open (ciphermessage_cb, decctx);
1577       if (!decctx->msg)
1578         {
1579           err = gpg_error_from_syserror ();
1580           log_error ("%s:%s: failed to open the RFC822 decryption parser: %s", 
1581                      SRCNAME, __func__, gpg_strerror (err));
1582           goto leave;
1583         }
1584     }
1585
1586   ctx->msg = rfc822parse_open (message_cb, ctx);
1587   if (!ctx->msg)
1588     {
1589       err = gpg_error_from_syserror ();
1590       log_error ("%s:%s: failed to open the RFC822 parser: %s", 
1591                  SRCNAME, __func__, gpg_strerror (err));
1592       goto leave;
1593     }
1594
1595   /* Prepare the decryption.  */
1596 /*       title = native_to_utf8 (_("[Encrypted S/MIME message]")); */
1597 /*       title = native_to_utf8 (_("[Encrypted PGP/MIME message]")); */
1598   if ((err=engine_create_filter (&filter, plaintext_handler, ctx)))
1599     goto leave;
1600   if ((err=engine_decrypt_start (filter, hwnd, protocol, !preview_mode)))
1601     goto leave;
1602
1603   if (decctx)
1604     decctx->outfilter = filter;
1605   
1606   /* Filter the stream.  */
1607   do
1608     {
1609       HRESULT hr;
1610       ULONG nread;
1611       char buffer[4096];
1612       
1613       /* For EOF detection we assume that Read returns no error and
1614          thus NREAD will be 0.  The specs say that "Depending on the
1615          implementation, either S_FALSE or an error code could be
1616          returned when reading past the end of the stream"; thus we
1617          are not really sure whether our assumption is correct.  At
1618          another place the documentation says that the implementation
1619          used by ISequentialStream exhibits the same EOF behaviour has
1620          found on the MSDOS FAT file system.  So we seem to have good
1621          karma. */
1622       hr = IStream_Read (instream, buffer, sizeof buffer, &nread);
1623       if (hr)
1624         {
1625           log_error ("%s:%s: IStream::Read failed: hr=%#lx", 
1626                      SRCNAME, __func__, hr);
1627           err = gpg_error (GPG_ERR_EIO);
1628         }
1629       else if (nread)
1630         {
1631           if (decctx)
1632             {
1633                ciphertext_handler (decctx, buffer, nread);
1634                if (ctx->parser_error || ctx->line_too_long)
1635                  {
1636                    err = gpg_error (GPG_ERR_GENERAL);
1637                    break;
1638                  }
1639             }
1640           else
1641             err = engine_filter (filter, buffer, nread);
1642         }
1643       else
1644         break; /* EOF */
1645     }
1646   while (!err);
1647   if (err)
1648     goto leave;
1649
1650   /* Wait for the engine to finish.  */
1651   if ((err = engine_filter (filter, NULL, 0)))
1652     goto leave;
1653   if ((err = engine_wait (filter)))
1654     goto leave;
1655   filter = NULL;
1656
1657   if (ctx->parser_error || ctx->line_too_long)
1658     err = gpg_error (GPG_ERR_GENERAL);
1659
1660  leave:
1661   engine_cancel (filter);
1662   if (ctx)
1663     {
1664       /* Cancel any left over attachment which means that the MIME
1665          structure was not complete.  However if we have not seen any
1666          boundary the message is a non-MIME one but we may have
1667          started the body attachment (gpgol000.txt) - this one needs
1668          to be finished properly.  */
1669       finish_attachment (ctx, ctx->any_boundary? 1: 0);
1670       /* Save the body attachment.  */
1671       finish_saved_body (ctx, 0);
1672       rfc822parse_close (ctx->msg);
1673       if (ctx->signed_data)
1674         gpgme_data_release (ctx->signed_data);
1675       if (ctx->sig_data)
1676         gpgme_data_release (ctx->sig_data);
1677       finish_message (mapi_message, err, ctx->protect_mode, ctx->mimestruct);
1678       while (ctx->mimestruct)
1679         {
1680           mimestruct_item_t tmp = ctx->mimestruct->next;
1681           xfree (ctx->mimestruct->filename);
1682           xfree (ctx->mimestruct->charset);
1683           xfree (ctx->mimestruct);
1684           ctx->mimestruct = tmp;
1685         }
1686       symenc_close (ctx->symenc);
1687       symenc_close (ctx->body_saved.symenc);
1688       xfree (ctx);
1689     }
1690   if (decctx)
1691     {
1692       rfc822parse_close (decctx->msg);
1693       xfree (decctx);
1694     }
1695   return err;
1696 }
1697