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