mutt stable branch with some hacks
at jcs 1963 lines 49 kB view raw
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 */