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