8db2a5df982998ee15c16a23943056da0182455d
[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, MCharset.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(MCore.tmpdir), 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(MCore.tmpdir), 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", MCharset.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(MCore.tmpdir), NULL);
470   if (mutt_decode_save_attachment (fp, b, tempfd, 0) != 0) {
471     unlink (tempfile);
472     return 0;
473   }
474
475   if (!(tfp = fopen(tempfile, "r"))) {
476     unlink(tempfile);
477     return 0;
478   }
479
480   while (fgets (buf, sizeof (buf), tfp)) {
481     if (m_strncmp("-----BEGIN PGP ", buf, 15) == 0) {
482       if (m_strcmp("MESSAGE-----\n", buf + 15) == 0)
483         enc = 1;
484       else if (m_strcmp("SIGNED MESSAGE-----\n", buf + 15) == 0)
485         sgn = 1;
486       else if (m_strcmp("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
487         key = 1;
488     }
489   }
490   m_fclose(&tfp);
491   unlink (tempfile);
492
493   if (!enc && !sgn && !key)
494     return 0;
495
496   /* fix the content type */
497
498   parameter_setval(&b->parameter, "format", "fixed");
499   if (enc)
500     parameter_setval(&b->parameter, "x-action", "pgp-encrypted");
501   else if (sgn)
502     parameter_setval(&b->parameter, "x-action", "pgp-signed");
503   else if (key)
504     parameter_setval(&b->parameter, "x-action", "pgp-keys");
505
506   return 1;
507 }
508
509 int pgp_check_traditional (FILE * fp, BODY * b, int tagged_only)
510 {
511   int rv = 0;
512   int r;
513
514   for (; b; b = b->next) {
515     if (is_multipart (b))
516       rv = pgp_check_traditional (fp, b->parts, tagged_only) || rv;
517     else if (b->type == TYPETEXT) {
518       if ((r = mutt_is_application_pgp (b)))
519         rv = rv || r;
520       else
521         rv = pgp_check_traditional_one_body (fp, b, tagged_only) || rv;
522     }
523   }
524
525   return rv;
526 }
527
528
529
530
531
532 int pgp_verify_one (BODY * sigbdy, STATE * s, const char *tempfile)
533 {
534   char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
535   FILE *fp, *pgpout, *pgperr;
536   pid_t thepid;
537   int badsig = -1;
538   int rv;
539
540   snprintf (sigfile, sizeof (sigfile), "%s.asc", tempfile);
541
542   if (!(fp = safe_fopen (sigfile, "w"))) {
543     mutt_perror (sigfile);
544     return -1;
545   }
546
547   fseeko (s->fpin, sigbdy->offset, 0);
548   mutt_copy_bytes (s->fpin, fp, sigbdy->length);
549   m_fclose(&fp);
550
551   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL);
552   if (pgperr == NULL) {
553     mutt_perror (pgperrfile);
554     unlink (sigfile);
555     return -1;
556   }
557
558   crypt_current_time (s, "PGP");
559
560   if ((thepid = pgp_invoke_verify (NULL, &pgpout, NULL,
561                                    -1, -1, fileno (pgperr),
562                                    tempfile, sigfile)) != -1) {
563     if (pgp_copy_checksig (pgpout, s->fpout) >= 0)
564       badsig = 0;
565
566
567     m_fclose(&pgpout);
568     fflush (pgperr);
569     rewind (pgperr);
570
571     if (pgp_copy_checksig (pgperr, s->fpout) >= 0)
572       badsig = 0;
573
574     if ((rv = mutt_wait_filter (thepid)))
575       badsig = -1;
576   }
577
578   m_fclose(&pgperr);
579
580   state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
581
582   mutt_unlink (sigfile);
583   mutt_unlink (pgperrfile);
584
585   return badsig;
586 }
587
588
589 /* Extract pgp public keys from messages or attachments */
590
591 static void pgp_extract_keys_from_attachment (FILE * fp, BODY * top)
592 {
593   STATE s;
594   FILE *tempfp;
595   char tempfname[_POSIX_PATH_MAX];
596
597   tempfp = m_tempfile(tempfname, sizeof(tempfname), NONULL(MCore.tmpdir), NULL);
598   if (tempfp == NULL) {
599     mutt_perror (_("Can't create temporary file"));
600     return;
601   }
602
603   p_clear(&s, 1);
604
605   s.fpin = fp;
606   s.fpout = tempfp;
607
608   mutt_body_handler (top, &s);
609
610   m_fclose(&tempfp);
611
612   if (CRYPT_MOD_CALL_CHECK (PGP, pgp_invoke_import)) {
613     (CRYPT_MOD_CALL (PGP, pgp_invoke_import)) (fname);
614     mutt_any_key_to_continue (NULL);
615   }
616
617   mutt_unlink (tempfname);
618 }
619
620 void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top)
621 {
622   if (!fp) {
623     mutt_error _("Internal error. Inform <roessler@does-not-exist.org>.");
624
625     return;
626   }
627
628   mutt_endwin (NULL);
629   set_option (OPTDONTHANDLEPGPKEYS);
630
631   for (; top; top = top->next) {
632     if (!tag || top->tagged)
633       pgp_extract_keys_from_attachment (fp, top);
634
635     if (!tag)
636       break;
637   }
638
639   unset_option (OPTDONTHANDLEPGPKEYS);
640 }
641
642 BODY *pgp_decrypt_part (BODY * a, STATE * s, FILE * fpout, BODY * p)
643 {
644   char buf[LONG_STRING];
645   FILE *pgpin, *pgpout, *pgperr, *pgptmp;
646   struct stat info;
647   BODY *tattach;
648   int len;
649   char pgperrfile[_POSIX_PATH_MAX];
650   char pgptmpfile[_POSIX_PATH_MAX];
651   pid_t thepid;
652   int rv;
653
654   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL);
655   if (!pgperr) {
656     mutt_perror (pgperrfile);
657     return NULL;
658   }
659   unlink (pgperrfile);
660
661   pgptmp = m_tempfile(pgptmpfile, sizeof(pgptmpfile), NONULL(MCore.tmpdir), NULL);
662   if (!pgptmp) {
663     mutt_perror (pgptmpfile);
664     m_fclose(&pgperr);
665     return NULL;
666   }
667
668   /* Position the stream at the beginning of the body, and send the data to
669    * the temporary file.
670    */
671
672   fseeko (s->fpin, a->offset, 0);
673   mutt_copy_bytes (s->fpin, pgptmp, a->length);
674   m_fclose(&pgptmp);
675
676   if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1,
677                                     fileno (pgperr), pgptmpfile)) == -1) {
678     m_fclose(&pgperr);
679     unlink (pgptmpfile);
680     if (s->flags & M_DISPLAY)
681       state_attach_puts (_
682                          ("[-- Error: could not create a PGP subprocess! --]\n\n"),
683                          s);
684     return (NULL);
685   }
686
687   /* send the PGP passphrase to the subprocess.  Never do this if the
688      agent is active, because this might lead to a passphrase send as
689      the message. */
690   if (!pgp_use_gpg_agent ())
691     fputs (PgpPass, pgpin);
692   fputc ('\n', pgpin);
693   m_fclose(&pgpin);
694
695   /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
696    * read_mime_header has a hard time parsing the message.
697    */
698   while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL) {
699     len = m_strlen(buf);
700     if (len > 1 && buf[len - 2] == '\r')
701       m_strcpy(buf + len - 2, len - 2,  "\n");
702     fputs (buf, fpout);
703   }
704
705   m_fclose(&pgpout);
706   rv = mutt_wait_filter (thepid);
707   mutt_unlink (pgptmpfile);
708
709   if (s->flags & M_DISPLAY) {
710     fflush (pgperr);
711     rewind (pgperr);
712     if (pgp_copy_checksig (pgperr, s->fpout) == 0 && !rv && p)
713       p->goodsig = 1;
714     else
715       p->goodsig = 0;
716     state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
717   }
718   m_fclose(&pgperr);
719
720   fflush (fpout);
721   rewind (fpout);
722
723   if (fgetc (fpout) == EOF) {
724     mutt_error (_("Decryption failed."));
725     pgp_void_passphrase ();
726     return NULL;
727   }
728
729   rewind (fpout);
730
731   if ((tattach = mutt_read_mime_header (fpout, 0)) != NULL) {
732     /*
733      * Need to set the length of this body part.
734      */
735     fstat (fileno (fpout), &info);
736     tattach->length = info.st_size - tattach->offset;
737
738     /* See if we need to recurse on this MIME part.  */
739
740     mutt_parse_part (fpout, tattach);
741   }
742
743   return (tattach);
744 }
745
746 int pgp_decrypt_mime (FILE * fpin, FILE ** fpout, BODY * b, BODY ** cur)
747 {
748   char tempfile[_POSIX_PATH_MAX];
749   STATE s;
750   BODY *p = b;
751
752   if (!mutt_is_multipart_encrypted (b))
753     return -1;
754
755   if (!b->parts || !b->parts->next)
756     return -1;
757
758   b = b->parts->next;
759
760   p_clear(&s, 1);
761   s.fpin = fpin;
762   *fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
763   if (*fpout == NULL) {
764     mutt_perror (_("Can't create temporary file"));
765     return (-1);
766   }
767   unlink (tempfile);
768
769   *cur = pgp_decrypt_part (b, &s, *fpout, p);
770
771   rewind (*fpout);
772
773   if (!*cur)
774     return -1;
775
776   return (0);
777 }
778
779 int pgp_encrypted_handler (BODY * a, STATE * s)
780 {
781   char tempfile[_POSIX_PATH_MAX];
782   FILE *fpout, *fpin;
783   BODY *tattach;
784   BODY *p = a;
785   int rc = 0;
786
787   a = a->parts;
788   if (!a || a->type != TYPEAPPLICATION || !a->subtype ||
789       ascii_strcasecmp ("pgp-encrypted", a->subtype) != 0 ||
790       !a->next || a->next->type != TYPEAPPLICATION || !a->next->subtype ||
791       ascii_strcasecmp ("octet-stream", a->next->subtype) != 0) {
792     if (s->flags & M_DISPLAY)
793       state_attach_puts (_("[-- Error: malformed PGP/MIME message! --]\n\n"),
794                          s);
795     return (-1);
796   }
797
798   /*
799    * Move forward to the application/pgp-encrypted body.
800    */
801   a = a->next;
802
803   fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
804   if (fpout == NULL) {
805     if (s->flags & M_DISPLAY)
806       state_attach_puts (_
807                          ("[-- Error: could not create temporary file! --]\n"),
808                          s);
809     return (-1);
810   }
811
812   if (s->flags & M_DISPLAY)
813     crypt_current_time (s, "PGP");
814
815   if ((tattach = pgp_decrypt_part (a, s, fpout, p)) != NULL) {
816     if (s->flags & M_DISPLAY)
817       state_attach_puts (_
818                          ("[-- The following data is PGP/MIME encrypted --]\n\n"),
819                          s);
820
821     fpin = s->fpin;
822     s->fpin = fpout;
823     rc = mutt_body_handler (tattach, s);
824     s->fpin = fpin;
825
826     /* 
827      * if a multipart/signed is the _only_ sub-part of a
828      * multipart/encrypted, cache signature verification
829      * status.
830      *
831      */
832
833     if (mutt_is_multipart_signed (tattach) && !tattach->next)
834       p->goodsig |= tattach->goodsig;
835
836     if (s->flags & M_DISPLAY) {
837       state_puts ("\n", s);
838       state_attach_puts (_("[-- End of PGP/MIME encrypted data --]\n"), s);
839     }
840
841     body_list_wipe(&tattach);
842     /* clear 'Invoking...' message, since there's no error */
843     mutt_message _("PGP message successfully decrypted.");
844   } else {
845     mutt_error _("Could not decrypt PGP message");
846     pgp_void_passphrase ();
847     rc = -1;
848   }
849
850   m_fclose(&fpout);
851   mutt_unlink (tempfile);
852
853   return (rc);
854 }
855
856 /* ----------------------------------------------------------------------------
857  * Routines for sending PGP/MIME messages.
858  */
859
860
861 BODY *pgp_sign_message (BODY * a)
862 {
863   BODY *t;
864   char buffer[LONG_STRING];
865   char sigfile[_POSIX_PATH_MAX], signedfile[_POSIX_PATH_MAX];
866   FILE *pgpin, *pgpout, *pgperr, *fp, *sfp;
867   int err = 0;
868   int empty = 1;
869   pid_t thepid;
870
871   convert_to_7bit (a);          /* Signed data _must_ be in 7-bit format. */
872
873   fp = m_tempfile(sigfile, sizeof(sigfile), NONULL(MCore.tmpdir), NULL);
874   if (fp == NULL) {
875     return (NULL);
876   }
877
878   sfp = m_tempfile(signedfile, sizeof(signedfile), NONULL(MCore.tmpdir), NULL);
879   if (sfp == NULL) {
880     mutt_perror (signedfile);
881     m_fclose(&fp);
882     unlink (sigfile);
883     return NULL;
884   }
885
886   mutt_write_mime_header (a, sfp);
887   fputc ('\n', sfp);
888   mutt_write_mime_body (a, sfp);
889   m_fclose(&sfp);
890
891   if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr,
892                                  -1, -1, -1, signedfile)) == -1) {
893     mutt_perror (_("Can't open PGP subprocess!"));
894
895     m_fclose(&fp);
896     unlink (sigfile);
897     unlink (signedfile);
898     return NULL;
899   }
900
901   if (!pgp_use_gpg_agent ())
902     fputs (PgpPass, pgpin);
903   fputc ('\n', pgpin);
904   m_fclose(&pgpin);
905
906   /*
907    * Read back the PGP signature.  Also, change MESSAGE=>SIGNATURE as
908    * recommended for future releases of PGP.
909    */
910   while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL) {
911     if (m_strcmp("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
912       fputs ("-----BEGIN PGP SIGNATURE-----\n", fp);
913     else if (m_strcmp("-----END PGP MESSAGE-----\n", buffer) == 0)
914       fputs ("-----END PGP SIGNATURE-----\n", fp);
915     else
916       fputs (buffer, fp);
917     empty = 0;                  /* got some output, so we're ok */
918   }
919
920   /* check for errors from PGP */
921   err = 0;
922   while (fgets (buffer, sizeof (buffer) - 1, pgperr) != NULL) {
923     err = 1;
924     fputs (buffer, stdout);
925   }
926
927   if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT))
928     empty = 1;
929
930   m_fclose(&pgperr);
931   m_fclose(&pgpout);
932   unlink (signedfile);
933
934   if (m_fclose(&fp) != 0) {
935     mutt_perror ("fclose");
936     unlink (sigfile);
937     return (NULL);
938   }
939
940   if (err) {
941     pgp_void_passphrase ();
942     mutt_any_key_to_continue (NULL);
943   }
944
945   if (empty) {
946     unlink (sigfile);
947     return (NULL);              /* fatal error while signing */
948   }
949
950   t = body_new();
951   t->type = TYPEMULTIPART;
952   t->subtype = m_strdup("signed");
953   t->encoding = ENC7BIT;
954   t->use_disp = 0;
955   t->disposition = DISPINLINE;
956
957   parameter_set_boundary(&t->parameter);
958   parameter_setval(&t->parameter, "protocol", "application/pgp-signature");
959   parameter_setval(&t->parameter, "micalg", pgp_micalg (sigfile));
960
961   t->parts = a;
962   a = t;
963
964   t->parts->next = body_new();
965   t = t->parts->next;
966   t->type = TYPEAPPLICATION;
967   t->subtype = m_strdup("pgp-signature");
968   t->filename = m_strdup(sigfile);
969   t->use_disp = 0;
970   t->disposition = DISPINLINE;
971   t->encoding = ENC7BIT;
972   t->unlink = 1;                /* ok to remove this file after sending. */
973
974   return (a);
975 }
976
977 static short is_numerical_keyid (const char *s)
978 {
979   /* or should we require the "0x"? */
980   if (m_strncmp (s, "0x", 2) == 0)
981     s += 2;
982   if (m_strlen(s) % 8)
983     return 0;
984   while (*s)
985     if (strchr ("0123456789ABCDEFabcdef", *s++) == NULL)
986       return 0;
987
988   return 1;
989 }
990
991 /* This routine attempts to find the keyids of the recipients of a message.
992  * It returns NULL if any of the keys can not be found.
993  */
994 char *pgp_findKeys (address_t * to, address_t * cc, address_t * bcc)
995 {
996   char *keylist = NULL, *t;
997   const char *keyID;
998   size_t keylist_size = 0;
999   size_t keylist_used = 0;
1000   address_t *tmp = NULL, *addr = NULL;
1001   address_t **last = &tmp;
1002   address_t *p, *q;
1003   int i;
1004   pgp_key_t k_info = NULL, key = NULL;
1005
1006   const char *fqdn = mutt_fqdn (1);
1007
1008   for (i = 0; i < 3; i++) {
1009     switch (i) {
1010     case 0:
1011       p = to;
1012       break;
1013     case 1:
1014       p = cc;
1015       break;
1016     case 2:
1017       p = bcc;
1018       break;
1019     default:
1020       abort ();
1021     }
1022
1023     *last = address_list_dup (p);
1024     while (*last)
1025       last = &((*last)->next);
1026   }
1027
1028   rfc822_qualify (tmp, fqdn);
1029
1030   address_list_uniq(tmp);
1031
1032   for (p = tmp; p; p = p->next) {
1033     char buf[LONG_STRING];
1034
1035     q = p;
1036     k_info = NULL;
1037
1038     if ((keyID = mutt_crypt_hook (p)) != NULL) {
1039       int r;
1040
1041       snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID,
1042                 p->mailbox);
1043       if ((r = mutt_yesorno (buf, M_YES)) == M_YES) {
1044         if (is_numerical_keyid (keyID)) {
1045           if (m_strncmp (keyID, "0x", 2) == 0)
1046             keyID += 2;
1047           goto bypass_selection;        /* you don't see this. */
1048         }
1049
1050         /* check for e-mail address */
1051         if ((t = strchr (keyID, '@')) &&
1052             (addr = rfc822_parse_adrlist (NULL, keyID))) {
1053           rfc822_qualify (addr, fqdn);
1054           q = addr;
1055         }
1056         else
1057           k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
1058       }
1059       else if (r == -1) {
1060         p_delete(&keylist);
1061         address_list_wipe(&tmp);
1062         address_list_wipe(&addr);
1063         return NULL;
1064       }
1065     }
1066
1067     if (k_info == NULL)
1068       pgp_invoke_getkeys (q);
1069
1070     if (k_info == NULL
1071         && (k_info =
1072             pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) {
1073       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
1074
1075       if ((key = pgp_ask_for_key (buf, q->mailbox,
1076                                   KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL) {
1077         p_delete(&keylist);
1078         address_list_wipe(&tmp);
1079         address_list_wipe(&addr);
1080         return NULL;
1081       }
1082     }
1083     else
1084       key = k_info;
1085
1086     keyID = pgp_keyid (key);
1087
1088   bypass_selection:
1089     keylist_size += m_strlen(keyID) + 4;
1090     p_realloc(&keylist, keylist_size);
1091     sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "",
1092              keyID);
1093     keylist_used = m_strlen(keylist);
1094
1095     pgp_free_key (&key);
1096     address_list_wipe(&addr);
1097
1098   }
1099   address_list_wipe(&tmp);
1100   return (keylist);
1101 }
1102
1103 /* Warning: "a" is no longer freed in this routine, you need
1104  * to free it later.  This is necessary for $fcc_attach. */
1105
1106 BODY *pgp_encrypt_message (BODY * a, char *keylist, int sign)
1107 {
1108   char buf[LONG_STRING];
1109   char tempfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
1110   char pgpinfile[_POSIX_PATH_MAX];
1111   FILE *pgpin, *pgperr, *fpout, *fptmp;
1112   BODY *t;
1113   int err = 0;
1114   int empty = 0;
1115   pid_t thepid;
1116
1117   fpout = m_tempfile(tempfile, sizeof(tempfile), NONULL(MCore.tmpdir), NULL);
1118   if (fpout == NULL) {
1119     mutt_perror (_("Can't create temporary file"));
1120     return (NULL);
1121   }
1122
1123   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL);
1124   if (pgperr == NULL) {
1125     mutt_perror (pgperrfile);
1126     m_fclose(&fpout);
1127     unlink (tempfile);
1128     return NULL;
1129   }
1130   unlink (pgperrfile);
1131
1132   fptmp = m_tempfile(pgpinfile, sizeof(pgpinfile), NONULL(MCore.tmpdir), NULL);
1133   if (fptmp == NULL) {
1134     mutt_perror (pgpinfile);
1135     m_fclose(&fpout);
1136     unlink (tempfile);
1137     m_fclose(&pgperr);
1138     unlink (pgperrfile);
1139     return NULL;
1140   }
1141
1142   if (sign)
1143     convert_to_7bit (a);
1144
1145   mutt_write_mime_header (a, fptmp);
1146   fputc ('\n', fptmp);
1147   mutt_write_mime_body (a, fptmp);
1148   m_fclose(&fptmp);
1149
1150   if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1,
1151                                     fileno (fpout), fileno (pgperr),
1152                                     pgpinfile, keylist, sign)) == -1) {
1153     m_fclose(&pgperr);
1154     unlink (pgpinfile);
1155     return (NULL);
1156   }
1157
1158   if (sign) {
1159     if (!pgp_use_gpg_agent ())
1160       fputs (PgpPass, pgpin);
1161     fputc ('\n', pgpin);
1162   }
1163   m_fclose(&pgpin);
1164
1165   if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT))
1166     empty = 1;
1167
1168   unlink (pgpinfile);
1169
1170   fflush (fpout);
1171   rewind (fpout);
1172   if (!empty)
1173     empty = (fgetc (fpout) == EOF);
1174   m_fclose(&fpout);
1175
1176   fflush (pgperr);
1177   rewind (pgperr);
1178   while (fgets (buf, sizeof (buf) - 1, pgperr) != NULL) {
1179     err = 1;
1180     fputs (buf, stdout);
1181   }
1182   m_fclose(&pgperr);
1183
1184   /* pause if there is any error output from PGP */
1185   if (err)
1186     mutt_any_key_to_continue (NULL);
1187
1188   if (empty) {
1189     /* fatal error while trying to encrypt message */
1190     if (sign)
1191       pgp_void_passphrase (); /* just in case */
1192     unlink (tempfile);
1193     return (NULL);
1194   }
1195
1196   t = body_new();
1197   t->type = TYPEMULTIPART;
1198   t->subtype = m_strdup("encrypted");
1199   t->encoding = ENC7BIT;
1200   t->use_disp = 0;
1201   t->disposition = DISPINLINE;
1202
1203   parameter_set_boundary(&t->parameter);
1204   parameter_setval(&t->parameter, "protocol", "application/pgp-encrypted");
1205
1206   t->parts = body_new();
1207   t->parts->type = TYPEAPPLICATION;
1208   t->parts->subtype = m_strdup("pgp-encrypted");
1209   t->parts->encoding = ENC7BIT;
1210
1211   t->parts->next = body_new();
1212   t->parts->next->type = TYPEAPPLICATION;
1213   t->parts->next->subtype = m_strdup("octet-stream");
1214   t->parts->next->encoding = ENC7BIT;
1215   t->parts->next->filename = m_strdup(tempfile);
1216   t->parts->next->use_disp = 1;
1217   t->parts->next->disposition = DISPINLINE;
1218   t->parts->next->unlink = 1;   /* delete after sending the message */
1219   t->parts->next->d_filename = m_strdup("msg.asc"); /* non pgp/mime can save */
1220
1221   return (t);
1222 }
1223
1224 BODY *pgp_traditional_encryptsign (BODY * a, int flags, char *keylist)
1225 {
1226   BODY *b;
1227
1228   char pgpoutfile[_POSIX_PATH_MAX];
1229   char pgperrfile[_POSIX_PATH_MAX];
1230   char pgpinfile[_POSIX_PATH_MAX];
1231
1232   char body_charset[STRING];
1233   char *from_charset;
1234   const char *send_charset;
1235
1236   FILE *pgpout = NULL, *pgperr = NULL, *pgpin = NULL;
1237   FILE *fp;
1238
1239   int empty = 0;
1240   int err;
1241
1242   char buff[STRING];
1243
1244   pid_t thepid;
1245
1246   if (a->type != TYPETEXT)
1247     return NULL;
1248   if (ascii_strcasecmp (a->subtype, "plain"))
1249     return NULL;
1250
1251   if ((fp = fopen (a->filename, "r")) == NULL) {
1252     mutt_perror (a->filename);
1253     return NULL;
1254   }
1255
1256   pgpin = m_tempfile(pgpinfile, sizeof(pgpinfile), NONULL(MCore.tmpdir), NULL);
1257   if (pgpin == NULL) {
1258     mutt_perror (pgpinfile);
1259     m_fclose(&fp);
1260     return NULL;
1261   }
1262
1263   /* The following code is really correct:  If noconv is set,
1264    * a's charset parameter contains the on-disk character set, and
1265    * we have to convert from that to utf-8.  If noconv is not set,
1266    * we have to convert from $charset to utf-8.
1267    */
1268
1269   mutt_get_body_charset (body_charset, sizeof (body_charset), a);
1270   if (a->noconv)
1271     from_charset = body_charset;
1272   else
1273     from_charset = MCharset.charset;
1274
1275   if (!charset_is_us_ascii (body_charset)) {
1276     int c;
1277     fgetconv_t *fc;
1278
1279     if (flags & ENCRYPT)
1280       send_charset = "us-ascii";
1281     else
1282       send_charset = "utf-8";
1283
1284     fc = fgetconv_open (fp, from_charset, "utf-8", M_ICONV_HOOK_FROM);
1285     while ((c = fgetconv (fc)) != EOF)
1286       fputc (c, pgpin);
1287
1288     fgetconv_close (&fc);
1289   }
1290   else {
1291     send_charset = "us-ascii";
1292     mutt_copy_stream (fp, pgpin);
1293   }
1294   m_fclose(&fp);
1295   m_fclose(&pgpin);
1296
1297   pgpout = m_tempfile(pgpoutfile, sizeof(pgpoutfile), NONULL(MCore.tmpdir), NULL);
1298   pgperr = m_tempfile(pgperrfile, sizeof(pgperrfile), NONULL(MCore.tmpdir), NULL);
1299   if (pgpout == NULL || pgperr == NULL) {
1300     mutt_perror (pgpout ? pgperrfile : pgpoutfile);
1301     m_fclose(&pgpin);
1302     unlink (pgpinfile);
1303     m_fclose(&pgpout);
1304     unlink (pgpoutfile);
1305     m_fclose(&pgperr);
1306     unlink(pgperrfile);
1307     return NULL;
1308   }
1309
1310   unlink (pgperrfile);
1311
1312   if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL,
1313                                         -1, fileno (pgpout), fileno (pgperr),
1314                                         pgpinfile, keylist, flags)) == -1) {
1315     mutt_perror (_("Can't invoke PGP"));
1316
1317     m_fclose(&pgpout);
1318     m_fclose(&pgperr);
1319     mutt_unlink (pgpinfile);
1320     unlink (pgpoutfile);
1321     return NULL;
1322   }
1323
1324   if (pgp_use_gpg_agent ())
1325     *PgpPass = 0;
1326   if (flags & SIGN)
1327     fprintf (pgpin, "%s\n", PgpPass);
1328   m_fclose(&pgpin);
1329
1330   if (mutt_wait_filter (thepid) && option (OPTPGPCHECKEXIT))
1331     empty = 1;
1332
1333   mutt_unlink (pgpinfile);
1334
1335   fflush (pgpout);
1336   fflush (pgperr);
1337
1338   rewind (pgpout);
1339   rewind (pgperr);
1340
1341   if (!empty)
1342     empty = (fgetc (pgpout) == EOF);
1343   m_fclose(&pgpout);
1344
1345   err = 0;
1346
1347   while (fgets (buff, sizeof (buff), pgperr)) {
1348     err = 1;
1349     fputs (buff, stdout);
1350   }
1351
1352   m_fclose(&pgperr);
1353
1354   if (err)
1355     mutt_any_key_to_continue (NULL);
1356
1357   if (empty) {
1358     if (flags & SIGN)
1359       pgp_void_passphrase (); /* just in case */
1360     unlink (pgpoutfile);
1361     return NULL;
1362   }
1363
1364   b = body_new();
1365
1366   b->encoding = ENC7BIT;
1367
1368   b->type = TYPETEXT;
1369   b->subtype = m_strdup("plain");
1370
1371   parameter_setval(&b->parameter, "x-action",
1372                    flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed");
1373   parameter_setval(&b->parameter, "charset", send_charset);
1374
1375   b->filename = m_strdup(pgpoutfile);
1376
1377   b->disposition = DISPINLINE;
1378   b->unlink = 1;
1379
1380   b->noconv = 1;
1381   b->use_disp = 0;
1382
1383   if (!(flags & ENCRYPT))
1384     b->encoding = a->encoding;
1385
1386   return b;
1387 }
1388
1389 int pgp_send_menu (HEADER * msg, int *redraw)
1390 {
1391   pgp_key_t p;
1392   char input_signas[STRING];
1393
1394   char prompt[LONG_STRING];
1395
1396   /* If autoinline and no crypto options set, then set inline. */
1397   if (option (OPTPGPAUTOINLINE) && !((msg->security & APPLICATION_PGP)
1398                                      && (msg->security & (SIGN | ENCRYPT))))
1399     msg->security |= INLINE;
1400
1401   snprintf (prompt, sizeof (prompt),
1402             _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s, or (c)lear? "),
1403             (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline"));
1404
1405   switch (mutt_multi_choice (prompt, _("esabifc"))) {
1406   case 1:                      /* (e)ncrypt */
1407     msg->security |= ENCRYPT;
1408     msg->security &= ~SIGN;
1409     break;
1410
1411   case 2:                      /* (s)ign */
1412     msg->security |= SIGN;
1413     msg->security &= ~ENCRYPT;
1414     break;
1415
1416   case 3:                      /* sign (a)s */
1417     unset_option (OPTPGPCHECKTRUST);
1418
1419     if ((p =
1420          pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN,
1421                           PGP_PUBRING))) {
1422       snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p));
1423       m_strreplace(&PgpSignAs, input_signas);
1424       pgp_free_key (&p);
1425
1426       msg->security |= SIGN;
1427
1428       crypt_pgp_void_passphrase ();     /* probably need a different passphrase */
1429     }
1430
1431     *redraw = REDRAW_FULL;
1432     break;
1433
1434   case 4:                      /* (b)oth */
1435     msg->security |= (ENCRYPT | SIGN);
1436     break;
1437
1438   case 5:                      /* (i)nline */
1439     if ((msg->security & (ENCRYPT | SIGN)))
1440       msg->security ^= INLINE;
1441     else
1442       msg->security &= ~INLINE;
1443     break;
1444
1445   case 6:                      /* (f)orget it */
1446   case 7:                      /* (c)lear     */
1447     msg->security = 0;
1448     break;
1449   }
1450
1451   if (msg->security) {
1452     if (!(msg->security & (ENCRYPT | SIGN)))
1453       msg->security = 0;
1454     else
1455       msg->security |= APPLICATION_PGP;
1456   }
1457
1458   return (msg->security);
1459 }