mutt stable branch with some hacks
1/*
2 * Copyright (C) 1996-1997,2000,2010 Michael R. Elkins <me@mutt.org>
3 * Copyright (C) 1998-2005 Thomas Roessler <roessler@does-not-exist.org>
4 * Copyright (C) 2004 g10 Code GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21/*
22 * This file contains all of the PGP routines necessary to sign, encrypt,
23 * verify and decrypt PGP messages in either the new PGP/MIME format, or
24 * in the older Application/Pgp format. It also contains some code to
25 * cache the user's passphrase for repeat use when decrypting or signing
26 * a message.
27 */
28
29#if HAVE_CONFIG_H
30# include "config.h"
31#endif
32
33#include "mutt.h"
34#include "mutt_crypt.h"
35#include "mutt_curses.h"
36#include "pgp.h"
37#include "mime.h"
38#include "copy.h"
39
40#include <sys/wait.h>
41#include <string.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <sys/stat.h>
45#include <errno.h>
46#include <ctype.h>
47
48#ifdef HAVE_LOCALE_H
49#include <locale.h>
50#endif
51
52#ifdef HAVE_SYS_TIME_H
53# include <sys/time.h>
54#endif
55
56#ifdef HAVE_SYS_RESOURCE_H
57# include <sys/resource.h>
58#endif
59
60#ifdef CRYPT_BACKEND_CLASSIC_PGP
61
62#include "mutt_crypt.h"
63#include "mutt_menu.h"
64
65
66char PgpPass[LONG_STRING];
67time_t PgpExptime = 0; /* when does the cached passphrase expire? */
68
69void pgp_void_passphrase (void)
70{
71 memset (PgpPass, 0, sizeof (PgpPass));
72 PgpExptime = 0;
73}
74
75int pgp_valid_passphrase (void)
76{
77 time_t now = time (NULL);
78
79 if (pgp_use_gpg_agent())
80 {
81 *PgpPass = 0;
82 return 1; /* handled by gpg-agent */
83 }
84
85 if (now < PgpExptime)
86 /* Use cached copy. */
87 return 1;
88
89 pgp_void_passphrase ();
90
91 if (mutt_get_password (_("Enter PGP passphrase:"), PgpPass, sizeof (PgpPass)) == 0)
92 {
93 PgpExptime = time (NULL) + PgpTimeout;
94 return (1);
95 }
96 else
97 PgpExptime = 0;
98
99 return 0;
100}
101
102void pgp_forget_passphrase (void)
103{
104 pgp_void_passphrase ();
105 mutt_message _("PGP passphrase forgotten.");
106}
107
108int pgp_use_gpg_agent (void)
109{
110 char *tty;
111
112 /* GnuPG 2.1 no longer exports GPG_AGENT_INFO */
113 if (!option (OPTUSEGPGAGENT))
114 return 0;
115
116 if ((tty = ttyname(0)))
117 setenv("GPG_TTY", tty, 0);
118
119 return 1;
120}
121
122static pgp_key_t _pgp_parent(pgp_key_t k)
123{
124 if((k->flags & KEYFLAG_SUBKEY) && k->parent && option(OPTPGPIGNORESUB))
125 k = k->parent;
126
127 return k;
128}
129
130char *pgp_long_keyid(pgp_key_t k)
131{
132 k = _pgp_parent(k);
133
134 return k->keyid;
135}
136
137char *pgp_short_keyid(pgp_key_t k)
138{
139 k = _pgp_parent(k);
140
141 return k->keyid + 8;
142}
143
144char *pgp_keyid(pgp_key_t k)
145{
146 k = _pgp_parent(k);
147
148 return _pgp_keyid(k);
149}
150
151char *_pgp_keyid(pgp_key_t k)
152{
153 if(option(OPTPGPLONGIDS))
154 return k->keyid;
155 else
156 return (k->keyid + 8);
157}
158
159char *pgp_fingerprint(pgp_key_t k)
160{
161 k = _pgp_parent(k);
162
163 return k->fingerprint;
164}
165
166/* Grab the longest key identifier available: fingerprint or else
167 * the long keyid.
168 *
169 * The longest available should be used for internally identifying
170 * the key and for invoking pgp commands.
171 */
172char *pgp_fpr_or_lkeyid(pgp_key_t k)
173{
174 char *fingerprint;
175
176 fingerprint = pgp_fingerprint (k);
177 return fingerprint ? fingerprint : pgp_long_keyid (k);
178}
179
180/* ----------------------------------------------------------------------------
181 * Routines for handing PGP input.
182 */
183
184
185
186/* Copy PGP output messages and look for signs of a good signature */
187
188static int pgp_copy_checksig (FILE *fpin, FILE *fpout)
189{
190 int rv = -1;
191
192 if (PgpGoodSign.pattern)
193 {
194 char *line = NULL;
195 int lineno = 0;
196 size_t linelen;
197
198 while ((line = mutt_read_line (line, &linelen, fpin, &lineno, 0)) != NULL)
199 {
200 if (regexec (PgpGoodSign.rx, line, 0, NULL, 0) == 0)
201 {
202 dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" matches regexp.\n",
203 line));
204 rv = 0;
205 }
206 else
207 dprint (2, (debugfile, "pgp_copy_checksig: \"%s\" doesn't match regexp.\n",
208 line));
209
210 if (strncmp (line, "[GNUPG:] ", 9) == 0)
211 continue;
212 fputs (line, fpout);
213 fputc ('\n', fpout);
214 }
215 FREE (&line);
216 }
217 else
218 {
219 dprint (2, (debugfile, "pgp_copy_checksig: No pattern.\n"));
220 mutt_copy_stream (fpin, fpout);
221 rv = 1;
222 }
223
224 return rv;
225}
226
227/* Checks PGP output messages to look for the $pgp_decryption_okay message.
228 * This protects against messages with multipart/encrypted headers
229 * but which aren't actually encrypted. See ticket #3770
230 */
231static int pgp_check_decryption_okay (FILE *fpin)
232{
233 int rv = -1;
234
235 if (PgpDecryptionOkay.pattern)
236 {
237 char *line = NULL;
238 int lineno = 0;
239 size_t linelen;
240
241 while ((line = mutt_read_line (line, &linelen, fpin, &lineno, 0)) != NULL)
242 {
243 if (regexec (PgpDecryptionOkay.rx, line, 0, NULL, 0) == 0)
244 {
245 dprint (2, (debugfile, "pgp_check_decryption_okay: \"%s\" matches regexp.\n",
246 line));
247 rv = 0;
248 break;
249 }
250 else
251 dprint (2, (debugfile, "pgp_check_decryption_okay: \"%s\" doesn't match regexp.\n",
252 line));
253 }
254 FREE (&line);
255 }
256 else
257 {
258 dprint (2, (debugfile, "pgp_check_decryption_okay: No pattern.\n"));
259 rv = 1;
260 }
261
262 return rv;
263}
264
265
266/*
267 * Copy a clearsigned message, and strip the signature and PGP's
268 * dash-escaping.
269 *
270 * XXX - charset handling: We assume that it is safe to do
271 * character set decoding first, dash decoding second here, while
272 * we do it the other way around in the main handler.
273 *
274 * (Note that we aren't worse than Outlook &c in this, and also
275 * note that we can successfully handle anything produced by any
276 * existing versions of mutt.)
277 */
278
279static void pgp_copy_clearsigned (FILE *fpin, STATE *s, char *charset)
280{
281 char buf[HUGE_STRING];
282 short complete, armor_header;
283
284 FGETCONV *fc;
285
286 rewind (fpin);
287
288 /* fromcode comes from the MIME Content-Type charset label. It might
289 * be a wrong label, so we want the ability to do corrections via
290 * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM.
291 */
292 fc = fgetconv_open (fpin, charset, Charset, MUTT_ICONV_HOOK_FROM);
293
294 for (complete = 1, armor_header = 1;
295 fgetconvs (buf, sizeof (buf), fc) != NULL;
296 complete = strchr (buf, '\n') != NULL)
297 {
298 if (!complete)
299 {
300 if (!armor_header)
301 state_puts (buf, s);
302 continue;
303 }
304
305 if (mutt_strcmp (buf, "-----BEGIN PGP SIGNATURE-----\n") == 0)
306 break;
307
308 if (armor_header)
309 {
310 char *p = mutt_skip_whitespace (buf);
311 if (*p == '\0')
312 armor_header = 0;
313 continue;
314 }
315
316 if (s->prefix)
317 state_puts (s->prefix, s);
318
319 if (buf[0] == '-' && buf[1] == ' ')
320 state_puts (buf + 2, s);
321 else
322 state_puts (buf, s);
323 }
324
325 fgetconv_close (&fc);
326}
327
328
329/* Support for the Application/PGP Content Type. */
330
331int pgp_application_pgp_handler (BODY *m, STATE *s)
332{
333 int could_not_decrypt = 0;
334 int needpass = -1, pgp_keyblock = 0;
335 int clearsign = 0, rv, rc;
336 int c = 1; /* silence GCC warning */
337 long bytes;
338 LOFF_T last_pos, offset;
339 char buf[HUGE_STRING];
340 char outfile[_POSIX_PATH_MAX];
341 char tmpfname[_POSIX_PATH_MAX];
342 FILE *pgpout = NULL, *pgpin = NULL, *pgperr = NULL;
343 FILE *tmpfp = NULL;
344 pid_t thepid;
345
346 short maybe_goodsig = 1;
347 short have_any_sigs = 0;
348
349 char *gpgcharset = NULL;
350 char body_charset[STRING];
351 mutt_get_body_charset (body_charset, sizeof (body_charset), m);
352
353 rc = 0; /* silence false compiler warning if (s->flags & MUTT_DISPLAY) */
354
355 fseeko (s->fpin, m->offset, 0);
356 last_pos = m->offset;
357
358 for (bytes = m->length; bytes > 0;)
359 {
360 if (fgets (buf, sizeof (buf), s->fpin) == NULL)
361 break;
362
363 offset = ftello (s->fpin);
364 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
365 last_pos = offset;
366
367 if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)
368 {
369 clearsign = 0;
370
371 if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
372 needpass = 1;
373 else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
374 {
375 clearsign = 1;
376 needpass = 0;
377 }
378 else if (!mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15))
379 {
380 needpass = 0;
381 pgp_keyblock = 1;
382 }
383 else
384 {
385 /* XXX - we may wish to recode here */
386 if (s->prefix)
387 state_puts (s->prefix, s);
388 state_puts (buf, s);
389 continue;
390 }
391
392 have_any_sigs = have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY));
393
394 /* Copy PGP material to temporary file */
395 mutt_mktemp (tmpfname, sizeof (tmpfname));
396 if ((tmpfp = safe_fopen (tmpfname, "w+")) == NULL)
397 {
398 mutt_perror (tmpfname);
399 return -1;
400 }
401
402 fputs (buf, tmpfp);
403 while (bytes > 0 && fgets (buf, sizeof (buf) - 1, s->fpin) != NULL)
404 {
405 offset = ftello (s->fpin);
406 bytes -= (offset - last_pos); /* don't rely on mutt_strlen(buf) */
407 last_pos = offset;
408
409 fputs (buf, tmpfp);
410
411 if ((needpass && mutt_strcmp ("-----END PGP MESSAGE-----\n", buf) == 0) ||
412 (!needpass
413 && (mutt_strcmp ("-----END PGP SIGNATURE-----\n", buf) == 0
414 || mutt_strcmp ("-----END PGP PUBLIC KEY BLOCK-----\n",buf) == 0)))
415 break;
416 /* remember optional Charset: armor header as defined by RfC4880 */
417 if (mutt_strncmp ("Charset: ", buf, 9) == 0)
418 {
419 size_t l = 0;
420 gpgcharset = safe_strdup (buf + 9);
421 if ((l = mutt_strlen (gpgcharset)) > 0 && gpgcharset[l-1] == '\n')
422 gpgcharset[l-1] = 0;
423 if (mutt_check_charset (gpgcharset, 0) < 0)
424 mutt_str_replace (&gpgcharset, "UTF-8");
425 }
426 }
427
428 /* leave tmpfp open in case we still need it - but flush it! */
429 fflush (tmpfp);
430
431 /* Invoke PGP if needed */
432 if (!clearsign || (s->flags & MUTT_VERIFY))
433 {
434 mutt_mktemp (outfile, sizeof (outfile));
435 if ((pgpout = safe_fopen (outfile, "w+")) == NULL)
436 {
437 mutt_perror (outfile);
438 return -1;
439 }
440
441 if ((thepid = pgp_invoke_decode (&pgpin, NULL, &pgperr, -1,
442 fileno (pgpout), -1, tmpfname,
443 needpass)) == -1)
444 {
445 safe_fclose (&pgpout);
446 maybe_goodsig = 0;
447 pgpin = NULL;
448 pgperr = NULL;
449 state_attach_puts (_("[-- Error: unable to create PGP subprocess! --]\n"), s);
450 }
451 else /* PGP started successfully */
452 {
453 if (needpass)
454 {
455 if (!pgp_valid_passphrase ()) pgp_void_passphrase();
456 if (pgp_use_gpg_agent())
457 *PgpPass = 0;
458 fprintf (pgpin, "%s\n", PgpPass);
459 }
460
461 safe_fclose (&pgpin);
462
463 if (s->flags & MUTT_DISPLAY)
464 {
465 crypt_current_time (s, "PGP");
466 rc = pgp_copy_checksig (pgperr, s->fpout);
467 }
468
469 safe_fclose (&pgperr);
470 rv = mutt_wait_filter (thepid);
471
472 if (s->flags & MUTT_DISPLAY)
473 {
474 if (rc == 0) have_any_sigs = 1;
475 /*
476 * Sig is bad if
477 * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
478 * Sig _is_ correct if
479 * gpg_good_sign="" && pgp_decode_command returned 0
480 */
481 if (rc == -1 || rv) maybe_goodsig = 0;
482
483 state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
484 }
485 if (pgp_use_gpg_agent())
486 mutt_need_hard_redraw ();
487 }
488
489 /* treat empty result as sign of failure */
490 /* TODO: maybe on failure mutt should include the original undecoded text. */
491 if (pgpout)
492 {
493 rewind (pgpout);
494 c = fgetc (pgpout);
495 ungetc (c, pgpout);
496 }
497 if (!clearsign && (!pgpout || c == EOF))
498 {
499 could_not_decrypt = 1;
500 pgp_void_passphrase ();
501 }
502
503 if (could_not_decrypt && !(s->flags & MUTT_DISPLAY))
504 {
505 mutt_error _("Could not decrypt PGP message");
506 mutt_sleep (1);
507 rc = -1;
508 goto out;
509 }
510 }
511
512 /*
513 * Now, copy cleartext to the screen.
514 */
515
516 if(s->flags & MUTT_DISPLAY)
517 {
518 if (needpass)
519 state_attach_puts (_("[-- BEGIN PGP MESSAGE --]\n\n"), s);
520 else if (pgp_keyblock)
521 state_attach_puts (_("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"), s);
522 else
523 state_attach_puts (_("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"), s);
524 }
525
526 if (clearsign)
527 {
528 rewind (tmpfp);
529 if (tmpfp)
530 pgp_copy_clearsigned (tmpfp, s, body_charset);
531 }
532 else if (pgpout)
533 {
534 FGETCONV *fc;
535 int c;
536 char *expected_charset = gpgcharset && *gpgcharset ? gpgcharset : "utf-8";
537
538 dprint(4,(debugfile,"pgp: recoding inline from [%s] to [%s]\n",
539 expected_charset, Charset));
540
541 rewind (pgpout);
542 state_set_prefix (s);
543 fc = fgetconv_open (pgpout, expected_charset, Charset, MUTT_ICONV_HOOK_FROM);
544 while ((c = fgetconv (fc)) != EOF)
545 state_prefix_putc (c, s);
546 fgetconv_close (&fc);
547 }
548
549 /*
550 * Multiple PGP blocks can exist, so these need to be closed and
551 * unlinked inside the loop.
552 */
553 safe_fclose (&tmpfp);
554 mutt_unlink (tmpfname);
555 if (pgpout)
556 {
557 safe_fclose (&pgpout);
558 mutt_unlink (outfile);
559 }
560
561 if (s->flags & MUTT_DISPLAY)
562 {
563 state_putc ('\n', s);
564 if (needpass)
565 {
566 state_attach_puts (_("[-- END PGP MESSAGE --]\n"), s);
567 if (could_not_decrypt)
568 mutt_error _("Could not decrypt PGP message");
569 else
570 mutt_message _("PGP message successfully decrypted.");
571 }
572 else if (pgp_keyblock)
573 state_attach_puts (_("[-- END PGP PUBLIC KEY BLOCK --]\n"), s);
574 else
575 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
576 }
577 }
578 else
579 {
580 /* A traditional PGP part may mix signed and unsigned content */
581 /* XXX - we may wish to recode here */
582 if (s->prefix)
583 state_puts (s->prefix, s);
584 state_puts (buf, s);
585 }
586 }
587
588 rc = 0;
589
590out:
591 m->goodsig = (maybe_goodsig && have_any_sigs);
592
593 if (tmpfp)
594 {
595 safe_fclose (&tmpfp);
596 mutt_unlink (tmpfname);
597 }
598 if (pgpout)
599 {
600 safe_fclose (&pgpout);
601 mutt_unlink (outfile);
602 }
603
604 FREE(&gpgcharset);
605
606 if (needpass == -1)
607 {
608 state_attach_puts (_("[-- Error: could not find beginning of PGP message! --]\n\n"), s);
609 return -1;
610 }
611
612 return rc;
613}
614
615static int pgp_check_traditional_one_body (FILE *fp, BODY *b, int tagged_only)
616{
617 char tempfile[_POSIX_PATH_MAX];
618 char buf[HUGE_STRING];
619 FILE *tfp;
620
621 short sgn = 0;
622 short enc = 0;
623 short key = 0;
624
625 if (b->type != TYPETEXT)
626 return 0;
627
628 if (tagged_only && !b->tagged)
629 return 0;
630
631 mutt_mktemp (tempfile, sizeof (tempfile));
632 if (mutt_decode_save_attachment (fp, b, tempfile, 0, 0) != 0)
633 {
634 unlink (tempfile);
635 return 0;
636 }
637
638 if ((tfp = fopen (tempfile, "r")) == NULL)
639 {
640 unlink (tempfile);
641 return 0;
642 }
643
644 while (fgets (buf, sizeof (buf), tfp))
645 {
646 if (mutt_strncmp ("-----BEGIN PGP ", buf, 15) == 0)
647 {
648 if (mutt_strcmp ("MESSAGE-----\n", buf + 15) == 0)
649 enc = 1;
650 else if (mutt_strcmp ("SIGNED MESSAGE-----\n", buf + 15) == 0)
651 sgn = 1;
652 else if (mutt_strcmp ("PUBLIC KEY BLOCK-----\n", buf + 15) == 0)
653 key = 1;
654 }
655 }
656 safe_fclose (&tfp);
657 unlink (tempfile);
658
659 if (!enc && !sgn && !key)
660 return 0;
661
662 /* fix the content type */
663
664 mutt_set_parameter ("format", "fixed", &b->parameter);
665 if (enc)
666 mutt_set_parameter ("x-action", "pgp-encrypted", &b->parameter);
667 else if (sgn)
668 mutt_set_parameter ("x-action", "pgp-signed", &b->parameter);
669 else if (key)
670 mutt_set_parameter ("x-action", "pgp-keys", &b->parameter);
671
672 return 1;
673}
674
675int pgp_check_traditional (FILE *fp, BODY *b, int tagged_only)
676{
677 int rv = 0;
678 int r;
679 for (; b; b = b->next)
680 {
681 if (is_multipart (b))
682 rv = pgp_check_traditional (fp, b->parts, tagged_only) || rv;
683 else if (b->type == TYPETEXT)
684 {
685 if ((r = mutt_is_application_pgp (b)))
686 rv = rv || r;
687 else
688 rv = pgp_check_traditional_one_body (fp, b, tagged_only) || rv;
689 }
690 }
691
692 return rv;
693}
694
695
696
697
698
699int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
700{
701 char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
702 FILE *fp, *pgpout, *pgperr;
703 pid_t thepid;
704 int badsig = -1;
705 int rv;
706
707 snprintf (sigfile, sizeof (sigfile), "%s.asc", tempfile);
708
709 if(!(fp = safe_fopen (sigfile, "w")))
710 {
711 mutt_perror(sigfile);
712 return -1;
713 }
714
715 fseeko (s->fpin, sigbdy->offset, 0);
716 mutt_copy_bytes (s->fpin, fp, sigbdy->length);
717 safe_fclose (&fp);
718
719 mutt_mktemp (pgperrfile, sizeof (pgperrfile));
720 if(!(pgperr = safe_fopen(pgperrfile, "w+")))
721 {
722 mutt_perror(pgperrfile);
723 unlink(sigfile);
724 return -1;
725 }
726
727 crypt_current_time (s, "PGP");
728
729 if((thepid = pgp_invoke_verify (NULL, &pgpout, NULL,
730 -1, -1, fileno(pgperr),
731 tempfile, sigfile)) != -1)
732 {
733 if (pgp_copy_checksig (pgpout, s->fpout) >= 0)
734 badsig = 0;
735
736
737 safe_fclose (&pgpout);
738 fflush (pgperr);
739 rewind (pgperr);
740
741 if (pgp_copy_checksig (pgperr, s->fpout) >= 0)
742 badsig = 0;
743
744 if ((rv = mutt_wait_filter (thepid)))
745 badsig = -1;
746
747 dprint (1, (debugfile, "pgp_verify_one: mutt_wait_filter returned %d.\n", rv));
748 }
749
750 safe_fclose (&pgperr);
751
752 state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
753
754 mutt_unlink (sigfile);
755 mutt_unlink (pgperrfile);
756
757 dprint (1, (debugfile, "pgp_verify_one: returning %d.\n", badsig));
758
759 return badsig;
760}
761
762
763/* Extract pgp public keys from messages or attachments */
764
765void pgp_extract_keys_from_messages (HEADER *h)
766{
767 int i;
768 char tempfname[_POSIX_PATH_MAX];
769 FILE *fpout;
770
771 if (h)
772 {
773 mutt_parse_mime_message (Context, h);
774 if(h->security & PGPENCRYPT && !pgp_valid_passphrase ())
775 return;
776 }
777
778 mutt_mktemp (tempfname, sizeof (tempfname));
779 if (!(fpout = safe_fopen (tempfname, "w")))
780 {
781 mutt_perror (tempfname);
782 return;
783 }
784
785 set_option (OPTDONTHANDLEPGPKEYS);
786
787 if (!h)
788 {
789 for (i = 0; i < Context->vcount; i++)
790 {
791 if (Context->hdrs[Context->v2r[i]]->tagged)
792 {
793 mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]]);
794 if (Context->hdrs[Context->v2r[i]]->security & PGPENCRYPT
795 && !pgp_valid_passphrase())
796 {
797 safe_fclose (&fpout);
798 goto bailout;
799 }
800 mutt_copy_message (fpout, Context, Context->hdrs[Context->v2r[i]],
801 MUTT_CM_DECODE|MUTT_CM_CHARCONV, 0);
802 }
803 }
804 }
805 else
806 {
807 mutt_parse_mime_message (Context, h);
808 if (h->security & PGPENCRYPT && !pgp_valid_passphrase())
809 {
810 safe_fclose (&fpout);
811 goto bailout;
812 }
813 mutt_copy_message (fpout, Context, h, MUTT_CM_DECODE|MUTT_CM_CHARCONV, 0);
814 }
815
816 safe_fclose (&fpout);
817 mutt_endwin (NULL);
818 pgp_invoke_import (tempfname);
819 mutt_any_key_to_continue (NULL);
820
821 bailout:
822
823 mutt_unlink (tempfname);
824 unset_option (OPTDONTHANDLEPGPKEYS);
825
826}
827
828static void pgp_extract_keys_from_attachment (FILE *fp, BODY *top)
829{
830 STATE s;
831 FILE *tempfp;
832 char tempfname[_POSIX_PATH_MAX];
833
834 mutt_mktemp (tempfname, sizeof (tempfname));
835 if (!(tempfp = safe_fopen (tempfname, "w")))
836 {
837 mutt_perror (tempfname);
838 return;
839 }
840
841 memset (&s, 0, sizeof (STATE));
842
843 s.fpin = fp;
844 s.fpout = tempfp;
845
846 mutt_body_handler (top, &s);
847
848 safe_fclose (&tempfp);
849
850 pgp_invoke_import (tempfname);
851 mutt_any_key_to_continue (NULL);
852
853 mutt_unlink (tempfname);
854}
855
856void pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top)
857{
858 if(!fp)
859 {
860 mutt_error _("Internal error. Please submit a bug report.");
861 return;
862 }
863
864 mutt_endwin (NULL);
865 set_option(OPTDONTHANDLEPGPKEYS);
866
867 for(; top; top = top->next)
868 {
869 if(!tag || top->tagged)
870 pgp_extract_keys_from_attachment (fp, top);
871
872 if(!tag)
873 break;
874 }
875
876 unset_option(OPTDONTHANDLEPGPKEYS);
877}
878
879BODY *pgp_decrypt_part (BODY *a, STATE *s, FILE *fpout, BODY *p)
880{
881 char buf[LONG_STRING];
882 FILE *pgpin, *pgpout, *pgperr, *pgptmp;
883 struct stat info;
884 BODY *tattach;
885 int len;
886 char pgperrfile[_POSIX_PATH_MAX];
887 char pgptmpfile[_POSIX_PATH_MAX];
888 pid_t thepid;
889 int rv;
890
891 mutt_mktemp (pgperrfile, sizeof (pgperrfile));
892 if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
893 {
894 mutt_perror (pgperrfile);
895 return NULL;
896 }
897 unlink (pgperrfile);
898
899 mutt_mktemp (pgptmpfile, sizeof (pgptmpfile));
900 if((pgptmp = safe_fopen (pgptmpfile, "w")) == NULL)
901 {
902 mutt_perror (pgptmpfile);
903 safe_fclose (&pgperr);
904 return NULL;
905 }
906
907 /* Position the stream at the beginning of the body, and send the data to
908 * the temporary file.
909 */
910
911 fseeko (s->fpin, a->offset, 0);
912 mutt_copy_bytes (s->fpin, pgptmp, a->length);
913 safe_fclose (&pgptmp);
914
915 if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1,
916 fileno (pgperr), pgptmpfile)) == -1)
917 {
918 safe_fclose (&pgperr);
919 unlink (pgptmpfile);
920 if (s->flags & MUTT_DISPLAY)
921 state_attach_puts (_("[-- Error: could not create a PGP subprocess! --]\n\n"), s);
922 return (NULL);
923 }
924
925 /* send the PGP passphrase to the subprocess. Never do this if the
926 agent is active, because this might lead to a passphrase send as
927 the message. */
928 if (!pgp_use_gpg_agent())
929 fputs (PgpPass, pgpin);
930 fputc ('\n', pgpin);
931 safe_fclose (&pgpin);
932
933 /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
934 * read_mime_header has a hard time parsing the message.
935 */
936 while (fgets (buf, sizeof (buf) - 1, pgpout) != NULL)
937 {
938 len = mutt_strlen (buf);
939 if (len > 1 && buf[len - 2] == '\r')
940 strcpy (buf + len - 2, "\n"); /* __STRCPY_CHECKED__ */
941 fputs (buf, fpout);
942 }
943
944 safe_fclose (&pgpout);
945 rv = mutt_wait_filter (thepid);
946 mutt_unlink(pgptmpfile);
947
948 fflush (pgperr);
949 rewind (pgperr);
950 if (pgp_check_decryption_okay (pgperr) < 0)
951 {
952 mutt_error _("Decryption failed");
953 pgp_void_passphrase ();
954 return NULL;
955 }
956
957 if (s->flags & MUTT_DISPLAY)
958 {
959 rewind (pgperr);
960 if (pgp_copy_checksig (pgperr, s->fpout) == 0 && !rv && p)
961 p->goodsig = 1;
962 else
963 p->goodsig = 0;
964 state_attach_puts (_("[-- End of PGP output --]\n\n"), s);
965 }
966 safe_fclose (&pgperr);
967
968 fflush (fpout);
969 rewind (fpout);
970
971 if (pgp_use_gpg_agent())
972 mutt_need_hard_redraw ();
973
974 if (fgetc (fpout) == EOF)
975 {
976 mutt_error _("Decryption failed");
977 pgp_void_passphrase ();
978 return NULL;
979 }
980
981 rewind (fpout);
982
983 if ((tattach = mutt_read_mime_header (fpout, 0)) != NULL)
984 {
985 /*
986 * Need to set the length of this body part.
987 */
988 fstat (fileno (fpout), &info);
989 tattach->length = info.st_size - tattach->offset;
990
991 /* See if we need to recurse on this MIME part. */
992
993 mutt_parse_part (fpout, tattach);
994 }
995
996 return (tattach);
997}
998
999int pgp_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
1000{
1001 char tempfile[_POSIX_PATH_MAX];
1002 STATE s;
1003 BODY *p = b;
1004 int need_decode = 0;
1005 int saved_type;
1006 LOFF_T saved_offset;
1007 size_t saved_length;
1008 FILE *decoded_fp = NULL;
1009 int rv = 0;
1010
1011 if (mutt_is_valid_multipart_pgp_encrypted (b))
1012 b = b->parts->next;
1013 else if (mutt_is_malformed_multipart_pgp_encrypted (b))
1014 {
1015 b = b->parts->next->next;
1016 need_decode = 1;
1017 }
1018 else
1019 return -1;
1020
1021 memset (&s, 0, sizeof (s));
1022 s.fpin = fpin;
1023
1024 if (need_decode)
1025 {
1026 saved_type = b->type;
1027 saved_offset = b->offset;
1028 saved_length = b->length;
1029
1030 mutt_mktemp (tempfile, sizeof (tempfile));
1031 if ((decoded_fp = safe_fopen (tempfile, "w+")) == NULL)
1032 {
1033 mutt_perror (tempfile);
1034 return (-1);
1035 }
1036 unlink (tempfile);
1037
1038 fseeko (s.fpin, b->offset, 0);
1039 s.fpout = decoded_fp;
1040
1041 mutt_decode_attachment (b, &s);
1042
1043 fflush (decoded_fp);
1044 b->length = ftello (decoded_fp);
1045 b->offset = 0;
1046 rewind (decoded_fp);
1047 s.fpin = decoded_fp;
1048 s.fpout = 0;
1049 }
1050
1051 mutt_mktemp (tempfile, sizeof (tempfile));
1052 if ((*fpout = safe_fopen (tempfile, "w+")) == NULL)
1053 {
1054 mutt_perror (tempfile);
1055 rv = -1;
1056 goto bail;
1057 }
1058 unlink (tempfile);
1059
1060 if ((*cur = pgp_decrypt_part (b, &s, *fpout, p)) == NULL)
1061 rv = -1;
1062 rewind (*fpout);
1063
1064bail:
1065 if (need_decode)
1066 {
1067 b->type = saved_type;
1068 b->length = saved_length;
1069 b->offset = saved_offset;
1070 safe_fclose (&decoded_fp);
1071 }
1072
1073 return rv;
1074}
1075
1076/*
1077 * This handler is passed the application/octet-stream directly.
1078 * The caller must propagate a->goodsig to its parent.
1079 */
1080int pgp_encrypted_handler (BODY *a, STATE *s)
1081{
1082 char tempfile[_POSIX_PATH_MAX];
1083 FILE *fpout, *fpin;
1084 BODY *tattach;
1085 int rc = 0;
1086
1087 mutt_mktemp (tempfile, sizeof (tempfile));
1088 if ((fpout = safe_fopen (tempfile, "w+")) == NULL)
1089 {
1090 if (s->flags & MUTT_DISPLAY)
1091 state_attach_puts (_("[-- Error: could not create temporary file! --]\n"), s);
1092 return -1;
1093 }
1094
1095 if (s->flags & MUTT_DISPLAY) crypt_current_time (s, "PGP");
1096
1097 if ((tattach = pgp_decrypt_part (a, s, fpout, a)) != NULL)
1098 {
1099 if (s->flags & MUTT_DISPLAY)
1100 state_attach_puts (_("[-- The following data is PGP/MIME encrypted --]\n\n"), s);
1101
1102 fpin = s->fpin;
1103 s->fpin = fpout;
1104 rc = mutt_body_handler (tattach, s);
1105 s->fpin = fpin;
1106
1107 /*
1108 * if a multipart/signed is the _only_ sub-part of a
1109 * multipart/encrypted, cache signature verification
1110 * status.
1111 *
1112 */
1113
1114 if (mutt_is_multipart_signed (tattach) && !tattach->next)
1115 a->goodsig |= tattach->goodsig;
1116
1117 if (s->flags & MUTT_DISPLAY)
1118 {
1119 state_puts ("\n", s);
1120 state_attach_puts (_("[-- End of PGP/MIME encrypted data --]\n"), s);
1121 }
1122
1123 mutt_free_body (&tattach);
1124 /* clear 'Invoking...' message, since there's no error */
1125 mutt_message _("PGP message successfully decrypted.");
1126 }
1127 else
1128 {
1129 mutt_error _("Could not decrypt PGP message");
1130 mutt_sleep (2);
1131 /* void the passphrase, even if it's not necessarily the problem */
1132 pgp_void_passphrase ();
1133 rc = -1;
1134 }
1135
1136 safe_fclose (&fpout);
1137 mutt_unlink(tempfile);
1138
1139 return rc;
1140}
1141
1142/* ----------------------------------------------------------------------------
1143 * Routines for sending PGP/MIME messages.
1144 */
1145
1146
1147BODY *pgp_sign_message (BODY *a)
1148{
1149 BODY *t;
1150 char buffer[LONG_STRING];
1151 char sigfile[_POSIX_PATH_MAX], signedfile[_POSIX_PATH_MAX];
1152 FILE *pgpin, *pgpout, *pgperr, *fp, *sfp;
1153 int err = 0;
1154 int empty = 1;
1155 pid_t thepid;
1156
1157 convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
1158
1159 mutt_mktemp (sigfile, sizeof (sigfile));
1160 if ((fp = safe_fopen (sigfile, "w")) == NULL)
1161 {
1162 return (NULL);
1163 }
1164
1165 mutt_mktemp (signedfile, sizeof (signedfile));
1166 if ((sfp = safe_fopen(signedfile, "w")) == NULL)
1167 {
1168 mutt_perror(signedfile);
1169 safe_fclose (&fp);
1170 unlink(sigfile);
1171 return NULL;
1172 }
1173
1174 mutt_write_mime_header (a, sfp);
1175 fputc ('\n', sfp);
1176 mutt_write_mime_body (a, sfp);
1177 safe_fclose (&sfp);
1178
1179 if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr,
1180 -1, -1, -1, signedfile)) == -1)
1181 {
1182 mutt_perror _("Can't open PGP subprocess!");
1183 safe_fclose (&fp);
1184 unlink(sigfile);
1185 unlink(signedfile);
1186 return NULL;
1187 }
1188
1189 if (!pgp_use_gpg_agent())
1190 fputs(PgpPass, pgpin);
1191 fputc('\n', pgpin);
1192 safe_fclose (&pgpin);
1193
1194 /*
1195 * Read back the PGP signature. Also, change MESSAGE=>SIGNATURE as
1196 * recommended for future releases of PGP.
1197 */
1198 while (fgets (buffer, sizeof (buffer) - 1, pgpout) != NULL)
1199 {
1200 if (mutt_strcmp ("-----BEGIN PGP MESSAGE-----\n", buffer) == 0)
1201 fputs ("-----BEGIN PGP SIGNATURE-----\n", fp);
1202 else if (mutt_strcmp("-----END PGP MESSAGE-----\n", buffer) == 0)
1203 fputs ("-----END PGP SIGNATURE-----\n", fp);
1204 else
1205 fputs (buffer, fp);
1206 empty = 0; /* got some output, so we're ok */
1207 }
1208
1209 /* check for errors from PGP */
1210 err = 0;
1211 while (fgets (buffer, sizeof (buffer) - 1, pgperr) != NULL)
1212 {
1213 err = 1;
1214 fputs (buffer, stdout);
1215 }
1216
1217 if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1218 empty=1;
1219
1220 safe_fclose (&pgperr);
1221 safe_fclose (&pgpout);
1222 unlink (signedfile);
1223
1224 if (fclose (fp) != 0)
1225 {
1226 mutt_perror ("fclose");
1227 unlink (sigfile);
1228 return (NULL);
1229 }
1230
1231 if (err)
1232 mutt_any_key_to_continue (NULL);
1233 if (empty)
1234 {
1235 unlink (sigfile);
1236 /* most likely error is a bad passphrase, so automatically forget it */
1237 pgp_void_passphrase ();
1238 return (NULL); /* fatal error while signing */
1239 }
1240
1241 t = mutt_new_body ();
1242 t->type = TYPEMULTIPART;
1243 t->subtype = safe_strdup ("signed");
1244 t->encoding = ENC7BIT;
1245 t->use_disp = 0;
1246 t->disposition = DISPINLINE;
1247
1248 mutt_generate_boundary (&t->parameter);
1249 mutt_set_parameter ("protocol", "application/pgp-signature", &t->parameter);
1250 mutt_set_parameter ("micalg", pgp_micalg (sigfile), &t->parameter);
1251
1252 t->parts = a;
1253 a = t;
1254
1255 t->parts->next = mutt_new_body ();
1256 t = t->parts->next;
1257 t->type = TYPEAPPLICATION;
1258 t->subtype = safe_strdup ("pgp-signature");
1259 t->filename = safe_strdup (sigfile);
1260 t->use_disp = 0;
1261 t->disposition = DISPNONE;
1262 t->encoding = ENC7BIT;
1263 t->unlink = 1; /* ok to remove this file after sending. */
1264 mutt_set_parameter ("name", "signature.asc", &t->parameter);
1265
1266 return (a);
1267}
1268
1269/* This routine attempts to find the keyids of the recipients of a message.
1270 * It returns NULL if any of the keys can not be found.
1271 * If oppenc_mode is true, only keys that can be determined without
1272 * prompting will be used.
1273 */
1274char *pgp_findKeys (ADDRESS *adrlist, int oppenc_mode)
1275{
1276 LIST *crypt_hook_list, *crypt_hook = NULL;
1277 char *keyID, *keylist = NULL;
1278 size_t keylist_size = 0;
1279 size_t keylist_used = 0;
1280 ADDRESS *addr = NULL;
1281 ADDRESS *p, *q;
1282 pgp_key_t k_info = NULL;
1283 char buf[LONG_STRING];
1284 int r;
1285 int key_selected;
1286
1287 const char *fqdn = mutt_fqdn (1);
1288
1289 for (p = adrlist; p ; p = p->next)
1290 {
1291 key_selected = 0;
1292 crypt_hook_list = crypt_hook = mutt_crypt_hook (p);
1293 do
1294 {
1295 q = p;
1296 k_info = NULL;
1297
1298 if (crypt_hook != NULL)
1299 {
1300 keyID = crypt_hook->data;
1301 r = MUTT_YES;
1302 if (! oppenc_mode && option(OPTCRYPTCONFIRMHOOK))
1303 {
1304 snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
1305 r = mutt_yesorno (buf, MUTT_YES);
1306 }
1307 if (r == MUTT_YES)
1308 {
1309 if (crypt_is_numerical_keyid (keyID))
1310 {
1311 if (strncmp (keyID, "0x", 2) == 0)
1312 keyID += 2;
1313 goto bypass_selection; /* you don't see this. */
1314 }
1315
1316 /* check for e-mail address */
1317 if (strchr (keyID, '@') &&
1318 (addr = rfc822_parse_adrlist (NULL, keyID)))
1319 {
1320 if (fqdn) rfc822_qualify (addr, fqdn);
1321 q = addr;
1322 }
1323 else if (! oppenc_mode)
1324 {
1325 k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
1326 }
1327 }
1328 else if (r == MUTT_NO)
1329 {
1330 if (key_selected || (crypt_hook->next != NULL))
1331 {
1332 crypt_hook = crypt_hook->next;
1333 continue;
1334 }
1335 }
1336 else if (r == -1)
1337 {
1338 FREE (&keylist);
1339 rfc822_free_address (&addr);
1340 mutt_free_list (&crypt_hook_list);
1341 return NULL;
1342 }
1343 }
1344
1345 if (k_info == NULL)
1346 {
1347 pgp_invoke_getkeys (q);
1348 k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING, oppenc_mode);
1349 }
1350
1351 if ((k_info == NULL) && (! oppenc_mode))
1352 {
1353 snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
1354 k_info = pgp_ask_for_key (buf, q->mailbox,
1355 KEYFLAG_CANENCRYPT, PGP_PUBRING);
1356 }
1357
1358 if (k_info == NULL)
1359 {
1360 FREE (&keylist);
1361 rfc822_free_address (&addr);
1362 mutt_free_list (&crypt_hook_list);
1363 return NULL;
1364 }
1365
1366 keyID = pgp_fpr_or_lkeyid (k_info);
1367
1368 bypass_selection:
1369 keylist_size += mutt_strlen (keyID) + 4;
1370 safe_realloc (&keylist, keylist_size);
1371 sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", /* __SPRINTF_CHECKED__ */
1372 keyID);
1373 keylist_used = mutt_strlen (keylist);
1374
1375 key_selected = 1;
1376
1377 pgp_free_key (&k_info);
1378 rfc822_free_address (&addr);
1379
1380 if (crypt_hook != NULL)
1381 crypt_hook = crypt_hook->next;
1382
1383 } while (crypt_hook != NULL);
1384
1385 mutt_free_list (&crypt_hook_list);
1386 }
1387 return (keylist);
1388}
1389
1390/* Warning: "a" is no longer freed in this routine, you need
1391 * to free it later. This is necessary for $fcc_attach. */
1392
1393BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign)
1394{
1395 char buf[LONG_STRING];
1396 char tempfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
1397 char pgpinfile[_POSIX_PATH_MAX];
1398 FILE *pgpin, *pgperr, *fpout, *fptmp;
1399 BODY *t;
1400 int err = 0;
1401 int empty = 0;
1402 pid_t thepid;
1403
1404 mutt_mktemp (tempfile, sizeof (tempfile));
1405 if ((fpout = safe_fopen (tempfile, "w+")) == NULL)
1406 {
1407 mutt_perror (tempfile);
1408 return (NULL);
1409 }
1410
1411 mutt_mktemp (pgperrfile, sizeof (pgperrfile));
1412 if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
1413 {
1414 mutt_perror (pgperrfile);
1415 unlink(tempfile);
1416 safe_fclose (&fpout);
1417 return NULL;
1418 }
1419 unlink (pgperrfile);
1420
1421 mutt_mktemp (pgpinfile, sizeof (pgpinfile));
1422 if((fptmp = safe_fopen(pgpinfile, "w")) == NULL)
1423 {
1424 mutt_perror(pgpinfile);
1425 unlink(tempfile);
1426 safe_fclose (&fpout);
1427 safe_fclose (&pgperr);
1428 return NULL;
1429 }
1430
1431 if (sign)
1432 convert_to_7bit (a);
1433
1434 mutt_write_mime_header (a, fptmp);
1435 fputc ('\n', fptmp);
1436 mutt_write_mime_body (a, fptmp);
1437 safe_fclose (&fptmp);
1438
1439 if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1,
1440 fileno (fpout), fileno (pgperr),
1441 pgpinfile, keylist, sign)) == -1)
1442 {
1443 safe_fclose (&pgperr);
1444 unlink(pgpinfile);
1445 return (NULL);
1446 }
1447
1448 if (sign)
1449 {
1450 if (!pgp_use_gpg_agent())
1451 fputs (PgpPass, pgpin);
1452 fputc ('\n', pgpin);
1453 }
1454 safe_fclose (&pgpin);
1455
1456 if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1457 empty=1;
1458
1459 unlink(pgpinfile);
1460
1461 fflush (fpout);
1462 rewind (fpout);
1463 if(!empty)
1464 empty = (fgetc (fpout) == EOF);
1465 safe_fclose (&fpout);
1466
1467 fflush (pgperr);
1468 rewind (pgperr);
1469 while (fgets (buf, sizeof (buf) - 1, pgperr) != NULL)
1470 {
1471 err = 1;
1472 fputs (buf, stdout);
1473 }
1474 safe_fclose (&pgperr);
1475
1476 /* pause if there is any error output from PGP */
1477 if (err)
1478 mutt_any_key_to_continue (NULL);
1479
1480 if (empty)
1481 {
1482 /* fatal error while trying to encrypt message */
1483 if (sign)
1484 pgp_void_passphrase (); /* just in case */
1485 unlink (tempfile);
1486 return (NULL);
1487 }
1488
1489 t = mutt_new_body ();
1490 t->type = TYPEMULTIPART;
1491 t->subtype = safe_strdup ("encrypted");
1492 t->encoding = ENC7BIT;
1493 t->use_disp = 0;
1494 t->disposition = DISPINLINE;
1495
1496 mutt_generate_boundary(&t->parameter);
1497 mutt_set_parameter("protocol", "application/pgp-encrypted", &t->parameter);
1498
1499 t->parts = mutt_new_body ();
1500 t->parts->type = TYPEAPPLICATION;
1501 t->parts->subtype = safe_strdup ("pgp-encrypted");
1502 t->parts->encoding = ENC7BIT;
1503
1504 t->parts->next = mutt_new_body ();
1505 t->parts->next->type = TYPEAPPLICATION;
1506 t->parts->next->subtype = safe_strdup ("octet-stream");
1507 t->parts->next->encoding = ENC7BIT;
1508 t->parts->next->filename = safe_strdup (tempfile);
1509 t->parts->next->use_disp = 1;
1510 t->parts->next->disposition = DISPATTACH;
1511 t->parts->next->unlink = 1; /* delete after sending the message */
1512 t->parts->next->d_filename = safe_strdup ("msg.asc"); /* non pgp/mime can save */
1513
1514 return (t);
1515}
1516
1517BODY *pgp_traditional_encryptsign (BODY *a, int flags, char *keylist)
1518{
1519 BODY *b;
1520
1521 char pgpoutfile[_POSIX_PATH_MAX];
1522 char pgperrfile[_POSIX_PATH_MAX];
1523 char pgpinfile[_POSIX_PATH_MAX];
1524
1525 char body_charset[STRING];
1526 char *from_charset;
1527 const char *send_charset;
1528
1529 FILE *pgpout = NULL, *pgperr = NULL, *pgpin = NULL;
1530 FILE *fp;
1531
1532 int empty = 0;
1533 int err;
1534
1535 char buff[STRING];
1536
1537 pid_t thepid;
1538
1539 if (a->type != TYPETEXT)
1540 return NULL;
1541 if (ascii_strcasecmp (a->subtype, "plain"))
1542 return NULL;
1543
1544 if ((fp = fopen (a->filename, "r")) == NULL)
1545 {
1546 mutt_perror (a->filename);
1547 return NULL;
1548 }
1549
1550 mutt_mktemp (pgpinfile, sizeof (pgpinfile));
1551 if ((pgpin = safe_fopen (pgpinfile, "w")) == NULL)
1552 {
1553 mutt_perror (pgpinfile);
1554 safe_fclose (&fp);
1555 return NULL;
1556 }
1557
1558 /* The following code is really correct: If noconv is set,
1559 * a's charset parameter contains the on-disk character set, and
1560 * we have to convert from that to utf-8. If noconv is not set,
1561 * we have to convert from $charset to utf-8.
1562 */
1563
1564 mutt_get_body_charset (body_charset, sizeof (body_charset), a);
1565 if (a->noconv)
1566 from_charset = body_charset;
1567 else
1568 from_charset = Charset;
1569
1570 if (!mutt_is_us_ascii (body_charset))
1571 {
1572 int c;
1573 FGETCONV *fc;
1574
1575 if (flags & ENCRYPT)
1576 send_charset = "us-ascii";
1577 else
1578 send_charset = "utf-8";
1579
1580 /* fromcode is assumed to be correct: we set flags to 0 */
1581 fc = fgetconv_open (fp, from_charset, "utf-8", 0);
1582 while ((c = fgetconv (fc)) != EOF)
1583 fputc (c, pgpin);
1584
1585 fgetconv_close (&fc);
1586 }
1587 else
1588 {
1589 send_charset = "us-ascii";
1590 mutt_copy_stream (fp, pgpin);
1591 }
1592 safe_fclose (&fp);
1593 safe_fclose (&pgpin);
1594
1595 mutt_mktemp (pgpoutfile, sizeof (pgpoutfile));
1596 mutt_mktemp (pgperrfile, sizeof (pgperrfile));
1597 if ((pgpout = safe_fopen (pgpoutfile, "w+")) == NULL ||
1598 (pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
1599 {
1600 mutt_perror (pgpout ? pgperrfile : pgpoutfile);
1601 unlink (pgpinfile);
1602 if (pgpout)
1603 {
1604 safe_fclose (&pgpout);
1605 unlink (pgpoutfile);
1606 }
1607 return NULL;
1608 }
1609
1610 unlink (pgperrfile);
1611
1612 if ((thepid = pgp_invoke_traditional (&pgpin, NULL, NULL,
1613 -1, fileno (pgpout), fileno (pgperr),
1614 pgpinfile, keylist, flags)) == -1)
1615 {
1616 mutt_perror _("Can't invoke PGP");
1617 safe_fclose (&pgpout);
1618 safe_fclose (&pgperr);
1619 mutt_unlink (pgpinfile);
1620 unlink (pgpoutfile);
1621 return NULL;
1622 }
1623
1624 if (pgp_use_gpg_agent())
1625 *PgpPass = 0;
1626 if (flags & SIGN)
1627 fprintf (pgpin, "%s\n", PgpPass);
1628 safe_fclose (&pgpin);
1629
1630 if(mutt_wait_filter (thepid) && option(OPTPGPCHECKEXIT))
1631 empty=1;
1632
1633 mutt_unlink (pgpinfile);
1634
1635 fflush (pgpout);
1636 fflush (pgperr);
1637
1638 rewind (pgpout);
1639 rewind (pgperr);
1640
1641 if(!empty)
1642 empty = (fgetc (pgpout) == EOF);
1643 safe_fclose (&pgpout);
1644
1645 err = 0;
1646
1647 while (fgets (buff, sizeof (buff), pgperr))
1648 {
1649 err = 1;
1650 fputs (buff, stdout);
1651 }
1652
1653 safe_fclose (&pgperr);
1654
1655 if (err)
1656 mutt_any_key_to_continue (NULL);
1657
1658 if (empty)
1659 {
1660 if (flags & SIGN)
1661 pgp_void_passphrase (); /* just in case */
1662 unlink (pgpoutfile);
1663 return NULL;
1664 }
1665
1666 b = mutt_new_body ();
1667
1668 b->encoding = ENC7BIT;
1669
1670 b->type = TYPETEXT;
1671 b->subtype = safe_strdup ("plain");
1672
1673 mutt_set_parameter ("x-action", flags & ENCRYPT ? "pgp-encrypted" : "pgp-signed",
1674 &b->parameter);
1675 mutt_set_parameter ("charset", send_charset, &b->parameter);
1676
1677 b->filename = safe_strdup (pgpoutfile);
1678
1679#if 0
1680 /* The following is intended to give a clue to some completely brain-dead
1681 * "mail environments" which are typically used by large corporations.
1682 */
1683
1684 b->d_filename = safe_strdup ("msg.pgp");
1685 b->use_disp = 1;
1686
1687#endif
1688
1689 b->disposition = DISPNONE;
1690 b->unlink = 1;
1691
1692 b->noconv = 1;
1693 b->use_disp = 0;
1694
1695 if (!(flags & ENCRYPT))
1696 b->encoding = a->encoding;
1697
1698 return b;
1699}
1700
1701int pgp_send_menu (HEADER *msg, int *redraw)
1702{
1703 pgp_key_t p;
1704 char input_signas[SHORT_STRING];
1705 char *prompt, *letters, *choices;
1706 char promptbuf[LONG_STRING];
1707 int choice;
1708
1709 if (!(WithCrypto & APPLICATION_PGP))
1710 return msg->security;
1711
1712 /* If autoinline and no crypto options set, then set inline. */
1713 if (option (OPTPGPAUTOINLINE) &&
1714 !((msg->security & APPLICATION_PGP) && (msg->security & (SIGN|ENCRYPT))))
1715 msg->security |= INLINE;
1716
1717 msg->security |= APPLICATION_PGP;
1718
1719 /*
1720 * Opportunistic encrypt is controlling encryption. Allow to toggle
1721 * between inline and mime, but not turn encryption on or off.
1722 * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different
1723 * letter choices for those.
1724 */
1725 if (option (OPTCRYPTOPPORTUNISTICENCRYPT) && (msg->security & OPPENCRYPT))
1726 {
1727 if (msg->security & (ENCRYPT | SIGN))
1728 {
1729 snprintf (promptbuf, sizeof (promptbuf),
1730 _("PGP (s)ign, sign (a)s, %s format, (c)lear, or (o)ppenc mode off? "),
1731 (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline"));
1732 prompt = promptbuf;
1733 /* L10N: The 'f' is from "forget it", an old undocumented synonym of
1734 'clear'. Please use a corresponding letter in your language.
1735 Alternatively, you may duplicate the letter 'c' is translated to.
1736 This comment also applies to the five following letter sequences. */
1737 letters = _("safcoi");
1738 choices = "SaFCoi";
1739 }
1740 else
1741 {
1742 prompt = _("PGP (s)ign, sign (a)s, (c)lear, or (o)ppenc mode off? ");
1743 letters = _("safco");
1744 choices = "SaFCo";
1745 }
1746 }
1747 /*
1748 * Opportunistic encryption option is set, but is toggled off
1749 * for this message.
1750 */
1751 else if (option (OPTCRYPTOPPORTUNISTICENCRYPT))
1752 {
1753 /* When the message is not selected for signing or encryption, the toggle
1754 * between PGP/MIME and Traditional doesn't make sense.
1755 */
1756 if (msg->security & (ENCRYPT | SIGN))
1757 {
1758
1759 snprintf (promptbuf, sizeof (promptbuf),
1760 _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, (c)lear, or (o)ppenc mode? "),
1761 (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline"));
1762 prompt = promptbuf;
1763 letters = _("esabfcoi");
1764 choices = "esabfcOi";
1765 }
1766 else
1767 {
1768 prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (c)lear, or (o)ppenc mode? ");
1769 letters = _("esabfco");
1770 choices = "esabfcO";
1771 }
1772 }
1773 /*
1774 * Opportunistic encryption is unset
1775 */
1776 else
1777 {
1778 if (msg->security & (ENCRYPT | SIGN))
1779 {
1780
1781 snprintf (promptbuf, sizeof (promptbuf),
1782 _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, or (c)lear? "),
1783 (msg->security & INLINE) ? _("PGP/M(i)ME") : _("(i)nline"));
1784 prompt = promptbuf;
1785 letters = _("esabfci");
1786 choices = "esabfci";
1787 }
1788 else
1789 {
1790 prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, or (c)lear? ");
1791 letters = _("esabfc");
1792 choices = "esabfc";
1793 }
1794 }
1795
1796 choice = mutt_multi_choice (prompt, letters);
1797 if (choice > 0)
1798 {
1799 switch (choices[choice - 1])
1800 {
1801 case 'e': /* (e)ncrypt */
1802 msg->security |= ENCRYPT;
1803 msg->security &= ~SIGN;
1804 break;
1805
1806 case 's': /* (s)ign */
1807 msg->security &= ~ENCRYPT;
1808 msg->security |= SIGN;
1809 break;
1810
1811 case 'S': /* (s)ign in oppenc mode */
1812 msg->security |= SIGN;
1813 break;
1814
1815 case 'a': /* sign (a)s */
1816 unset_option(OPTPGPCHECKTRUST);
1817
1818 if ((p = pgp_ask_for_key (_("Sign as: "), NULL, 0, PGP_SECRING)))
1819 {
1820 snprintf (input_signas, sizeof (input_signas), "0x%s",
1821 pgp_fpr_or_lkeyid (p));
1822 mutt_str_replace (&PgpSignAs, input_signas);
1823 pgp_free_key (&p);
1824
1825 msg->security |= SIGN;
1826
1827 crypt_pgp_void_passphrase (); /* probably need a different passphrase */
1828 }
1829 *redraw = REDRAW_FULL;
1830 break;
1831
1832 case 'b': /* (b)oth */
1833 msg->security |= (ENCRYPT | SIGN);
1834 break;
1835
1836 case 'f': /* (f)orget it: kept for backward compatibility. */
1837 case 'c': /* (c)lear */
1838 msg->security &= ~(ENCRYPT | SIGN);
1839 break;
1840
1841 case 'F': /* (f)orget it or (c)lear in oppenc mode */
1842 case 'C':
1843 msg->security &= ~SIGN;
1844 break;
1845
1846 case 'O': /* oppenc mode on */
1847 msg->security |= OPPENCRYPT;
1848 crypt_opportunistic_encrypt (msg);
1849 break;
1850
1851 case 'o': /* oppenc mode off */
1852 msg->security &= ~OPPENCRYPT;
1853 break;
1854
1855 case 'i': /* toggle (i)nline */
1856 msg->security ^= INLINE;
1857 break;
1858 }
1859 }
1860
1861 return (msg->security);
1862}
1863
1864
1865#endif /* CRYPT_BACKEND_CLASSIC_PGP */