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