b0e7e6299286626e53ffe99e2190527e4cd10072
[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                   int slbrk = 0;
1044
1045                   if (ctx->is_qp_encoded)
1046                     len = qp_decode (ctx->linebuf, pos, &slbrk);
1047                   else if (ctx->is_base64_encoded)
1048                     len = b64_decode (&ctx->base64, ctx->linebuf, pos);
1049                   else
1050                     len = pos;
1051                   if (len)
1052                     {
1053                       if (ctx->symenc)
1054                         symenc_cfb_encrypt (ctx->symenc, ctx->linebuf,
1055                                             ctx->linebuf, len);
1056                       hr = IStream_Write (ctx->outstream, ctx->linebuf,
1057                                           len, NULL);
1058                     }
1059                   if (!hr && !ctx->is_base64_encoded && !slbrk)
1060                     {
1061                       char tmp[3] = "\r\n";
1062                       
1063                       if (ctx->symenc)
1064                         symenc_cfb_encrypt (ctx->symenc, tmp, tmp, 2);
1065                       hr = IStream_Write (ctx->outstream, tmp, 2, NULL);
1066                     }
1067                   if (hr)
1068                     {
1069                       log_debug ("%s:%s: Write failed: hr=%#lx",
1070                                  SRCNAME, __func__, hr);
1071                       if (!ctx->preview)
1072                         MessageBox (ctx->hwnd, _("Error writing to stream"),
1073                                     _("I/O-Error"), MB_ICONERROR|MB_OK);
1074                       ctx->parser_error = 1;
1075                       return -1; /* Error. */
1076                     }
1077                 }
1078             }
1079           else if (ctx->in_data && ctx->collect_signature)
1080             {
1081               /* We are inside of a signature attachment part.  */
1082               if (ctx->collect_signature == 1)  /* Skip the first line. */
1083                 ctx->collect_signature = 2;
1084               else if (ctx->sig_data)
1085                 {
1086                   int slbrk = 0;
1087
1088                   if (ctx->is_qp_encoded)
1089                     len = qp_decode (ctx->linebuf, pos, &slbrk);
1090                   else if (ctx->is_base64_encoded)
1091                     len = b64_decode (&ctx->base64, ctx->linebuf, pos);
1092                   else
1093                     len = pos;
1094                   if (len)
1095                     gpgme_data_write (ctx->sig_data, ctx->linebuf, len);
1096                   if (!ctx->is_base64_encoded && !slbrk)
1097                     gpgme_data_write (ctx->sig_data, "\r\n", 2);
1098                 }
1099             }
1100           
1101           /* Continue with next line. */
1102           pos = 0;
1103         }
1104     }
1105   ctx->linebufpos = pos;
1106
1107   return size;
1108 }
1109
1110
1111
1112 int
1113 mime_verify (protocol_t protocol, const char *message, size_t messagelen, 
1114              LPMESSAGE mapi_message, HWND hwnd, int preview_mode)
1115 {
1116   gpg_error_t err = 0;
1117   mime_context_t ctx;
1118   const char *s;
1119   size_t len;
1120   char *signature = NULL;
1121   size_t sig_len;
1122   engine_filter_t filter = NULL;
1123
1124   /* Note: PROTOCOL is not used here but figured out directly while
1125      collecting the message.  Eventually it might help use setup a
1126      proper verification context right at startup to avoid collecting
1127      all the stuff.  However there are a couple of problems with that
1128      - for example we don't know whether gpgsm behaves correctly by
1129      first reading all the data and only the reading the signature.  I
1130      guess it is the case but that needs to be checked first.  It is
1131      just a performance issue.  */
1132  
1133   ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
1134   ctx->linebufsize = LINEBUFSIZE;
1135   ctx->hwnd = hwnd;
1136   ctx->preview = preview_mode;
1137   ctx->verify_mode = 1;
1138   ctx->mapi_message = mapi_message;
1139   ctx->mimestruct_tail = &ctx->mimestruct;
1140
1141   ctx->msg = rfc822parse_open (message_cb, ctx);
1142   if (!ctx->msg)
1143     {
1144       err = gpg_error_from_syserror ();
1145       log_error ("%s:%s: failed to open the RFC822 parser: %s", 
1146                  SRCNAME, __func__, gpg_strerror (err));
1147       goto leave;
1148     }
1149
1150   /* Need to pass the data line by line to the handler. */
1151   while ( (s = memchr (message, '\n', messagelen)) )
1152     {
1153       len = s - message + 1;
1154 /*       log_debug ("passing '%.*s'\n", (int)len, message); */
1155       plaintext_handler (ctx, message, len);
1156       if (ctx->parser_error || ctx->line_too_long)
1157         {
1158           err = gpg_error (GPG_ERR_GENERAL);
1159           break;
1160         }
1161       message += len;
1162       assert (messagelen >= len);
1163       messagelen -= len;
1164     }
1165   /* Note: the last character should be a LF, if not we ignore such an
1166      incomplete last line.  */
1167   if (ctx->sig_data && gpgme_data_write (ctx->sig_data, "", 1) == 1)
1168     {
1169       signature = gpgme_data_release_and_get_mem (ctx->sig_data, &sig_len);
1170       ctx->sig_data = NULL; 
1171     }
1172
1173   /* Now actually verify the signature. */
1174   if (!err && ctx->signed_data && signature)
1175     {
1176       gpgme_data_seek (ctx->signed_data, 0, SEEK_SET);
1177       
1178       if ((err=engine_create_filter (&filter, NULL, NULL)))
1179         goto leave;
1180       if ((err=engine_verify_start (filter, hwnd, signature, sig_len,
1181                                     ctx->protocol)))
1182         goto leave;
1183
1184       /* Filter the data.  */
1185       do
1186         {
1187           int nread;
1188           char buffer[4096];
1189           
1190           nread = gpgme_data_read (ctx->signed_data, buffer, sizeof buffer);
1191           if (nread < 0)
1192             {
1193               err = gpg_error_from_syserror ();
1194               log_error ("%s:%s: gpgme_data_read failed: %s", 
1195                          SRCNAME, __func__, gpg_strerror (err));
1196             }
1197           else if (nread)
1198             {
1199               err = engine_filter (filter, buffer, nread);
1200             }
1201           else
1202             break; /* EOF */
1203         }
1204       while (!err);
1205       if (err)
1206         goto leave;
1207       
1208       /* Wait for the engine to finish.  */
1209       if ((err = engine_filter (filter, NULL, 0)))
1210         goto leave;
1211       if ((err = engine_wait (filter)))
1212         goto leave;
1213       filter = NULL;
1214     }
1215
1216
1217  leave:
1218   gpgme_free (signature);
1219   engine_cancel (filter);
1220   if (ctx)
1221     {
1222       /* Cancel any left open attachment.  */
1223       finish_attachment (ctx, 1); 
1224       /* Save the body atatchment. */
1225       finish_saved_body (ctx, 0);
1226       rfc822parse_close (ctx->msg);
1227       gpgme_data_release (ctx->signed_data);
1228       gpgme_data_release (ctx->sig_data);
1229       finish_message (mapi_message, err, ctx->protect_mode, ctx->mimestruct);
1230       while (ctx->mimestruct)
1231         {
1232           mimestruct_item_t tmp = ctx->mimestruct->next;
1233           xfree (ctx->mimestruct->filename);
1234           xfree (ctx->mimestruct->charset);
1235           xfree (ctx->mimestruct);
1236           ctx->mimestruct = tmp;
1237         }
1238       symenc_close (ctx->symenc);
1239       symenc_close (ctx->body_saved.symenc);
1240       xfree (ctx);
1241     }
1242   return err;
1243 }
1244
1245
1246 /* A special version of mime_verify which works only for S/MIME opaque
1247    signed messages.  The message is expected to be a binary data
1248    stream with a CMS signature.  This function passes the entire
1249    message to the crypto engine and then parses the (cleartext) output
1250    for rendering the data.  */
1251 int
1252 mime_verify_opaque (protocol_t protocol, LPSTREAM instream, 
1253                     LPMESSAGE mapi_message, HWND hwnd, int preview_mode)
1254 {
1255   gpg_error_t err = 0;
1256   mime_context_t ctx;
1257   engine_filter_t filter = NULL;
1258
1259   log_debug ("%s:%s: enter (protocol=%d)", SRCNAME, __func__, protocol);
1260
1261   if (protocol != PROTOCOL_SMIME)
1262     return gpg_error (GPG_ERR_INV_VALUE);
1263
1264   ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
1265   ctx->linebufsize = LINEBUFSIZE;
1266   ctx->hwnd = hwnd;
1267   ctx->preview = preview_mode;
1268   ctx->verify_mode = 0;
1269   ctx->mapi_message = mapi_message;
1270   ctx->mimestruct_tail = &ctx->mimestruct;
1271
1272   ctx->msg = rfc822parse_open (message_cb, ctx);
1273   if (!ctx->msg)
1274     {
1275       err = gpg_error_from_syserror ();
1276       log_error ("%s:%s: failed to open the RFC822 parser: %s", 
1277                  SRCNAME, __func__, gpg_strerror (err));
1278       goto leave;
1279     }
1280
1281   if ((err=engine_create_filter (&filter, plaintext_handler, ctx)))
1282     goto leave;
1283   if ((err=engine_verify_start (filter, hwnd, NULL, 0, protocol)))
1284     goto leave;
1285
1286   /* Filter the stream.  */
1287   do
1288     {
1289       HRESULT hr;
1290       ULONG nread;
1291       char buffer[4096];
1292       
1293       hr = IStream_Read (instream, buffer, sizeof buffer, &nread);
1294       if (hr)
1295         {
1296           log_error ("%s:%s: IStream::Read failed: hr=%#lx", 
1297                      SRCNAME, __func__, hr);
1298           err = gpg_error (GPG_ERR_EIO);
1299         }
1300       else if (nread)
1301         {
1302           err = engine_filter (filter, buffer, nread);
1303         }
1304       else
1305         break; /* EOF */
1306     }
1307   while (!err);
1308   if (err)
1309     goto leave;
1310
1311   /* Wait for the engine to finish.  */
1312   if ((err = engine_filter (filter, NULL, 0)))
1313     goto leave;
1314   if ((err = engine_wait (filter)))
1315     goto leave;
1316   filter = NULL;
1317
1318   if (ctx->parser_error || ctx->line_too_long)
1319     err = gpg_error (GPG_ERR_GENERAL);
1320
1321  leave:
1322   engine_cancel (filter);
1323   if (ctx)
1324     {
1325       /* Cancel any left over attachment which means that the MIME
1326          structure was not complete.  However if we have not seen any
1327          boundary the message is a non-MIME one but we may have
1328          started the body attachment (gpgol000.txt) - this one needs
1329          to be finished properly.  */
1330       finish_attachment (ctx, ctx->any_boundary? 1: 0);
1331       /* Save the body attachment. */
1332       finish_saved_body (ctx, 0);
1333       rfc822parse_close (ctx->msg);
1334       if (ctx->signed_data)
1335         gpgme_data_release (ctx->signed_data);
1336       if (ctx->sig_data)
1337         gpgme_data_release (ctx->sig_data);
1338       finish_message (mapi_message, err, ctx->protect_mode, ctx->mimestruct);
1339       while (ctx->mimestruct)
1340         {
1341           mimestruct_item_t tmp = ctx->mimestruct->next;
1342           xfree (ctx->mimestruct->filename);
1343           xfree (ctx->mimestruct->charset);
1344           xfree (ctx->mimestruct);
1345           ctx->mimestruct = tmp;
1346         }
1347       symenc_close (ctx->symenc);
1348       symenc_close (ctx->body_saved.symenc);
1349       xfree (ctx);
1350     }
1351   return err;
1352 }
1353
1354
1355
1356 /* Process the transition to body event in the decryption parser.
1357
1358    This means we have received the empty line indicating the body and
1359    should now check the headers to see what to do about this part.  */
1360 static int
1361 ciphermessage_t2body (mime_context_t ctx, rfc822parse_t msg)
1362 {
1363   rfc822parse_field_t field;
1364   const char *ctmain, *ctsub;
1365   size_t off;
1366   char *p;
1367   int is_text = 0;
1368         
1369   /* Figure out the encoding.  */
1370   ctx->is_qp_encoded = 0;
1371   ctx->is_base64_encoded = 0;
1372   p = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1, &off);
1373   if (p)
1374     {
1375       if (!stricmp (p+off, "quoted-printable"))
1376         ctx->is_qp_encoded = 1;
1377       else if (!stricmp (p+off, "base64"))
1378         {
1379           ctx->is_base64_encoded = 1;
1380           b64_init (&ctx->base64);
1381         }
1382       free (p);
1383     }
1384
1385   /* Process the Content-type and all its parameters.  */
1386   /* Fixme: Currently we don't make any use of it but consider all the
1387      content to be the encrypted data.  */
1388   ctmain = ctsub = NULL;
1389   field = rfc822parse_parse_field (msg, "Content-Type", -1);
1390   if (field)
1391     ctmain = rfc822parse_query_media_type (field, &ctsub);
1392   if (!ctmain)
1393     {
1394       /* Either there is no content type field or it is faulty; in
1395          both cases we fall back to text/plain.  */
1396       ctmain = "text";
1397       ctsub  = "plain";
1398     }
1399
1400 #ifdef DEBUG_PARSER  
1401   log_debug ("%s:%s: ctx=%p, ct=`%s/%s'\n",
1402              SRCNAME, __func__, ctx, ctmain, ctsub);
1403 #endif
1404   rfc822parse_release_field (field); /* (Content-type) */
1405   ctx->in_data = 1;
1406
1407 #ifdef DEBUG_PARSER
1408   log_debug ("%s:%s: this body: nesting=%d part_counter=%d is_text=%d\n",
1409              SRCNAME, __func__, 
1410              ctx->nesting_level, ctx->part_counter, is_text);
1411 #endif
1412
1413
1414   return 0;
1415 }
1416
1417 /* This routine gets called by the RFC822 decryption parser for all
1418    kind of events.  Should return 0 on success or -1 as well as
1419    setting errno on failure.  */
1420 static int
1421 ciphermessage_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
1422 {
1423   int retval = 0;
1424   mime_context_t decctx = opaque;
1425
1426   debug_message_event (decctx, event);
1427
1428   switch (event)
1429     {
1430     case RFC822PARSE_T2BODY:
1431       retval = ciphermessage_t2body (decctx, msg);
1432       break;
1433
1434     case RFC822PARSE_LEVEL_DOWN:
1435       decctx->nesting_level++;
1436       break;
1437
1438     case RFC822PARSE_LEVEL_UP:
1439       if (decctx->nesting_level)
1440         decctx->nesting_level--;
1441       else 
1442         {
1443           log_error ("%s: decctx=%p, invalid structure: bad nesting level\n",
1444                      SRCNAME, decctx);
1445           decctx->parser_error = 1;
1446         }
1447       break;
1448     
1449     case RFC822PARSE_BOUNDARY:
1450     case RFC822PARSE_LAST_BOUNDARY:
1451       decctx->any_boundary = 1;
1452       decctx->in_data = 0;
1453       break;
1454     
1455     case RFC822PARSE_BEGIN_HEADER:
1456       decctx->part_counter++;
1457       break;
1458
1459     default:  /* Ignore all other events. */
1460       break;
1461     }
1462
1463   return retval;
1464 }
1465
1466
1467 /* This handler is called by us with the MIME message containing the
1468    ciphertext. */
1469 static int
1470 ciphertext_handler (void *handle, const void *buffer, size_t size)
1471 {
1472   mime_context_t ctx = handle;
1473   const char *s;
1474   size_t nleft, pos, len;
1475   gpg_error_t err;
1476
1477   s = buffer;
1478   pos = ctx->linebufpos;
1479   nleft = size;
1480   for (; nleft ; nleft--, s++)
1481     {
1482       if (pos >= ctx->linebufsize)
1483         {
1484           log_error ("%s:%s: ctx=%p, rfc822 parser failed: line too long\n",
1485                      SRCNAME, __func__, ctx);
1486           ctx->line_too_long = 1;
1487           return -1; /* Error. */
1488         }
1489       if (*s != '\n')
1490         ctx->linebuf[pos++] = *s;
1491       else
1492         { /* Got a complete line.  Remove the last CR.  */
1493           if (pos && ctx->linebuf[pos-1] == '\r')
1494             pos--;
1495
1496           if (rfc822parse_insert (ctx->msg, ctx->linebuf, pos))
1497             {
1498               log_error ("%s:%s: ctx=%p, rfc822 parser failed: %s\n",
1499                          SRCNAME, __func__, ctx, strerror (errno));
1500               ctx->parser_error = 1;
1501               return -1; /* Error. */
1502             }
1503
1504           if (ctx->in_data)
1505             {
1506               /* We are inside the data.  That should be the actual
1507                  ciphertext in the given encoding.  Pass it on to the
1508                  crypto engine. */
1509               int slbrk = 0;
1510
1511               if (ctx->is_qp_encoded)
1512                 len = qp_decode (ctx->linebuf, pos, &slbrk);
1513               else if (ctx->is_base64_encoded)
1514                 len = b64_decode (&ctx->base64, ctx->linebuf, pos);
1515               else
1516                 len = pos;
1517               if (len)
1518                 err = engine_filter (ctx->outfilter, ctx->linebuf, len);
1519               else
1520                 err = 0;
1521               if (!err && !ctx->is_base64_encoded && !slbrk)
1522                 {
1523                   char tmp[3] = "\r\n";
1524                   err = engine_filter (ctx->outfilter, tmp, 2);
1525                 }
1526               if (err)
1527                 {
1528                   log_debug ("%s:%s: sending ciphertext to engine failed: %s",
1529                              SRCNAME, __func__, gpg_strerror (err));
1530                   ctx->parser_error = 1;
1531                   return -1; /* Error. */
1532                 }
1533             }
1534           
1535           /* Continue with next line. */
1536           pos = 0;
1537         }
1538     }
1539   ctx->linebufpos = pos;
1540
1541   return size;
1542 }
1543
1544
1545
1546 /* Decrypt the PGP or S/MIME message taken from INSTREAM.  HWND is the
1547    window to be used for message box and such.  In PREVIEW_MODE no
1548    verification will be done, no messages saved and no messages boxes
1549    will pop up.  If IS_RFC822 is set, the message is expected to be in
1550    rfc822 format.  */
1551 int
1552 mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
1553               int is_rfc822, HWND hwnd, int preview_mode)
1554 {
1555   gpg_error_t err;
1556   mime_context_t decctx, ctx;
1557   engine_filter_t filter = NULL;
1558
1559   log_debug ("%s:%s: enter (protocol=%d, is_rfc822=%d)",
1560              SRCNAME, __func__, protocol, is_rfc822);
1561
1562   if (is_rfc822)
1563     {
1564       decctx = xcalloc (1, sizeof *decctx + LINEBUFSIZE);
1565       decctx->linebufsize = LINEBUFSIZE;
1566       decctx->hwnd = hwnd;
1567     }
1568   else
1569     decctx = NULL;
1570
1571   ctx = xcalloc (1, sizeof *ctx + LINEBUFSIZE);
1572   ctx->linebufsize = LINEBUFSIZE;
1573   ctx->protect_mode = 1; 
1574   ctx->hwnd = hwnd;
1575   ctx->preview = preview_mode;
1576   ctx->mapi_message = mapi_message;
1577   ctx->mimestruct_tail = &ctx->mimestruct;
1578
1579   if (decctx)
1580     {
1581       decctx->msg = rfc822parse_open (ciphermessage_cb, decctx);
1582       if (!decctx->msg)
1583         {
1584           err = gpg_error_from_syserror ();
1585           log_error ("%s:%s: failed to open the RFC822 decryption parser: %s", 
1586                      SRCNAME, __func__, gpg_strerror (err));
1587           goto leave;
1588         }
1589     }
1590
1591   ctx->msg = rfc822parse_open (message_cb, ctx);
1592   if (!ctx->msg)
1593     {
1594       err = gpg_error_from_syserror ();
1595       log_error ("%s:%s: failed to open the RFC822 parser: %s", 
1596                  SRCNAME, __func__, gpg_strerror (err));
1597       goto leave;
1598     }
1599
1600   /* Prepare the decryption.  */
1601 /*       title = native_to_utf8 (_("[Encrypted S/MIME message]")); */
1602 /*       title = native_to_utf8 (_("[Encrypted PGP/MIME message]")); */
1603   if ((err=engine_create_filter (&filter, plaintext_handler, ctx)))
1604     goto leave;
1605   if ((err=engine_decrypt_start (filter, hwnd, protocol, !preview_mode)))
1606     goto leave;
1607
1608   if (decctx)
1609     decctx->outfilter = filter;
1610   
1611   /* Filter the stream.  */
1612   do
1613     {
1614       HRESULT hr;
1615       ULONG nread;
1616       char buffer[4096];
1617       
1618       /* For EOF detection we assume that Read returns no error and
1619          thus NREAD will be 0.  The specs say that "Depending on the
1620          implementation, either S_FALSE or an error code could be
1621          returned when reading past the end of the stream"; thus we
1622          are not really sure whether our assumption is correct.  At
1623          another place the documentation says that the implementation
1624          used by ISequentialStream exhibits the same EOF behaviour has
1625          found on the MSDOS FAT file system.  So we seem to have good
1626          karma. */
1627       hr = IStream_Read (instream, buffer, sizeof buffer, &nread);
1628       if (hr)
1629         {
1630           log_error ("%s:%s: IStream::Read failed: hr=%#lx", 
1631                      SRCNAME, __func__, hr);
1632           err = gpg_error (GPG_ERR_EIO);
1633         }
1634       else if (nread)
1635         {
1636           if (decctx)
1637             {
1638                ciphertext_handler (decctx, buffer, nread);
1639                if (ctx->parser_error || ctx->line_too_long)
1640                  {
1641                    err = gpg_error (GPG_ERR_GENERAL);
1642                    break;
1643                  }
1644             }
1645           else
1646             err = engine_filter (filter, buffer, nread);
1647         }
1648       else
1649         break; /* EOF */
1650     }
1651   while (!err);
1652   if (err)
1653     goto leave;
1654
1655   /* Wait for the engine to finish.  */
1656   if ((err = engine_filter (filter, NULL, 0)))
1657     goto leave;
1658   if ((err = engine_wait (filter)))
1659     goto leave;
1660   filter = NULL;
1661
1662   if (ctx->parser_error || ctx->line_too_long)
1663     err = gpg_error (GPG_ERR_GENERAL);
1664
1665  leave:
1666   engine_cancel (filter);
1667   if (ctx)
1668     {
1669       /* Cancel any left over attachment which means that the MIME
1670          structure was not complete.  However if we have not seen any
1671          boundary the message is a non-MIME one but we may have
1672          started the body attachment (gpgol000.txt) - this one needs
1673          to be finished properly.  */
1674       finish_attachment (ctx, ctx->any_boundary? 1: 0);
1675       /* Save the body attachment.  */
1676       finish_saved_body (ctx, 0);
1677       rfc822parse_close (ctx->msg);
1678       if (ctx->signed_data)
1679         gpgme_data_release (ctx->signed_data);
1680       if (ctx->sig_data)
1681         gpgme_data_release (ctx->sig_data);
1682       finish_message (mapi_message, err, ctx->protect_mode, ctx->mimestruct);
1683       while (ctx->mimestruct)
1684         {
1685           mimestruct_item_t tmp = ctx->mimestruct->next;
1686           xfree (ctx->mimestruct->filename);
1687           xfree (ctx->mimestruct->charset);
1688           xfree (ctx->mimestruct);
1689           ctx->mimestruct = tmp;
1690         }
1691       symenc_close (ctx->symenc);
1692       symenc_close (ctx->body_saved.symenc);
1693       xfree (ctx);
1694     }
1695   if (decctx)
1696     {
1697       rfc822parse_close (decctx->msg);
1698       xfree (decctx);
1699     }
1700   return err;
1701 }
1702