g10: Unattended key generation "Key-Grip" and "Subkey-Grip".
[gnupg.git] / tools / mime-parser.c
1 /* mime-parser.c - Parse MIME structures (high level rfc822 parser).
2  * Copyright (C) 2016 g10 Code GmbH
3  * Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * This file is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "../common/util.h"
27 #include "rfc822parse.h"
28 #include "mime-parser.h"
29
30
31 enum pgpmime_states
32   {
33     PGPMIME_NONE = 0,
34     PGPMIME_WAIT_ENCVERSION,
35     PGPMIME_IN_ENCVERSION,
36     PGPMIME_WAIT_ENCDATA,
37     PGPMIME_IN_ENCDATA,
38     PGPMIME_GOT_ENCDATA,
39     PGPMIME_WAIT_SIGNEDDATA,
40     PGPMIME_IN_SIGNEDDATA,
41     PGPMIME_WAIT_SIGNATURE,
42     PGPMIME_IN_SIGNATURE,
43     PGPMIME_GOT_SIGNATURE,
44     PGPMIME_INVALID
45   };
46
47
48 /* Definition of the mime parser object.  */
49 struct mime_parser_context_s
50 {
51   void *cookie;                /* Cookie passed to all callbacks.  */
52
53   /* The callback to announce the transation from header to body.  */
54   gpg_error_t (*t2body) (void *cookie, int level);
55
56   /* The callback to announce a new part.  */
57   gpg_error_t (*new_part) (void *cookie,
58                            const char *mediatype,
59                            const char *mediasubtype);
60   /* The callback to return data of a part.  */
61   gpg_error_t (*part_data) (void *cookie,
62                             const void *data,
63                             size_t datalen);
64   /* The callback to collect encrypted data.  */
65   gpg_error_t (*collect_encrypted) (void *cookie, const char *data);
66   /* The callback to collect signed data.  */
67   gpg_error_t (*collect_signeddata) (void *cookie, const char *data);
68   /* The callback to collect a signature.  */
69   gpg_error_t (*collect_signature) (void *cookie, const char *data);
70
71   /* The RFC822 parser context is stored here during callbacks.  */
72   rfc822parse_t msg;
73
74   /* Helper to convey error codes from user callbacks.  */
75   gpg_error_t err;
76
77   int nesting_level;           /* The current nesting level.  */
78   int hashing_at_level;        /* The nesting level at which we are hashing. */
79   enum pgpmime_states pgpmime; /* Current PGP/MIME state.  */
80   unsigned int delay_hashing:1;/* Helper for PGPMIME_IN_SIGNEDDATA. */
81   unsigned int want_part:1;    /* Return the current part.  */
82   unsigned int decode_part:2;  /* Decode the part.  1 = QP, 2 = Base64. */
83
84   unsigned int verbose:1;      /* Enable verbose mode.  */
85   unsigned int debug:1;        /* Enable debug mode.  */
86
87   /* Flags to help with debug output.  */
88   struct {
89     unsigned int n_skip;         /* Skip showing these number of lines.  */
90     unsigned int header:1;       /* Show the header lines.  */
91     unsigned int data:1;         /* Show the data lines.  */
92     unsigned int as_note:1;      /* Show the next data line as a note.  */
93     unsigned int boundary : 1;
94   } show;
95
96   struct b64state *b64state;     /* NULL or malloced Base64 decoder state.  */
97
98   /* A buffer for reading a mail line,  */
99   char line[5000];
100 };
101
102
103 /* Print the event received by the parser for debugging.  */
104 static void
105 show_message_parser_event (rfc822parse_event_t event)
106 {
107   const char *s;
108
109   switch (event)
110     {
111     case RFC822PARSE_OPEN: s= "Open"; break;
112     case RFC822PARSE_CLOSE: s= "Close"; break;
113     case RFC822PARSE_CANCEL: s= "Cancel"; break;
114     case RFC822PARSE_T2BODY: s= "T2Body"; break;
115     case RFC822PARSE_FINISH: s= "Finish"; break;
116     case RFC822PARSE_RCVD_SEEN: s= "Rcvd_Seen"; break;
117     case RFC822PARSE_LEVEL_DOWN: s= "Level_Down"; break;
118     case RFC822PARSE_LEVEL_UP: s= "Level_Up"; break;
119     case RFC822PARSE_BOUNDARY: s= "Boundary"; break;
120     case RFC822PARSE_LAST_BOUNDARY: s= "Last_Boundary"; break;
121     case RFC822PARSE_BEGIN_HEADER: s= "Begin_Header"; break;
122     case RFC822PARSE_PREAMBLE: s= "Preamble"; break;
123     case RFC822PARSE_EPILOGUE: s= "Epilogue"; break;
124     default: s= "[unknown event]"; break;
125     }
126   log_debug ("*** RFC822 event %s\n", s);
127 }
128
129
130 /* Do in-place decoding of quoted-printable data of LENGTH in BUFFER.
131    Returns the new length of the buffer and stores true at R_SLBRK if
132    the line ended with a soft line break; false is stored if not.
133    This function asssumes that a complete line is passed in
134    buffer.  */
135 static size_t
136 qp_decode (char *buffer, size_t length, int *r_slbrk)
137 {
138   char *d, *s;
139
140   if (r_slbrk)
141     *r_slbrk = 0;
142
143   /* Fixme:  We should remove trailing white space first.  */
144   for (s=d=buffer; length; length--)
145     {
146       if (*s == '=')
147         {
148           if (length > 2 && hexdigitp (s+1) && hexdigitp (s+2))
149             {
150               s++;
151               *(unsigned char*)d++ = xtoi_2 (s);
152               s += 2;
153               length -= 2;
154             }
155           else if (length > 2 && s[1] == '\r' && s[2] == '\n')
156             {
157               /* Soft line break.  */
158               s += 3;
159               length -= 2;
160               if (r_slbrk && length == 1)
161                 *r_slbrk = 1;
162             }
163           else if (length > 1 && s[1] == '\n')
164             {
165               /* Soft line break with only a Unix line terminator. */
166               s += 2;
167               length -= 1;
168               if (r_slbrk && length == 1)
169                 *r_slbrk = 1;
170             }
171           else if (length == 1)
172             {
173               /* Soft line break at the end of the line. */
174               s += 1;
175               if (r_slbrk)
176                 *r_slbrk = 1;
177             }
178           else
179             *d++ = *s++;
180         }
181       else
182         *d++ = *s++;
183     }
184
185   return d - buffer;
186 }
187
188
189 /* This function is called by parse_mail to communicate events.  This
190  * callback communicates with the caller using a structure passed in
191  * OPAQUE.  Should return 0 on success or set ERRNO and return -1. */
192 static int
193 parse_message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
194 {
195   mime_parser_t ctx = opaque;
196   const char *s;
197   int rc = 0;
198
199   /* Make the RFC822 parser context availabale for callbacks.  */
200   ctx->msg = msg;
201
202   if (ctx->debug)
203     show_message_parser_event (event);
204
205   if (event == RFC822PARSE_BEGIN_HEADER || event == RFC822PARSE_T2BODY)
206     {
207       /* We need to check here whether to start collecting signed data
208        * because attachments might come without header lines and thus
209        * we won't see the BEGIN_HEADER event.  */
210       if (ctx->pgpmime == PGPMIME_WAIT_SIGNEDDATA)
211         {
212           if (ctx->debug)
213             log_debug ("begin_hash\n");
214           ctx->hashing_at_level = ctx->nesting_level;
215           ctx->pgpmime = PGPMIME_IN_SIGNEDDATA;
216           ctx->delay_hashing = 0;
217         }
218     }
219
220   if (event == RFC822PARSE_OPEN)
221     {
222       /* Initialize for a new message. */
223       ctx->show.header = 1;
224     }
225   else if (event == RFC822PARSE_T2BODY)
226     {
227       rfc822parse_field_t field;
228
229       ctx->want_part = 0;
230       ctx->decode_part = 0;
231
232       if (ctx->t2body)
233         {
234           rc = ctx->t2body (ctx->cookie, ctx->nesting_level);
235           if (rc)
236             goto t2body_leave;
237         }
238
239       field = rfc822parse_parse_field (msg, "Content-Type", -1);
240       if (field)
241         {
242           const char *s1, *s2;
243
244           s1 = rfc822parse_query_media_type (field, &s2);
245           if (s1)
246             {
247               if (ctx->verbose)
248                 log_debug ("h media: %*s%s %s\n",
249                            ctx->nesting_level*2, "", s1, s2);
250               if (ctx->pgpmime == PGPMIME_WAIT_ENCVERSION)
251                 {
252                   if (!strcmp (s1, "application")
253                       && !strcmp (s2, "pgp-encrypted"))
254                     {
255                       if (ctx->debug)
256                         log_debug ("c begin_encversion\n");
257                       ctx->pgpmime = PGPMIME_IN_ENCVERSION;
258                     }
259                   else
260                     {
261                       log_error ("invalid PGP/MIME structure;"
262                                  " expected '%s', got '%s/%s'\n",
263                                  "application/pgp-encrypted", s1, s2);
264                       ctx->pgpmime = PGPMIME_INVALID;
265                     }
266                 }
267               else if (ctx->pgpmime == PGPMIME_WAIT_ENCDATA)
268                 {
269                   if (!strcmp (s1, "application")
270                       && !strcmp (s2, "octet-stream"))
271                     {
272                       if (ctx->debug)
273                         log_debug ("c begin_encdata\n");
274                       ctx->pgpmime = PGPMIME_IN_ENCDATA;
275                     }
276                   else
277                     {
278                       log_error ("invalid PGP/MIME structure;"
279                                  " expected '%s', got '%s/%s'\n",
280                                  "application/octet-stream", s1, s2);
281                       ctx->pgpmime = PGPMIME_INVALID;
282                     }
283                 }
284               else if (ctx->pgpmime == PGPMIME_WAIT_SIGNATURE)
285                 {
286                   if (!strcmp (s1, "application")
287                       && !strcmp (s2, "pgp-signature"))
288                     {
289                       if (ctx->debug)
290                         log_debug ("c begin_signature\n");
291                       ctx->pgpmime = PGPMIME_IN_SIGNATURE;
292                     }
293                   else
294                     {
295                       log_error ("invalid PGP/MIME structure;"
296                                  " expected '%s', got '%s/%s'\n",
297                                  "application/pgp-signature", s1, s2);
298                       ctx->pgpmime = PGPMIME_INVALID;
299                     }
300                 }
301               else if (!strcmp (s1, "multipart")
302                        && !strcmp (s2, "encrypted"))
303                 {
304                   s = rfc822parse_query_parameter (field, "protocol", 0);
305                   if (s)
306                     {
307                       if (ctx->debug)
308                         log_debug ("h encrypted.protocol: %s\n", s);
309                       if (!strcmp (s, "application/pgp-encrypted"))
310                         {
311                           if (ctx->pgpmime)
312                             log_error ("note: "
313                                        "ignoring nested PGP/MIME signature\n");
314                           else
315                             ctx->pgpmime = PGPMIME_WAIT_ENCVERSION;
316                         }
317                       else if (ctx->verbose)
318                         log_debug ("# this protocol is not supported\n");
319                     }
320                 }
321               else if (!strcmp (s1, "multipart")
322                        && !strcmp (s2, "signed"))
323                 {
324                   s = rfc822parse_query_parameter (field, "protocol", 1);
325                   if (s)
326                     {
327                       if (ctx->debug)
328                         log_debug ("h signed.protocol: %s\n", s);
329                       if (!strcmp (s, "application/pgp-signature"))
330                         {
331                           if (ctx->pgpmime)
332                             log_error ("note: "
333                                        "ignoring nested PGP/MIME signature\n");
334                           else
335                             ctx->pgpmime = PGPMIME_WAIT_SIGNEDDATA;
336                         }
337                       else if (ctx->verbose)
338                         log_debug ("# this protocol is not supported\n");
339                     }
340                 }
341               else if (ctx->new_part)
342                 {
343                   ctx->err = ctx->new_part (ctx->cookie, s1, s2);
344                   if (!ctx->err)
345                     ctx->want_part = 1;
346                   else if (gpg_err_code (ctx->err) == GPG_ERR_FALSE)
347                     ctx->err = 0;
348                   else if (gpg_err_code (ctx->err) == GPG_ERR_TRUE)
349                     {
350                       ctx->want_part = ctx->decode_part = 1;
351                       ctx->err = 0;
352                     }
353                 }
354             }
355           else
356             {
357               if (ctx->debug)
358                 log_debug ("h media: %*s none\n", ctx->nesting_level*2, "");
359               if (ctx->new_part)
360                 {
361                   ctx->err = ctx->new_part (ctx->cookie, "", "");
362                   if (!ctx->err)
363                     ctx->want_part = 1;
364                   else if (gpg_err_code (ctx->err) == GPG_ERR_FALSE)
365                     ctx->err = 0;
366                   else if (gpg_err_code (ctx->err) == GPG_ERR_TRUE)
367                     {
368                       ctx->want_part = ctx->decode_part = 1;
369                       ctx->err = 0;
370                     }
371                 }
372             }
373
374           rfc822parse_release_field (field);
375         }
376       else
377         {
378           if (ctx->verbose)
379             log_debug ("h media: %*stext plain [assumed]\n",
380                        ctx->nesting_level*2, "");
381           if (ctx->new_part)
382             {
383               ctx->err = ctx->new_part (ctx->cookie, "text", "plain");
384               if (!ctx->err)
385                 ctx->want_part = 1;
386               else if (gpg_err_code (ctx->err) == GPG_ERR_FALSE)
387                 ctx->err = 0;
388               else if (gpg_err_code (ctx->err) == GPG_ERR_TRUE)
389                 {
390                   ctx->want_part = ctx->decode_part = 1;
391                   ctx->err = 0;
392                 }
393             }
394         }
395
396       /* Figure out the encoding if needed.  */
397       if (ctx->decode_part)
398         {
399           char *value;
400           size_t valueoff;
401
402           ctx->decode_part = 0; /* Fallback for unknown encoding.  */
403           value = rfc822parse_get_field (msg, "Content-Transfer-Encoding", -1,
404                                          &valueoff);
405           if (value)
406             {
407               if (!stricmp (value+valueoff, "quoted-printable"))
408                 ctx->decode_part = 1;
409               else if (!stricmp (value+valueoff, "base64"))
410                 {
411                   ctx->decode_part = 2;
412                   if (ctx->b64state)
413                     b64dec_finish (ctx->b64state); /* Reuse state.  */
414                   else
415                     {
416                       ctx->b64state = xtrymalloc (sizeof *ctx->b64state);
417                       if (!ctx->b64state)
418                         rc = gpg_error_from_syserror ();
419                     }
420                   if (!rc)
421                     rc = b64dec_start (ctx->b64state, NULL);
422                 }
423               free (value); /* Right, we need a plain free.  */
424             }
425         }
426
427     t2body_leave:
428       ctx->show.header = 0;
429       ctx->show.data = 1;
430       ctx->show.n_skip = 1;
431     }
432   else if (event == RFC822PARSE_PREAMBLE)
433     ctx->show.as_note = 1;
434   else if (event == RFC822PARSE_LEVEL_DOWN)
435     {
436       if (ctx->debug)
437         log_debug ("b down\n");
438       ctx->nesting_level++;
439     }
440   else if (event == RFC822PARSE_LEVEL_UP)
441     {
442       if (ctx->debug)
443         log_debug ("b up\n");
444       if (ctx->nesting_level)
445         ctx->nesting_level--;
446       else
447         log_error ("invalid structure (bad nesting level)\n");
448     }
449   else if (event == RFC822PARSE_BOUNDARY || event == RFC822PARSE_LAST_BOUNDARY)
450     {
451       ctx->show.data = 0;
452       ctx->show.boundary = 1;
453       if (event == RFC822PARSE_BOUNDARY)
454         {
455           ctx->show.header = 1;
456           ctx->show.n_skip = 1;
457           if (ctx->debug)
458             log_debug ("b part\n");
459         }
460       else if (ctx->debug)
461         log_debug ("b last\n");
462
463       if (ctx->pgpmime == PGPMIME_IN_ENCDATA)
464         {
465           if (ctx->debug)
466             log_debug ("c end_encdata\n");
467           ctx->pgpmime = PGPMIME_GOT_ENCDATA;
468           /* FIXME: We should assert (event == LAST_BOUNDARY).  */
469         }
470       else if (ctx->pgpmime == PGPMIME_IN_SIGNEDDATA
471                && ctx->nesting_level == ctx->hashing_at_level)
472         {
473           if (ctx->debug)
474             log_debug ("c end_hash\n");
475           ctx->pgpmime = PGPMIME_WAIT_SIGNATURE;
476           if (ctx->collect_signeddata)
477             ctx->err = ctx->collect_signeddata (ctx->cookie, NULL);
478         }
479       else if (ctx->pgpmime == PGPMIME_IN_SIGNATURE)
480         {
481           if (ctx->debug)
482             log_debug ("c end_signature\n");
483           ctx->pgpmime = PGPMIME_GOT_SIGNATURE;
484           /* FIXME: We should assert (event == LAST_BOUNDARY).  */
485         }
486       else if (ctx->want_part)
487         {
488           if (ctx->part_data)
489             {
490               /* FIXME: We may need to flush things.  */
491               ctx->err = ctx->part_data (ctx->cookie, NULL, 0);
492             }
493           ctx->want_part = 0;
494         }
495     }
496
497   ctx->msg = NULL;
498
499   return rc;
500 }
501
502
503 /* Create a new mime parser object.  COOKIE is a values which will be
504  * used as first argument for all callbacks registered with this
505  * parser object.  */
506 gpg_error_t
507 mime_parser_new (mime_parser_t *r_parser, void *cookie)
508 {
509   mime_parser_t ctx;
510
511   *r_parser = NULL;
512
513   ctx = xtrycalloc (1, sizeof *ctx);
514   if (!ctx)
515     return gpg_error_from_syserror ();
516   ctx->cookie = cookie;
517
518   *r_parser = ctx;
519   return 0;
520 }
521
522
523 /* Release a mime parser object.  */
524 void
525 mime_parser_release (mime_parser_t ctx)
526 {
527   if (!ctx)
528     return;
529
530   if (ctx->b64state)
531     {
532       b64dec_finish (ctx->b64state);
533       xfree (ctx->b64state);
534     }
535   xfree (ctx);
536 }
537
538
539 /* Set verbose and debug mode.  */
540 void
541 mime_parser_set_verbose (mime_parser_t ctx, int level)
542 {
543   if (!level)
544     {
545       ctx->verbose = 0;
546       ctx->debug = 0;
547     }
548   else
549     {
550       ctx->verbose = 1;
551       if (level > 10)
552         ctx->debug = 1;
553     }
554 }
555
556
557 /* Set a callback for the transition from header to body.  LEVEL is
558  * the current nesting level, starting with 0.  This callback can be
559  * used to evaluate headers before any other action is done.  Note
560  * that if a new NEW_PART callback needs to be called it is done after
561  * this T2BODY callback.  */
562 void
563 mime_parser_set_t2body (mime_parser_t ctx,
564                         gpg_error_t (*fnc) (void *cookie, int level))
565 {
566   ctx->t2body = fnc;
567 }
568
569
570 /* Set the callback used to announce a new part.  It will be called
571  * with the media type and media subtype of the part.  If no
572  * Content-type header was given both values are the empty string.
573  * The callback should return 0 on success or an error code.  The
574  * error code GPG_ERR_FALSE indicates that the caller is not
575  * interested in the part and data shall not be returned via a
576  * registered part_data callback.  The error code GPG_ERR_TRUE
577  * indicates that the parts shall be redurned in decoded format
578  * (i.e. base64 or QP encoding is removed).  */
579 void
580 mime_parser_set_new_part (mime_parser_t ctx,
581                           gpg_error_t (*fnc) (void *cookie,
582                                               const char *mediatype,
583                                               const char *mediasubtype))
584 {
585   ctx->new_part = fnc;
586 }
587
588
589 /* Set the callback used to return the data of a part to the caller.
590  * The end of the part is indicated by passing NUL for DATA.  */
591 void
592 mime_parser_set_part_data (mime_parser_t ctx,
593                            gpg_error_t (*fnc) (void *cookie,
594                                                const void *data,
595                                                size_t datalen))
596 {
597   ctx->part_data = fnc;
598 }
599
600
601 /* Set the callback to collect encrypted data.  A NULL passed to the
602  * callback indicates the end of the encrypted data; the callback may
603  * then decrypt the collected data.  */
604 void
605 mime_parser_set_collect_encrypted (mime_parser_t ctx,
606                                    gpg_error_t (*fnc) (void *cookie,
607                                                        const char *data))
608 {
609   ctx->collect_encrypted = fnc;
610 }
611
612
613 /* Set the callback to collect signed data.  A NULL passed to the
614  * callback indicates the end of the signed data.  */
615 void
616 mime_parser_set_collect_signeddata (mime_parser_t ctx,
617                                     gpg_error_t (*fnc) (void *cookie,
618                                                         const char *data))
619 {
620   ctx->collect_signeddata = fnc;
621 }
622
623
624 /* Set the callback to collect the signature.  A NULL passed to the
625  * callback indicates the end of the signature; the callback may the
626  * verify the signature.  */
627 void
628 mime_parser_set_collect_signature (mime_parser_t ctx,
629                                    gpg_error_t (*fnc) (void *cookie,
630                                                        const char *data))
631 {
632   ctx->collect_signature = fnc;
633 }
634
635
636 /* Return the RFC888 parser context.  This is only available inside a
637  * callback.  */
638 rfc822parse_t
639 mime_parser_rfc822parser (mime_parser_t ctx)
640 {
641   return ctx->msg;
642 }
643
644
645 /* Helper for mime_parser_parse.  */
646 static gpg_error_t
647 process_part_data (mime_parser_t ctx, char *line, size_t *length)
648 {
649   gpg_error_t err;
650   size_t nbytes;
651
652   if (!ctx->want_part)
653     return 0;
654   if (!ctx->part_data)
655     return 0;
656
657   if (ctx->decode_part == 1)
658     {
659       *length = qp_decode (line, *length, NULL);
660     }
661   else if (ctx->decode_part == 2)
662     {
663       log_assert (ctx->b64state);
664       err = b64dec_proc (ctx->b64state, line, *length, &nbytes);
665       if (err)
666         return err;
667       *length = nbytes;
668     }
669
670   return ctx->part_data (ctx->cookie, line, *length);
671 }
672
673
674 /* Read and parse a message from FP and call the appropriate
675  * callbacks.  */
676 gpg_error_t
677 mime_parser_parse (mime_parser_t ctx, estream_t fp)
678 {
679   gpg_error_t err;
680   rfc822parse_t msg = NULL;
681   unsigned int lineno = 0;
682   size_t length;
683   char *line;
684
685   line = ctx->line;
686
687   msg = rfc822parse_open (parse_message_cb, ctx);
688   if (!msg)
689     {
690       err = gpg_error_from_syserror ();
691       log_error ("can't open mail parser: %s", gpg_strerror (err));
692       goto leave;
693     }
694
695   /* Fixme: We should not use fgets because it can't cope with
696      embedded nul characters. */
697   while (es_fgets (ctx->line, sizeof (ctx->line), fp))
698     {
699       lineno++;
700       if (lineno == 1 && !strncmp (line, "From ", 5))
701         continue;  /* We better ignore a leading From line. */
702
703       length = strlen (line);
704       if (length && line[length - 1] == '\n')
705         line[--length] = 0;
706       else
707         log_error ("mail parser detected too long or"
708                    " non terminated last line (lnr=%u)\n", lineno);
709       if (length && line[length - 1] == '\r')
710         line[--length] = 0;
711
712       ctx->err = 0;
713       if (rfc822parse_insert (msg, line, length))
714         {
715           err = gpg_error_from_syserror ();
716           log_error ("mail parser failed: %s", gpg_strerror (err));
717           goto leave;
718         }
719       if (ctx->err)
720         {
721           /* Error from a callback detected.  */
722           err = ctx->err;
723           goto leave;
724         }
725
726
727       /* Debug output.  Note that the boundary is shown before n_skip
728        * is evaluated.  */
729       if (ctx->show.boundary)
730         {
731           if (ctx->debug)
732             log_debug ("# Boundary: %s\n", line);
733           ctx->show.boundary = 0;
734         }
735       if (ctx->show.n_skip)
736         ctx->show.n_skip--;
737       else if (ctx->show.data)
738         {
739           if (ctx->show.as_note)
740             {
741               if (ctx->verbose)
742                 log_debug ("# Note: %s\n", line);
743               ctx->show.as_note = 0;
744             }
745           else if (ctx->debug)
746             log_debug ("# Data: %s\n", line);
747         }
748       else if (ctx->show.header && ctx->verbose)
749         log_debug ("# Header: %s\n", line);
750
751       if (ctx->pgpmime == PGPMIME_IN_ENCVERSION)
752         {
753           trim_trailing_spaces (line);
754           if (!*line)
755             ;  /* Skip empty lines.  */
756           else if (!strcmp (line, "Version: 1"))
757             ctx->pgpmime = PGPMIME_WAIT_ENCDATA;
758           else
759             {
760               log_error ("invalid PGP/MIME structure;"
761                          " garbage in pgp-encrypted part ('%s')\n", line);
762               ctx->pgpmime = PGPMIME_INVALID;
763             }
764         }
765       else if (ctx->pgpmime == PGPMIME_IN_ENCDATA)
766         {
767           if (ctx->collect_encrypted)
768             {
769               err = ctx->collect_encrypted (ctx->cookie, line);
770               if (!err)
771                 err = ctx->collect_encrypted (ctx->cookie, "\r\n");
772               if (err)
773                 goto leave;
774             }
775         }
776       else if (ctx->pgpmime == PGPMIME_GOT_ENCDATA)
777         {
778           ctx->pgpmime = PGPMIME_NONE;
779           if (ctx->collect_encrypted)
780             ctx->collect_encrypted (ctx->cookie, NULL);
781         }
782       else if (ctx->pgpmime == PGPMIME_IN_SIGNEDDATA)
783         {
784           /* If we are processing signed data, store the signed data.
785            * We need to delay the hashing of the CR/LF because the
786            * last line ending belongs to the next boundary.  This is
787            * the reason why we can't use the PGPMIME state as a
788            * condition.  */
789           if (ctx->debug)
790             log_debug ("# hashing %s'%s'\n",
791                        ctx->delay_hashing? "CR,LF+":"", line);
792           if (ctx->collect_signeddata)
793             {
794               if (ctx->delay_hashing)
795                 ctx->collect_signeddata (ctx->cookie, "\r\n");
796               ctx->collect_signeddata (ctx->cookie, line);
797             }
798           ctx->delay_hashing = 1;
799
800           err = process_part_data (ctx, line, &length);
801           if (err)
802             goto leave;
803         }
804       else if (ctx->pgpmime == PGPMIME_IN_SIGNATURE)
805         {
806           if (ctx->collect_signeddata)
807             {
808               ctx->collect_signature (ctx->cookie, line);
809               ctx->collect_signature (ctx->cookie, "\r\n");
810             }
811         }
812       else if (ctx->pgpmime == PGPMIME_GOT_SIGNATURE)
813         {
814           ctx->pgpmime = PGPMIME_NONE;
815           if (ctx->collect_signeddata)
816             ctx->collect_signature (ctx->cookie, NULL);
817         }
818       else
819         {
820           err = process_part_data (ctx, line, &length);
821           if (err)
822             goto leave;
823         }
824     }
825
826   rfc822parse_close (msg);
827   msg = NULL;
828   err = 0;
829
830  leave:
831   rfc822parse_cancel (msg);
832   return err;
833 }