Use file descriptor instead of path for mutt_decode_save_attachment()
[apps/madmutt.git] / lib-crypt / pgp.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996,1997 Michael R. Elkins <me@mutt.org>
4  * Copyright (C) 1998,1999 Thomas Roessler <roessler@does-not-exist.org>
5  * Copyright (C) 2004 g10 Code GmbH
6  *
7  * This file is part of mutt-ng, see http://www.muttng.org/.
8  * It's licensed under the GNU General Public License,
9  * please see the file GPL in the top level source directory.
10  */
11
12 /*
13  * This file contains all of the PGP routines necessary to sign, encrypt,
14  * verify and decrypt PGP messages in either the new PGP/MIME format, or
15  * in the older Application/Pgp format.  It also contains some code to
16  * cache the user's passphrase for repeat use when decrypting or signing
17  * a message.
18  */
19
20 #include <lib-lib/lib-lib.h>
21
22 #ifdef HAVE_SYS_RESOURCE_H
23 # include <sys/resource.h>
24 #endif
25
26 #include <lib-mime/mime.h>
27 #include <lib-sys/unix.h>
28
29 #include <lib-ui/curses.h>
30 #include <lib-ui/enter.h>
31 #include <lib-ui/menu.h>
32 #include <lib-mx/mx.h>
33
34 #include "handler.h"
35 #include "pgp.h"
36 #include "copy.h"
37 #include "attach.h"
38
39 #include "crypt.h"
40
41
42 char PgpPass[LONG_STRING];
43 time_t PgpExptime = 0;          /* when does the cached passphrase expire? */
44
45 void pgp_void_passphrase (void)
46 {
47   p_clear(PgpPass, countof(PgpPass));
48   PgpExptime = 0;
49 }
50
51 int pgp_valid_passphrase (void)
52 {
53   time_t now = time (NULL);
54
55   if (pgp_use_gpg_agent ()) {
56     *PgpPass = 0;
57     return 1;                   /* handled by gpg-agent */
58   }
59
60   if (now < PgpExptime)
61     /* Use cached copy.  */
62     return 1;
63
64   pgp_void_passphrase ();
65
66   if (mutt_get_field_unbuffered (_("Enter PGP passphrase:"), PgpPass,
67                                  sizeof (PgpPass), M_PASS) == 0) {
68     PgpExptime = time (NULL) + PgpTimeout;
69     return (1);
70   }
71   else
72     PgpExptime = 0;
73
74   return 0;
75 }
76
77 void pgp_forget_passphrase (void)
78 {
79   pgp_void_passphrase ();
80   mutt_message _("PGP passphrase forgotten.");
81 }
82
83 int pgp_use_gpg_agent (void) {
84   char *tty;
85
86   if (!option (OPTUSEGPGAGENT) || !getenv ("GPG_AGENT_INFO"))
87     return 0;
88
89   if ((tty = ttyname(0)))
90     setenv ("GPG_TTY", tty, 0);
91
92   return 1;
93 }
94
95 char *pgp_keyid (pgp_key_t k)
96 {
97   if ((k->flags & KEYFLAG_SUBKEY) && k->parent && option (OPTPGPIGNORESUB))
98     k = k->parent;
99
100   return _pgp_keyid (k);
101 }
102
103 char *_pgp_keyid (pgp_key_t k)
104 {
105   if (option (OPTPGPLONGIDS))
106     return k->keyid;
107   else
108     return (k->keyid + 8);
109 }
110
111 /* ----------------------------------------------------------------------------
112  * Routines for handing PGP input.
113  */
114
115
116
117 /* Copy PGP output messages and look for signs of a good signature */
118
119 static int pgp_copy_checksig (FILE * fpin, FILE * fpout)
120 {
121   int rv = -1;
122
123   if (PgpGoodSign.pattern) {
124     char *line = NULL;
125     int lineno = 0;
126     ssize_t linelen;
127
128     while ((line = mutt_read_line (line, &linelen, fpin, &lineno)) != NULL) {
129       if (regexec (PgpGoodSign.rx, line, 0, NULL, 0) == 0) {
130         rv = 0;
131       }
132
133       if (m_strncmp (line, "[GNUPG:] ", 9) == 0)
134         continue;
135       fputs (line, fpout);
136       fputc ('\n', fpout);
137     }
138     p_delete(&line);
139   }
140   else {
141     mutt_copy_stream (fpin, fpout);
142     rv = 1;
143   }
144
145   return rv;
146 }
147
148 /* 
149  * Copy a clearsigned message, and strip the signature and PGP's
150  * dash-escaping.
151  * 
152  * XXX - charset handling: We assume that it is safe to do
153  * character set decoding first, dash decoding second here, while
154  * we do it the other way around in the main handler.
155  * 
156  * (Note that we aren't worse than Outlook &c in this, and also
157  * note that we can successfully handle anything produced by any
158  * existing versions of mutt.) 
159  */
160
161 static void pgp_copy_clearsigned (FILE * fpin, STATE * s, char *charset)
162 {
163   char buf[HUGE_STRING];
164   short complete, armor_header;
165
166   fgetconv_t *fc;
167
168   rewind (fpin);
169
170   fc = fgetconv_open (fpin, charset, Charset, M_ICONV_HOOK_FROM);
171
172   for (complete = 1, armor_header = 1;
173        fgetconvs (buf, sizeof (buf), fc) != NULL;
174        complete = strchr (buf, '\n') != NULL) {
175     if (!complete) {
176       if (!armor_header)
177         state_puts (buf, s);
178       continue;
179     }
180
181     if (m_strcmp(buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
182       break;
183
184     if (armor_header) {
185       char *p = vskipspaces(buf);
186
187       if (*p == '\0')
188         armor_header = 0;
189       continue;
190     }
191
192     if (s->prefix)
193       state_puts (s->prefix, s);
194
195     if (buf[0] == '-' && buf[1] == ' ')
196       state_puts (buf + 2, s);
197     else
198       state_puts (buf, s);
199   }
200
201   fgetconv_close (&fc);
202 }
203
204
205 /* Support for the Application/PGP Content Type. */
206
207 int pgp_application_pgp_handler (BODY * m, STATE * s)
208 {
209   int could_not_decrypt = 0;
210   int needpass = -1, pgp_keyblock = 0;
211   int c = 1;
212   int clearsign = 0, rv, rc;
213   long start_pos = 0;
214   long bytes;
215   off_t last_pos, offset;
216   char buf[HUGE_STRING];
217   char outfile[_POSIX_PATH_MAX];
218   char tmpfname[_POSIX_PATH_MAX];
219   FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
220   FILE *tmpfp = NULL;
221   pid_t thepid;
222
223   short maybe_goodsig = 1;
224   short have_any_sigs = 0;
225
226   char body_charset[STRING];
227
228   mutt_get_body_charset (body_charset, sizeof (body_charset), m);
229
230   rc = 0;                       /* silence false compiler warning if (s->flags & M_DISPLAY) */
231
232   fseeko (s->fpin, m->offset, 0);
233   last_pos = m->offset;
234
235   for (bytes = m->length; bytes > 0;) {
236     if (fgets (buf, sizeof (buf), s->fpin) == NULL)
237       break;
238
239     offset = ftello (s->fpin);
240     bytes -= (offset - last_pos);       /* don't rely on m_strlen(buf) */
241     last_pos = offset;
242
243     if (m_strncmp("-----BEGIN PGP ", buf, 15) == 0) {
244       clearsign = 0;
245       start_pos = last_pos;
246
247       if (m_strcmp("MESSAGE-----\n", buf + 15) == 0)
248         needpass = 1;
249       else if (m_strcmp("SIGNED MESSAGE-----\n", buf + 15) == 0) {
250         clearsign = 1;
251         needpass = 0;
252       }
253       else if (!option (OPTDONTHANDLEPGPKEYS) &&
254                m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15) == 0) {
255         needpass = 0;
256         pgp_keyblock = 1;
257       }
258       else {
259         /* XXX - we may wish to recode here */
260         if (s->prefix)
261           state_puts (s->prefix, s);
262         state_puts (buf, s);
263         continue;
264       }
265
266       have_any_sigs = have_any_sigs || (clearsign && (s->flags & M_VERIFY));
267
268       /* Copy PGP material to temporary file */
269       tmpfp = m_tempfile(tmpfname, sizeof(tmpfname), NONULL(Tempdir), NULL);
270       if (tmpfp == NULL) {
271         mutt_perror (tmpfname);
272         return (-1);
273       }
274
275       fputs (buf, tmpfp);
276       while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL) {
277         offset = ftello (s->fpin);
278         bytes -= (offset - last_pos);   /* don't rely on m_strlen(buf) */
279         last_pos = offset;
280
281         fputs (buf, tmpfp);
282
283         if ((needpass
284              && m_strcmp("-----END PGP MESSAGE-----\n", buf) == 0)
285             || (!needpass
286                 && (m_strcmp("-----END PGP SIGNATURE-----\n", buf) == 0
287                     || m_strcmp("-----END PGP PUBLIC KEY BLOCK-----\n",
288                                     buf) == 0)))
289           break;
290       }
291
292       /* leave tmpfp open in case we still need it - but flush it! */
293       fflush (tmpfp);
294
295
296       /* Invoke PGP if needed */
297       if (!clearsign || (s->flags & M_VERIFY)) {
298         pgpout = m_tempfile(outfile, sizeof(outfile), NONULL(Tempdir), NULL);
299         if (pgpout == NULL) {
300           mutt_perror (outfile);
301           return (-1);
302         }
303
304         if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
305                                          fileno (pgpout), -1, tmpfname,
306                                          needpass)) == -1) {
307           m_fclose(&pgpout);
308           maybe_goodsig = 0;
309           pgpin = NULL;
310           pgperr = NULL;
311           state_attach_puts (_
312                              ("[-- Error: unable to create PGP subprocess! --]\n"),
313                              s);
314         }
315         else {                  /* PGP started successfully */
316
317           if (needpass) {
318             if (!pgp_valid_passphrase ())
319               pgp_void_passphrase ();
320             if (pgp_use_gpg_agent ())
321               *PgpPass = 0;
322             fprintf (pgpin, "%s\n", PgpPass);
323           }
324
325           m_fclose(&pgpin);
326
327           if (s->flags & M_DISPLAY) {
328             crypt_current_time (s, "PGP");
329             rc = pgp_copy_checksig (pgperr, s->fpout);
330           }
331
332           m_fclose(&pgperr);
333           rv = mutt_wait_filter (thepid);
334
335           if (s->flags & M_DISPLAY) {
336             if (rc == 0)
337               have_any_sigs = 1;
338
339             /*
340              * Sig is bad if
341              * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
342              * Sig _is_ correct if
343              * gpg_good_sign="" && pgp_decode_command returned 0
344              */
345             if (rc == -1 || rv)
346               maybe_goodsig = 0;
347
348             state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
349           }
350         }
351
352         /* treat empty result as sign of failure */
353         /* TODO: maybe on failure mutt should include the original undecoded text. */
354         if (pgpout) {
355           rewind (pgpout);
356           c = fgetc (pgpout);
357           ungetc (c, pgpout);
358         }
359         if (!clearsign && (!pgpout || c == EOF)) {
360           could_not_decrypt = 1;
361           pgp_void_passphrase ();
362         }
363
364         if (could_not_decrypt && !(s->flags & M_DISPLAY)) {
365           mutt_error _("Could not decrypt PGP message");
366           mutt_sleep (1);
367           rc = -1;
368           goto out;
369         }
370       }
371
372       /*
373        * Now, copy cleartext to the screen.  NOTE - we expect that PGP
374        * outputs utf-8 cleartext.  This may not always be true, but it 
375        * seems to be a reasonable guess.
376        */
377
378       if (s->flags & M_DISPLAY) {
379         if (needpass)
380           state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
381         else if (pgp_keyblock)
382           state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
383         else
384           state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
385       }
386
387       if (clearsign) {
388         rewind (tmpfp);
389         if (tmpfp)
390           pgp_copy_clearsigned (tmpfp, s, body_charset);
391       }
392       else if (pgpout) {
393         fgetconv_t *fc;
394
395         rewind (pgpout);
396         state_set_prefix (s);
397         fc = fgetconv_open (pgpout, "utf-8", Charset, 0);
398         while ((c = fgetconv (fc)) != EOF)
399           state_prefix_putc (c, s);
400         fgetconv_close (&fc);
401       }
402
403       if (s->flags & M_DISPLAY) {
404         state_putc ('\n', s);
405         if (needpass) {
406           state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
407           if (could_not_decrypt)
408             mutt_error _("Could not decrypt PGP message.");
409           else
410             mutt_message _("PGP message successfully decrypted.");
411         }
412         else if (pgp_keyblock)
413           state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
414         else
415           state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
416       }
417
418     }
419     else {
420       /* XXX - we may wish to recode here */
421       if (s->prefix)
422         state_puts (s->prefix, s);
423       state_puts (buf, s);
424     }
425   }
426
427   rc = 0;
428
429 out:
430   m->goodsig = (maybe_goodsig && have_any_sigs);
431
432   if (tmpfp) {
433     m_fclose(&tmpfp);
434     mutt_unlink (tmpfname);
435   }
436   if (pgpout) {
437     m_fclose(&pgpout);
438     mutt_unlink (outfile);
439   }
440
441   if (needpass == -1) {
442     state_attach_puts (_
443                        ("[-- Error: could not find beginning of PGP message! --]\n\n"),
444                        s);
445     return (-1);
446   }
447
448   return (rc);
449 }
450
451 static int pgp_check_traditional_one_body (FILE * fp, BODY * b,
452                                            int tagged_only)
453 {
454   char tempfile[_POSIX_PATH_MAX];
455   char buf[HUGE_STRING];
456   FILE *tfp;
457   int tempfd;
458
459   short sgn = 0;
460   short enc = 0;
461   short key = 0;
462
463   if (b->type != TYPETEXT)
464     return 0;
465
466   if (tagged_only && !b->tagged)
467     return 0;
468
469   tempfd = m_tempfd(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL);
470
471   if (mutt_decode_save_attachment (fp, b, tempfd, 0) != 0) {
472     unlink (tempfile);
473     return 0;
474   }
475
476   if ((tfp = fdopen (tempfd, "r")) == NULL) {
477     unlink (tempfile);
478     return 0;
479   }
480
481   while (fgets (buf, sizeof (buf), tfp)) {
482     if (m_strncmp("-----BEGIN PGP ", buf, 15) == 0) {
483       if (m_strcmp("MESSAGE-----\n", buf + 15) == 0)
484         enc = 1;
485       else if (m_strcmp("SIGNED MESSAGE-----\n", buf + 15) == 0)
486         sgn = 1;
487       else if (m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
488         key = 1;
489     }
490   }
491   m_fclose(&tfp);
492   unlink (tempfile);
493
494   if (!enc && !sgn && !key)
495     return 0;
496
497   /* fix the content type */
498
499   parameter_setval(&b->parameter, "format", "fixed");
500   if (enc)
501     parameter_setval(&b->parameter, "x-action", "pgp-encrypted");
502   else if (sgn)
503     parameter_setval(&b->parameter, "x-action", "pgp-signed");
504   else if (key)
505     parameter_setval(&b->parameter, "x-action", "pgp-keys");
506
507   return 1;
508 }
509
510 int pgp_check_traditional (FILE * fp, BODY * b, int tagged_only)
511 {
512   int rv = 0;
513   int r;
514
515   for (; b; b = b->next) {
516     if (is_multipart (b))
517       rv = pgp_check_traditional (fp, b->parts, tagged_only) || rv;
518     else if (b->type == TYPETEXT) {
519       if ((r = mutt_is_application_pgp (b)))
520         rv = rv || r;
521       else
522         rv = pgp_check_traditional_one_body (fp, b, tagged_only) || rv;
523     }
524   }
525
526   return rv;
527 }
528
529
530
531
532
533 int pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
534 {
535   char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
536   FILE *fp, *pgpout, *pgperr;
537   pid_t thepid;
538   int badsig = -1;
539   int rv;
540
541   snprintf (sigfile, sizeof (sigfile), "%s.asc", tempfile);
542
543   if (!(fp = safe_fopen (sigfile, "w"))) {
544     mutt_perror (sigfile);
545     return -1;
546   }
547
548   fseeko (s->fpin, sigbdy->offset, 0);
549   mutt_copy_bytes (s->fpin, fp, sigbdy->length);
550   m_fclose(&fp);
551
552   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(Tempdir), NULL);
553   if (pgperr == NULL) {
554     mutt_perror (pgperrfile);
555     unlink (sigfile);
556     return -1;
557   }
558
559   crypt_current_time (s, "PGP");
560
561   if ((thepid = pgp_invoke_verify (NULL, &pgpout, NULL,
562                                    -1, -1, fileno (pgperr),
563                                    tempfile, sigfile)) != -1) {
564     if (pgp_copy_checksig (pgpout, s->fpout) >= 0)
565       badsig = 0;
566
567
568     m_fclose(&pgpout);
569     fflush (pgperr);
570     rewind (pgperr);
571
572     if (pgp_copy_checksig (pgperr, s->fpout) >= 0)
573       badsig = 0;
574
575     if ((rv = mutt_wait_filter (thepid)))
576       badsig = -1;
577   }
578
579   m_fclose(&pgperr);
580
581   state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
582
583   mutt_unlink (sigfile);
584   mutt_unlink (pgperrfile);
585
586   return badsig;
587 }
588
589
590 /* Extract pgp public keys from messages or attachments */
591
592 static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top)
593 {
594   STATE s;
595   FILE *tempfp;
596   char tempfname[_POSIX_PATH_MAX];
597
598   tempfp = m_tempfile(tempfname, sizeof(tempfname), NONULL(Tempdir), NULL);
599   if (tempfp == NULL) {
600     mutt_perror (_("Can't create temporary file"));
601     return;
602   }
603
604   p_clear(&s, 1);
605
606   s.fpin = fp;
607   s.fpout = tempfp;
608
609   mutt_body_handler (top, &s);
610
611   m_fclose(&tempfp);
612
613   pgp_invoke_import (tempfname);
614   mutt_any_key_to_continue (NULL);
615
616   mutt_unlink (tempfname);
617 }
618
619 void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top)
620 {
621   if (!fp) {
622     mutt_error _("Internal error. Inform <roessler@does-not-exist.org>.");
623
624     return;
625   }
626
627   mutt_endwin (NULL);
628   set_option (OPTDONTHANDLEPGPKEYS);
629
630   for (; top; top = top->next) {
631     if (!tag || top->tagged)
632       pgp_extract_keys_from_attachment (fp, top);
633
634     if (!tag)
635       break;
636   }
637
638   unset_option (OPTDONTHANDLEPGPKEYS);
639 }
640
641 BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p)
642 {
643   char buf[LONG_STRING];
644   FILE *pgpin, *pgpout, *pgperr, *pgptmp;
645   struct stat info;
646   BODY *tattach;
647   int len;
648   char pgperrfile[_POSIX_PATH_MAX];
649   char pgptmpfile[_POSIX_PATH_MAX];
650   pid_t thepid;
651   int rv;
652
653   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(Tempdir), NULL);
654   if (!pgperr) {
655     mutt_perror (pgperrfile);
656     return NULL;
657   }
658   unlink (pgperrfile);
659
660   pgptmp = m_tempfile(pgptmpfile, sizeof(pgptmpfile), NONULL(Tempdir), NULL);
661   if (!pgptmp) {
662     mutt_perror (pgptmpfile);
663     m_fclose(&pgperr);
664     return NULL;
665   }
666
667   /* Position the stream at the beginning of the body, and send the data to
668    * the temporary file.
669    */
670
671   fseeko (s->fpin, a->offset, 0);
672   mutt_copy_bytes (s->fpin, pgptmp, a->length);
673   m_fclose(&pgptmp);
674
675   if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1,
676                                     fileno (pgperr), pgptmpfile)) == -1) {
677     m_fclose(&pgperr);
678     unlink (pgptmpfile);
679     if (s->flags & M_DISPLAY)
680       state_attach_puts (_
681                          ("[-- Error: could not create a PGP subprocess! --]\n\n"),
682                          s);
683     return (NULL);
684   }
685
686   /* send the PGP passphrase to the subprocess.  Never do this if the
687      agent is active, because this might lead to a passphrase send as
688      the message. */
689   if (!pgp_use_gpg_agent ())
690     fputs (PgpPass, pgpin);
691   fputc ('\n', pgpin);
692   m_fclose(&pgpin);
693
694   /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
695    * read_mime_header has a hard time parsing the message.
696    */
697   while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL) {
698     len = m_strlen(buf);
699     if (len > 1 && buf[len - 2] == '\r')
700       m_strcpy(buf + len - 2, len - 2,  "\n");
701     fputs (buf, fpout);
702   }
703
704   m_fclose(&pgpout);
705   rv = mutt_wait_filter (thepid);
706   mutt_unlink (pgptmpfile);
707
708   if (s->flags & M_DISPLAY) {
709     fflush (pgperr);
710     rewind (pgperr);
711     if (pgp_copy_checksig (pgperr, s->fpout) == 0 && !rv && p)
712       p->goodsig = 1;
713     else
714       p->goodsig = 0;
715     state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
716   }
717   m_fclose(&pgperr);
718
719   fflush (fpout);
720   rewind (fpout);
721
722   if (fgetc (fpout) == EOF) {
723     mutt_error (_("Decryption failed."));
724     pgp_void_passphrase ();
725     return NULL;
726   }
727
728   rewind (fpout);
729
730   if ((tattach = mutt_read_mime_header (fpout, 0)) != NULL) {
731     /*
732      * Need to set the length of this body part.
733      */
734     fstat (fileno (fpout), &info);
735     tattach->length = info.st_size - tattach->offset;
736
737     /* See if we need to recurse on this MIME part.  */
738
739     mutt_parse_part (fpout, tattach);
740   }
741
742   return (tattach);
743 }
744
745 int pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
746 {
747   char tempfile[_POSIX_PATH_MAX];
748   STATE s;
749   BODY *p = b;
750
751   if (!mutt_is_multipart_encrypted (b))
752     return -1;
753
754   if (!b->parts || !b->parts->next)
755     return -1;
756
757   b = b->parts->next;
758
759   p_clear(&s, 1);
760   s.fpin = fpin;
761   *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL);
762   if (*fpout == NULL) {
763     mutt_perror (_("Can't create temporary file"));
764     return (-1);
765   }
766   unlink (tempfile);
767
768   *cur = pgp_decrypt_part (b, &s, *fpout, p);
769
770   rewind (*fpout);
771
772   if (!*cur)
773     return -1;
774
775   return (0);
776 }
777
778 int pgp_encrypted_handler (BODY * a, STATE * s)
779 {
780   char tempfile[_POSIX_PATH_MAX];
781   FILE *fpout, *fpin;
782   BODY *tattach;
783   BODY *p = a;
784   int rc = 0;
785
786   a = a->parts;
787   if (!a || a->type != TYPEAPPLICATION || !a->subtype ||
788       ascii_strcasecmp ("pgp-encrypted", a->subtype) != 0 ||
789       !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype ||
790       ascii_strcasecmp ("octet-stream", a->next->subtype) != 0) {
791     if (s->flags & M_DISPLAY)
792       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
793                          s);
794     return (-1);
795   }
796
797   /*
798    * Move forward to the application/pgp-encrypted body.
799    */
800   a = a->next;
801
802   fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL);
803   if (fpout == NULL) {
804     if (s->flags & M_DISPLAY)
805       state_attach_puts (_
806                          ("[-- Error: could not create temporary file! --]\n"),
807                          s);
808     return (-1);
809   }
810
811   if (s->flags & M_DISPLAY)
812     crypt_current_time (s, "PGP");
813
814   if ((tattach = pgp_decrypt_part (a, s, fpout, p)) != NULL) {
815     if (s->flags & M_DISPLAY)
816       state_attach_puts (_
817                          ("[-- The following data is PGP/MIME encrypted --]\n\n"),
818                          s);
819
820     fpin = s->fpin;
821     s->fpin = fpout;
822     rc = mutt_body_handler (tattach, s);
823     s->fpin = fpin;
824
825     /* 
826      * if a multipart/signed is the _only_ sub-part of a
827      * multipart/encrypted, cache signature verification
828      * status.
829      *
830      */
831
832     if (mutt_is_multipart_signed (tattach) && !tattach->next)
833       p->goodsig |= tattach->goodsig;
834
835     if (s->flags & M_DISPLAY) {
836       state_puts ("\n", s);
837       state_attach_puts (_("[-- End of PGP/MIME encrypted data --]\n"), s);
838     }
839
840     body_list_wipe(&tattach);
841     /* clear 'Invoking...' message, since there's no error */
842     mutt_message _("PGP message successfully decrypted.");
843   } else {
844     mutt_error _("Could not decrypt PGP message");
845     pgp_void_passphrase ();
846     rc = -1;
847   }
848
849   m_fclose(&fpout);
850   mutt_unlink (tempfile);
851
852   return (rc);
853 }
854
855 /* ----------------------------------------------------------------------------
856  * Routines for sending PGP/MIME messages.
857  */
858
859
860 BODY *pgp_sign_message (BODY * a)
861 {
862   BODY *t;
863   char buffer[LONG_STRING];
864   char sigfile[_POSIX_PATH_MAX], signedfile[_POSIX_PATH_MAX];
865   FILE *pgpin, *pgpout, *pgperr, *fp, *sfp;
866   int err = 0;
867   int empty = 1;
868   pid_t thepid;
869
870   convert_to_7bit (a);          /* Signed data _must_ be in 7-bit format. */
871
872   fp = m_tempfile(sigfile, sizeof(sigfile), NONULL(Tempdir), NULL);
873   if (fp == NULL) {
874     return (NULL);
875   }
876
877   sfp = m_tempfile(signedfile, sizeof(signedfile), NONULL(Tempdir), NULL);
878   if (sfp == NULL) {
879     mutt_perror (signedfile);
880     m_fclose(&fp);
881     unlink (sigfile);
882     return NULL;
883   }
884
885   mutt_write_mime_header (a, sfp);
886   fputc ('\n', sfp);
887   mutt_write_mime_body (a, sfp);
888   m_fclose(&sfp);
889
890   if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr,
891                                  -1, -1, -1, signedfile)) == -1) {
892     mutt_perror (_("Can't open PGP subprocess!"));
893
894     m_fclose(&fp);
895     unlink (sigfile);
896     unlink (signedfile);
897     return NULL;
898   }
899
900   if (!pgp_use_gpg_agent ())
901     fputs (PgpPass, pgpin);
902   fputc ('\n', pgpin);
903   m_fclose(&pgpin);
904
905   /*
906    * Read back the PGP signature.  Also, change MESSAGE=>SIGNATURE as
907    * recommended for future releases of PGP.
908    */
909   while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL) {
910     if (m_strcmp("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
911       fputs ("-----BEGIN PGP SIGNATURE-----\n", fp);
912     else if (m_strcmp("-----END PGP MESSAGE-----\n", buffer) == 0)
913       fputs ("-----END PGP SIGNATURE-----\n", fp);
914     else
915       fputs (buffer, fp);
916     empty = 0;                  /* got some output, so we're ok */
917   }
918
919   /* check for errors from PGP */
920   err = 0;
921   while (fgets (buffer, sizeof (buffer) - 1, pgperr) != NULL) {
922     err = 1;
923     fputs (buffer, stdout);
924   }
925
926   if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT))
927     empty = 1;
928
929   m_fclose(&pgperr);
930   m_fclose(&pgpout);
931   unlink (signedfile);
932
933   if (m_fclose(&fp) != 0) {
934     mutt_perror ("fclose");
935     unlink (sigfile);
936     return (NULL);
937   }
938
939   if (err) {
940     pgp_void_passphrase ();
941     mutt_any_key_to_continue (NULL);
942   }
943
944   if (empty) {
945     unlink (sigfile);
946     return (NULL);              /* fatal error while signing */
947   }
948
949   t = body_new();
950   t->type = TYPEMULTIPART;
951   t->subtype = m_strdup("signed");
952   t->encoding = ENC7BIT;
953   t->use_disp = 0;
954   t->disposition = DISPINLINE;
955
956   parameter_set_boundary(&t->parameter);
957   parameter_setval(&t->parameter, "protocol", "application/pgp-signature");
958   parameter_setval(&t->parameter, "micalg", pgp_micalg (sigfile));
959
960   t->parts = a;
961   a = t;
962
963   t->parts->next = body_new();
964   t = t->parts->next;
965   t->type = TYPEAPPLICATION;
966   t->subtype = m_strdup("pgp-signature");
967   t->filename = m_strdup(sigfile);
968   t->use_disp = 0;
969   t->disposition = DISPINLINE;
970   t->encoding = ENC7BIT;
971   t->unlink = 1;                /* ok to remove this file after sending. */
972
973   return (a);
974 }
975
976 static short is_numerical_keyid (const char *s)
977 {
978   /* or should we require the "0x"? */
979   if (m_strncmp (s, "0x", 2) == 0)
980     s += 2;
981   if (m_strlen(s) % 8)
982     return 0;
983   while (*s)
984     if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL)
985       return 0;
986
987   return 1;
988 }
989
990 /* This routine attempts to find the keyids of the recipients of a message.
991  * It returns NULL if any of the keys can not be found.
992  */
993 char *pgp_findKeys (address_t * to, address_t * cc, address_t * bcc)
994 {
995   char *keylist = NULL, *t;
996   const char *keyID;
997   size_t keylist_size = 0;
998   size_t keylist_used = 0;
999   address_t *tmp = NULL, *addr = NULL;
1000   address_t **last = &tmp;
1001   address_t *p, *q;
1002   int i;
1003   pgp_key_t k_info = NULL, key = NULL;
1004
1005   const char *fqdn = mutt_fqdn (1);
1006
1007   for (i = 0; i < 3; i++) {
1008     switch (i) {
1009     case 0:
1010       p = to;
1011       break;
1012     case 1:
1013       p = cc;
1014       break;
1015     case 2:
1016       p = bcc;
1017       break;
1018     default:
1019       abort ();
1020     }
1021
1022     *last = address_list_dup (p);
1023     while (*last)
1024       last = &((*last)->next);
1025   }
1026
1027   rfc822_qualify (tmp, fqdn);
1028
1029   address_list_uniq(tmp);
1030
1031   for (p = tmp; p; p = p->next) {
1032     char buf[LONG_STRING];
1033
1034     q = p;
1035     k_info = NULL;
1036
1037     if ((keyID = mutt_crypt_hook (p)) != NULL) {
1038       int r;
1039
1040       snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID,
1041                 p->mailbox);
1042       if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
1043         if (is_numerical_keyid (keyID)) {
1044           if (m_strncmp (keyID, "0x", 2) == 0)
1045             keyID += 2;
1046           goto bypass_selection;        /* you don't see this. */
1047         }
1048
1049         /* check for e-mail address */
1050         if ((t = strchr (keyID, '@')) &&
1051             (addr = rfc822_parse_adrlist (NULL, keyID))) {
1052           rfc822_qualify (addr, fqdn);
1053           q = addr;
1054         }
1055         else
1056           k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
1057       }
1058       else if (r == -1) {
1059         p_delete(&keylist);
1060         address_list_wipe(&tmp);
1061         address_list_wipe(&addr);
1062         return NULL;
1063       }
1064     }
1065
1066     if (k_info == NULL)
1067       pgp_invoke_getkeys (q);
1068
1069     if (k_info == NULL
1070         && (k_info =
1071             pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) {
1072       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
1073
1074       if ((key = pgp_ask_for_key (buf, q->mailbox,
1075                                   KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) {
1076         p_delete(&keylist);
1077         address_list_wipe(&tmp);
1078         address_list_wipe(&addr);
1079         return NULL;
1080       }
1081     }
1082     else
1083       key = k_info;
1084
1085     keyID = pgp_keyid (key);
1086
1087   bypass_selection:
1088     keylist_size += m_strlen(keyID) + 4;
1089     p_realloc(&keylist, keylist_size);
1090     sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "",
1091              keyID);
1092     keylist_used = m_strlen(keylist);
1093
1094     pgp_free_key (&key);
1095     address_list_wipe(&addr);
1096
1097   }
1098   address_list_wipe(&tmp);
1099   return (keylist);
1100 }
1101
1102 /* Warning: "a" is no longer freed in this routine, you need
1103  * to free it later.  This is necessary for $fcc_attach. */
1104
1105 BODY *pgp_encrypt_message (BODY * a, char *keylist, int sign)
1106 {
1107   char buf[LONG_STRING];
1108   char tempfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
1109   char pgpinfile[_POSIX_PATH_MAX];
1110   FILE *pgpin, *pgperr, *fpout, *fptmp;
1111   BODY *t;
1112   int err = 0;
1113   int empty = 0;
1114   pid_t thepid;
1115
1116   fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(Tempdir), NULL);
1117   if (fpout == NULL) {
1118     mutt_perror (_("Can't create temporary file"));
1119     return (NULL);
1120   }
1121
1122   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(Tempdir), NULL);
1123   if (pgperr == NULL) {
1124     mutt_perror (pgperrfile);
1125     m_fclose(&fpout);
1126     unlink (tempfile);
1127     return NULL;
1128   }
1129   unlink (pgperrfile);
1130
1131   fptmp = m_tempfile(pgpinfile, sizeof(pgpinfile), NONULL(Tempdir), NULL);
1132   if (fptmp == NULL) {
1133     mutt_perror (pgpinfile);
1134     m_fclose(&fpout);
1135     unlink (tempfile);
1136     m_fclose(&pgperr);
1137     unlink (pgperrfile);
1138     return NULL;
1139   }
1140
1141   if (sign)
1142     convert_to_7bit (a);
1143
1144   mutt_write_mime_header (a, fptmp);
1145   fputc ('\n', fptmp);
1146   mutt_write_mime_body (a, fptmp);
1147   m_fclose(&fptmp);
1148
1149   if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1,
1150                                     fileno (fpout), fileno (pgperr),
1151                                     pgpinfile, keylist, sign)) == -1) {
1152     m_fclose(&pgperr);
1153     unlink (pgpinfile);
1154     return (NULL);
1155   }
1156
1157   if (sign) {
1158     if (!pgp_use_gpg_agent ())
1159       fputs (PgpPass, pgpin);
1160     fputc ('\n', pgpin);
1161   }
1162   m_fclose(&pgpin);
1163
1164   if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT))
1165     empty = 1;
1166
1167   unlink (pgpinfile);
1168
1169   fflush (fpout);
1170   rewind (fpout);
1171   if (!empty)
1172     empty = (fgetc (fpout) == EOF);
1173   m_fclose(&fpout);
1174
1175   fflush (pgperr);
1176   rewind (pgperr);
1177   while (fgets (buf, sizeof (buf) - 1, pgperr) != NULL) {
1178     err = 1;
1179     fputs (buf, stdout);
1180   }
1181   m_fclose(&pgperr);
1182
1183   /* pause if there is any error output from PGP */
1184   if (err)
1185     mutt_any_key_to_continue (NULL);
1186
1187   if (empty) {
1188     /* fatal error while trying to encrypt message */
1189     if (sign)
1190       pgp_void_passphrase (); /* just in case */
1191     unlink (tempfile);
1192     return (NULL);
1193   }
1194
1195   t = body_new();
1196   t->type = TYPEMULTIPART;
1197   t->subtype = m_strdup("encrypted");
1198   t->encoding = ENC7BIT;
1199   t->use_disp = 0;
1200   t->disposition = DISPINLINE;
1201
1202   parameter_set_boundary(&t->parameter);
1203   parameter_setval(&t->parameter, "protocol", "application/pgp-encrypted");
1204
1205   t->parts = body_new();
1206   t->parts->type = TYPEAPPLICATION;
1207   t->parts->subtype = m_strdup("pgp-encrypted");
1208   t->parts->encoding = ENC7BIT;
1209
1210   t->parts->next = body_new();
1211   t->parts->next->type = TYPEAPPLICATION;
1212   t->parts->next->subtype = m_strdup("octet-stream");
1213   t->parts->next->encoding = ENC7BIT;
1214   t->parts->next->filename = m_strdup(tempfile);
1215   t->parts->next->use_disp = 1;
1216   t->parts->next->disposition = DISPINLINE;
1217   t->parts->next->unlink = 1;   /* delete after sending the message */
1218   t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime can save */
1219
1220   return (t);
1221 }
1222
1223 BODY *pgp_traditional_encryptsign (BODY * a, int flags, char *keylist)
1224 {
1225   BODY *b;
1226
1227   char pgpoutfile[_POSIX_PATH_MAX];
1228   char pgperrfile[_POSIX_PATH_MAX];
1229   char pgpinfile[_POSIX_PATH_MAX];
1230
1231   char body_charset[STRING];
1232   char *from_charset;
1233   const char *send_charset;
1234
1235   FILE *pgpout = NULL, *pgperr = NULL, *pgpin = NULL;
1236   FILE *fp;
1237
1238   int empty = 0;
1239   int err;
1240
1241   char buff[STRING];
1242
1243   pid_t thepid;
1244
1245   if (a->type != TYPETEXT)
1246     return NULL;
1247   if (ascii_strcasecmp (a->subtype, "plain"))
1248     return NULL;
1249
1250   if ((fp = fopen (a->filename, "r")) == NULL) {
1251     mutt_perror (a->filename);
1252     return NULL;
1253   }
1254
1255   pgpin = m_tempfile(pgpinfile, sizeof(pgpinfile), NONULL(Tempdir), NULL);
1256   if (pgpin == NULL) {
1257     mutt_perror (pgpinfile);
1258     m_fclose(&fp);
1259     return NULL;
1260   }
1261
1262   /* The following code is really correct:  If noconv is set,
1263    * a's charset parameter contains the on-disk character set, and
1264    * we have to convert from that to utf-8.  If noconv is not set,
1265    * we have to convert from $charset to utf-8.
1266    */
1267
1268   mutt_get_body_charset (body_charset, sizeof (body_charset), a);
1269   if (a->noconv)
1270     from_charset = body_charset;
1271   else
1272     from_charset = Charset;
1273
1274   if (!charset_is_us_ascii (body_charset)) {
1275     int c;
1276     fgetconv_t *fc;
1277
1278     if (flags & ENCRYPT)
1279       send_charset = "us-ascii";
1280     else
1281       send_charset = "utf-8";
1282
1283     fc = fgetconv_open (fp, from_charset, "utf-8", M_ICONV_HOOK_FROM);
1284     while ((c = fgetconv (fc)) != EOF)
1285       fputc (c, pgpin);
1286
1287     fgetconv_close (&fc);
1288   }
1289   else {
1290     send_charset = "us-ascii";
1291     mutt_copy_stream (fp, pgpin);
1292   }
1293   m_fclose(&fp);
1294   m_fclose(&pgpin);
1295
1296   pgpout = m_tempfile(pgpoutfile, sizeof(pgpoutfile), NONULL(Tempdir), NULL);
1297   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(Tempdir), NULL);
1298   if (pgpout == NULL || pgperr == NULL) {
1299     mutt_perror (pgpout ? pgperrfile : pgpoutfile);
1300     m_fclose(&pgpin);
1301     unlink (pgpinfile);
1302     m_fclose(&pgpout);
1303     unlink (pgpoutfile);
1304     m_fclose(&pgperr);
1305     unlink(pgperrfile);
1306     return NULL;
1307   }
1308
1309   unlink (pgperrfile);
1310
1311   if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL,
1312                                         -1, fileno (pgpout), fileno (pgperr),
1313                                         pgpinfile, keylist, flags)) == -1) {
1314     mutt_perror (_("Can't invoke PGP"));
1315
1316     m_fclose(&pgpout);
1317     m_fclose(&pgperr);
1318     mutt_unlink (pgpinfile);
1319     unlink (pgpoutfile);
1320     return NULL;
1321   }
1322
1323   if (pgp_use_gpg_agent ())
1324     *PgpPass = 0;
1325   if (flags & SIGN)
1326     fprintf (pgpin, "%s\n", PgpPass);
1327   m_fclose(&pgpin);
1328
1329   if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT))
1330     empty = 1;
1331
1332   mutt_unlink (pgpinfile);
1333
1334   fflush (pgpout);
1335   fflush (pgperr);
1336
1337   rewind (pgpout);
1338   rewind (pgperr);
1339
1340   if (!empty)
1341     empty = (fgetc (pgpout) == EOF);
1342   m_fclose(&pgpout);
1343
1344   err = 0;
1345
1346   while (fgets (buff, sizeof (buff), pgperr)) {
1347     err = 1;
1348     fputs (buff, stdout);
1349   }
1350
1351   m_fclose(&pgperr);
1352
1353   if (err)
1354     mutt_any_key_to_continue (NULL);
1355
1356   if (empty) {
1357     if (flags & SIGN)
1358       pgp_void_passphrase (); /* just in case */
1359     unlink (pgpoutfile);
1360     return NULL;
1361   }
1362
1363   b = body_new();
1364
1365   b->encoding = ENC7BIT;
1366
1367   b->type = TYPETEXT;
1368   b->subtype = m_strdup("plain");
1369
1370   parameter_setval(&b->parameter, "x-action",
1371                    flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed");
1372   parameter_setval(&b->parameter, "charset", send_charset);
1373
1374   b->filename = m_strdup(pgpoutfile);
1375
1376   b->disposition = DISPINLINE;
1377   b->unlink = 1;
1378
1379   b->noconv = 1;
1380   b->use_disp = 0;
1381
1382   if (!(flags & ENCRYPT))
1383     b->encoding = a->encoding;
1384
1385   return b;
1386 }
1387
1388 int pgp_send_menu (HEADER * msg, int *redraw)
1389 {
1390   pgp_key_t p;
1391   char input_signas[STRING];
1392
1393   char prompt[LONG_STRING];
1394
1395   /* If autoinline and no crypto options set, then set inline. */
1396   if (option (OPTPGPAUTOINLINE) && !((msg->security & APPLICATION_PGP)
1397                                      && (msg->security & (SIGN | ENCRYPT))))
1398     msg->security |= INLINE;
1399
1400   snprintf (prompt, sizeof (prompt),
1401             _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s, or (c)lear? "),
1402             (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline"));
1403
1404   switch (mutt_multi_choice (prompt, _("esabifc"))) {
1405   case 1:                      /* (e)ncrypt */
1406     msg->security |= ENCRYPT;
1407     msg->security &= ~SIGN;
1408     break;
1409
1410   case 2:                      /* (s)ign */
1411     msg->security |= SIGN;
1412     msg->security &= ~ENCRYPT;
1413     break;
1414
1415   case 3:                      /* sign (a)s */
1416     unset_option (OPTPGPCHECKTRUST);
1417
1418     if ((p =
1419          pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
1420                           PGP_PUBRING))) {
1421       snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p));
1422       m_strreplace(&PgpSignAs, input_signas);
1423       pgp_free_key (&p);
1424
1425       msg->security |= SIGN;
1426
1427       crypt_pgp_void_passphrase ();     /* probably need a different passphrase */
1428     }
1429
1430     *redraw = REDRAW_FULL;
1431     break;
1432
1433   case 4:                      /* (b)oth */
1434     msg->security |= (ENCRYPT | SIGN);
1435     break;
1436
1437   case 5:                      /* (i)nline */
1438     if ((msg->security & (ENCRYPT | SIGN)))
1439       msg->security ^= INLINE;
1440     else
1441       msg->security &= ~INLINE;
1442     break;
1443
1444   case 6:                      /* (f)orget it */
1445   case 7:                      /* (c)lear     */
1446     msg->security = 0;
1447     break;
1448   }
1449
1450   if (msg->security) {
1451     if (!(msg->security & (ENCRYPT | SIGN)))
1452       msg->security = 0;
1453     else
1454       msg->security |= APPLICATION_PGP;
1455   }
1456
1457   return (msg->security);
1458 }