NeoMutt  2022-04-29-323-g5fcc6c
Teaching an old dog new tricks
DOXYGEN
application_handler()

Manage the MIME type "application/pgp" or "application/smime". More...

+ Collaboration diagram for application_handler():

Functions

int pgp_gpgme_application_handler (struct Body *m, struct State *s)
 Implements CryptModuleSpecs::application_handler() -. More...
 
int smime_gpgme_application_handler (struct Body *a, struct State *s)
 Implements CryptModuleSpecs::application_handler() -. More...
 
int pgp_class_application_handler (struct Body *m, struct State *s)
 Implements CryptModuleSpecs::application_handler() -. More...
 
int smime_class_application_handler (struct Body *m, struct State *s)
 Implements CryptModuleSpecs::application_handler() -. More...
 

Detailed Description

Manage the MIME type "application/pgp" or "application/smime".

Parameters
mBody of the email
sState of text being processed
Return values
0Success
-1Error

Function Documentation

◆ pgp_gpgme_application_handler()

int pgp_gpgme_application_handler ( struct Body m,
struct State s 
)

Implements CryptModuleSpecs::application_handler() -.

Definition at line 2414 of file crypt_gpgme.c.

2415{
2416 int needpass = -1;
2417 bool pgp_keyblock = false;
2418 bool clearsign = false;
2419 long bytes;
2420 LOFF_T last_pos;
2421 char buf[8192] = { 0 };
2422 FILE *fp_out = NULL;
2423
2424 gpgme_error_t err = 0;
2425 gpgme_data_t armored_data = NULL;
2426
2427 bool maybe_goodsig = true;
2428 bool have_any_sigs = false;
2429
2430 char body_charset[256] = { 0 }; /* Only used for clearsigned messages. */
2431
2432 mutt_debug(LL_DEBUG2, "Entering handler\n");
2433
2434 /* For clearsigned messages we won't be able to get a character set
2435 * but we know that this may only be text thus we assume Latin-1 here. */
2436 if (!mutt_body_get_charset(m, body_charset, sizeof(body_charset)))
2437 mutt_str_copy(body_charset, "iso-8859-1", sizeof(body_charset));
2438
2439 if (!mutt_file_seek(s->fp_in, m->offset, SEEK_SET))
2440 {
2441 return -1;
2442 }
2443 last_pos = m->offset;
2444
2445 for (bytes = m->length; bytes > 0;)
2446 {
2447 if (!fgets(buf, sizeof(buf), s->fp_in))
2448 break;
2449
2450 LOFF_T offset = ftello(s->fp_in);
2451 bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
2452 last_pos = offset;
2453
2454 size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2455 if (plen != 0)
2456 {
2457 clearsign = false;
2458
2459 if (MESSAGE(buf + plen))
2460 needpass = 1;
2461 else if (SIGNED_MESSAGE(buf + plen))
2462 {
2463 clearsign = true;
2464 needpass = 0;
2465 }
2466 else if (PUBLIC_KEY_BLOCK(buf + plen))
2467 {
2468 needpass = 0;
2469 pgp_keyblock = true;
2470 }
2471 else
2472 {
2473 /* XXX we may wish to recode here */
2474 if (s->prefix)
2475 state_puts(s, s->prefix);
2476 state_puts(s, buf);
2477 continue;
2478 }
2479
2480 have_any_sigs = (have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY)));
2481
2482 /* Copy PGP material to an data container */
2483 armored_data = file_to_data_object(s->fp_in, m->offset, m->length);
2484 /* Invoke PGP if needed */
2485 if (pgp_keyblock)
2486 {
2487 pgp_gpgme_extract_keys(armored_data, &fp_out);
2488 }
2489 else if (!clearsign || (s->flags & MUTT_VERIFY))
2490 {
2491 gpgme_data_t plaintext = create_gpgme_data();
2492 gpgme_ctx_t ctx = create_gpgme_context(false);
2493
2494 if (clearsign)
2495 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2496 else
2497 {
2498 err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
2499 if (gpg_err_code(err) == GPG_ERR_NO_DATA)
2500 {
2501 /* Decrypt verify can't handle signed only messages. */
2502 gpgme_data_seek(armored_data, 0, SEEK_SET);
2503 /* Must release plaintext so that we supply an uninitialized object. */
2504 gpgme_data_release(plaintext);
2505 plaintext = create_gpgme_data();
2506 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2507 }
2508 }
2509 redraw_if_needed(ctx);
2510
2511 if (err != 0)
2512 {
2513 char errbuf[200] = { 0 };
2514
2515 snprintf(errbuf, sizeof(errbuf) - 1,
2516 _("Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
2517 state_puts(s, errbuf);
2518 }
2519 else
2520 {
2521 /* Decryption/Verification succeeded */
2522
2523 mutt_message(_("PGP message successfully decrypted"));
2524
2525 bool sig_stat = false;
2526 char *tmpfname = NULL;
2527
2528 {
2529 /* Check whether signatures have been verified. */
2530 gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2531 if (verify_result->signatures)
2532 sig_stat = true;
2533 }
2534
2535 have_any_sigs = false;
2536 maybe_goodsig = false;
2537 if ((s->flags & MUTT_DISPLAY) && sig_stat)
2538 {
2539 int res, idx;
2540 bool anybad = false;
2541
2542 state_attach_puts(s, _("[-- Begin signature information --]\n"));
2543 have_any_sigs = true;
2544 for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2545 {
2546 if (res == 1)
2547 anybad = true;
2548 }
2549 if (!anybad && idx)
2550 maybe_goodsig = true;
2551
2552 state_attach_puts(s, _("[-- End signature information --]\n\n"));
2553 }
2554
2555 tmpfname = data_object_to_tempfile(plaintext, &fp_out);
2556 if (tmpfname)
2557 {
2558 unlink(tmpfname);
2559 FREE(&tmpfname);
2560 }
2561 else
2562 {
2563 mutt_file_fclose(&fp_out);
2564 state_puts(s, _("Error: copy data failed\n"));
2565 }
2566 }
2567 gpgme_data_release(plaintext);
2568 gpgme_release(ctx);
2569 }
2570
2571 /* Now, copy cleartext to the screen. NOTE - we expect that PGP
2572 * outputs utf-8 cleartext. This may not always be true, but it
2573 * seems to be a reasonable guess. */
2574 if (s->flags & MUTT_DISPLAY)
2575 {
2576 if (needpass)
2577 state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
2578 else if (pgp_keyblock)
2579 state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
2580 else
2581 state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
2582 }
2583
2584 if (clearsign)
2585 {
2586 copy_clearsigned(armored_data, s, body_charset);
2587 }
2588 else if (fp_out)
2589 {
2590 int c;
2591 rewind(fp_out);
2592 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
2593 struct FgetConv *fc = mutt_ch_fgetconv_open(fp_out, "utf-8", c_charset,
2595 while ((c = mutt_ch_fgetconv(fc)) != EOF)
2596 {
2597 state_putc(s, c);
2598 if ((c == '\n') && s->prefix)
2599 state_puts(s, s->prefix);
2600 }
2602 }
2603
2604 if (s->flags & MUTT_DISPLAY)
2605 {
2606 state_putc(s, '\n');
2607 if (needpass)
2608 state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
2609 else if (pgp_keyblock)
2610 state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
2611 else
2612 state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
2613 }
2614
2615 gpgme_data_release(armored_data);
2616 mutt_file_fclose(&fp_out);
2617 }
2618 else
2619 {
2620 /* A traditional PGP part may mix signed and unsigned content */
2621 /* XXX we may wish to recode here */
2622 if (s->prefix)
2623 state_puts(s, s->prefix);
2624 state_puts(s, buf);
2625 }
2626 }
2627
2628 m->goodsig = (maybe_goodsig && have_any_sigs);
2629
2630 if (needpass == -1)
2631 {
2632 state_attach_puts(s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
2633 return 1;
2634 }
2635 mutt_debug(LL_DEBUG2, "Leaving handler\n");
2636
2637 return err;
2638}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:397
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:358
#define SIGNED_MESSAGE(_y)
Definition: crypt_gpgme.c:98
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1412
static gpgme_data_t file_to_data_object(FILE *fp, long offset, size_t length)
Create GPGME data object from file.
Definition: crypt_gpgme.c:488
#define PUBLIC_KEY_BLOCK(_y)
Definition: crypt_gpgme.c:99
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
Definition: crypt_gpgme.c:556
static void copy_clearsigned(gpgme_data_t data, struct State *s, char *charset)
Copy a clearsigned message.
Definition: crypt_gpgme.c:2357
static void redraw_if_needed(gpgme_ctx_t ctx)
Accommodate for a redraw if needed.
Definition: crypt_gpgme.c:117
static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
Write PGP keys to a file.
Definition: crypt_gpgme.c:2056
#define MESSAGE(_y)
Definition: crypt_gpgme.c:97
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:151
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:706
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
#define FREE(x)
Definition: memory.h:43
void mutt_ch_fgetconv_close(struct FgetConv **fc)
Close an fgetconv handle.
Definition: charset.c:887
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file's character set.
Definition: charset.c:907
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, uint8_t flags)
Prepare a file for charset conversion.
Definition: charset.c:857
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
#define _(a)
Definition: message.h:28
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:100
#define state_puts(STATE, STR)
Definition: state.h:56
#define MUTT_VERIFY
Perform signature verification.
Definition: state.h:33
#define state_putc(STATE, STR)
Definition: state.h:57
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:652
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
bool goodsig
Good cryptographic signature.
Definition: body.h:45
Cursor for converting a file's encoding.
Definition: charset.h:41
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
char * prefix
String to add to the beginning of each output line.
Definition: state.h:49
FILE * fp_in
File to read from.
Definition: state.h:47
+ Here is the call graph for this function:

◆ smime_gpgme_application_handler()

int smime_gpgme_application_handler ( struct Body a,
struct State s 
)

Implements CryptModuleSpecs::application_handler() -.

Definition at line 2738 of file crypt_gpgme.c.

2739{
2740 int is_signed = 0;
2741 int rc = 0;
2742
2743 mutt_debug(LL_DEBUG2, "Entering handler\n");
2744
2745 /* clear out any mime headers before the handler, so they can't be spoofed. */
2747 a->warnsig = false;
2748 FILE *fp_out = mutt_file_mkstemp();
2749 if (!fp_out)
2750 {
2751 mutt_perror(_("Can't create temporary file"));
2752 if (s->flags & MUTT_DISPLAY)
2753 {
2754 state_attach_puts(s, _("[-- Error: could not create temporary file --]\n"));
2755 }
2756 return -1;
2757 }
2758
2759 struct Body *tattach = decrypt_part(a, s, fp_out, true, &is_signed);
2760 if (tattach)
2761 {
2762 tattach->goodsig = is_signed > 0;
2763
2764 if (s->flags & MUTT_DISPLAY)
2765 {
2766 state_attach_puts(s, is_signed ?
2767 _("[-- The following data is S/MIME signed --]\n\n") :
2768 _("[-- The following data is S/MIME encrypted --]\n\n"));
2770 }
2771
2772 /* Store any protected headers in the parent so they can be
2773 * accessed for index updates after the handler recursion is done.
2774 * This is done before the handler to prevent a nested encrypted
2775 * handler from freeing the headers. */
2777 a->mime_headers = tattach->mime_headers;
2778 tattach->mime_headers = NULL;
2779
2780 {
2781 FILE *fp_save = s->fp_in;
2782 s->fp_in = fp_out;
2783 rc = mutt_body_handler(tattach, s);
2784 s->fp_in = fp_save;
2785 }
2786
2787 /* Embedded multipart signed protected headers override the
2788 * encrypted headers. We need to do this after the handler so
2789 * they can be printed in the pager. */
2790 if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
2791 {
2793 a->mime_headers = tattach->parts->mime_headers;
2794 tattach->parts->mime_headers = NULL;
2795 }
2796
2797 /* if a multipart/signed is the _only_ sub-part of a multipart/encrypted,
2798 * cache signature verification status. */
2799 if (mutt_is_multipart_signed(tattach) && !tattach->next)
2800 {
2801 a->goodsig = tattach->goodsig;
2802 if (!a->goodsig)
2803 a->warnsig = tattach->warnsig;
2804 }
2805 else if (tattach->goodsig)
2806 {
2807 a->goodsig = true;
2808 a->warnsig = tattach->warnsig;
2809 }
2810
2811 if (s->flags & MUTT_DISPLAY)
2812 {
2813 state_puts(s, "\n");
2814 state_attach_puts(s, is_signed ? _("[-- End of S/MIME signed data --]\n") :
2815 _("[-- End of S/MIME encrypted data --]\n"));
2816 }
2817
2818 mutt_body_free(&tattach);
2819 }
2820
2821 mutt_file_fclose(&fp_out);
2822 mutt_debug(LL_DEBUG2, "Leaving handler\n");
2823
2824 return rc;
2825}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:402
static struct Body * decrypt_part(struct Body *a, struct State *s, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:1684
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
#define mutt_file_mkstemp()
Definition: file.h:122
int mutt_protected_headers_handler(struct Body *b, struct State *s)
Process a protected header - Implements handler_t -.
Definition: crypt.c:1093
#define mutt_perror(...)
Definition: logging.h:88
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1596
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:75
struct Body * next
next attachment in the list
Definition: body.h:71
bool warnsig
Maybe good signature.
Definition: body.h:48
+ Here is the call graph for this function:

◆ pgp_class_application_handler()

int pgp_class_application_handler ( struct Body m,
struct State s 
)

Implements CryptModuleSpecs::application_handler() -.

Definition at line 465 of file pgp.c.

466{
467 bool could_not_decrypt = false;
468 int decrypt_okay_rc = 0;
469 int needpass = -1;
470 bool pgp_keyblock = false;
471 bool clearsign = false;
472 int rc = -1;
473 int c = 1;
474 long bytes;
475 LOFF_T last_pos, offset;
476 char buf[8192] = { 0 };
477 FILE *fp_pgp_out = NULL, *fp_pgp_in = NULL, *fp_pgp_err = NULL;
478 FILE *fp_tmp = NULL;
479 pid_t pid;
480 struct Buffer *tmpfname = mutt_buffer_pool_get();
481
482 bool maybe_goodsig = true;
483 bool have_any_sigs = false;
484
485 char *gpgcharset = NULL;
486 char body_charset[256] = { 0 };
487 mutt_body_get_charset(m, body_charset, sizeof(body_charset));
488
489 if (!mutt_file_seek(s->fp_in, m->offset, SEEK_SET))
490 {
491 return -1;
492 }
493 last_pos = m->offset;
494
495 for (bytes = m->length; bytes > 0;)
496 {
497 if (!fgets(buf, sizeof(buf), s->fp_in))
498 break;
499
500 offset = ftello(s->fp_in);
501 bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
502 last_pos = offset;
503
504 size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
505 if (plen != 0)
506 {
507 clearsign = false;
508 could_not_decrypt = false;
509 decrypt_okay_rc = 0;
510
511 if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
512 needpass = 1;
513 else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
514 {
515 clearsign = true;
516 needpass = 0;
517 }
518 else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
519 {
520 needpass = 0;
521 pgp_keyblock = true;
522 }
523 else
524 {
525 /* XXX we may wish to recode here */
526 if (s->prefix)
527 state_puts(s, s->prefix);
528 state_puts(s, buf);
529 continue;
530 }
531
532 have_any_sigs = have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY));
533
534 /* Copy PGP material to temporary file */
535 mutt_buffer_mktemp(tmpfname);
536 fp_tmp = mutt_file_fopen(mutt_buffer_string(tmpfname), "w+");
537 if (!fp_tmp)
538 {
540 FREE(&gpgcharset);
541 goto out;
542 }
543
544 fputs(buf, fp_tmp);
545 while ((bytes > 0) && fgets(buf, sizeof(buf) - 1, s->fp_in))
546 {
547 offset = ftello(s->fp_in);
548 bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
549 last_pos = offset;
550
551 fputs(buf, fp_tmp);
552
553 if ((needpass && mutt_str_equal("-----END PGP MESSAGE-----\n", buf)) ||
554 (!needpass && (mutt_str_equal("-----END PGP SIGNATURE-----\n", buf) ||
555 mutt_str_equal("-----END PGP PUBLIC KEY BLOCK-----\n", buf))))
556 {
557 break;
558 }
559 /* remember optional Charset: armor header as defined by RFC4880 */
560 if (mutt_str_startswith(buf, "Charset: "))
561 {
562 size_t l = 0;
563 FREE(&gpgcharset);
564 gpgcharset = mutt_str_dup(buf + 9);
565 l = mutt_str_len(gpgcharset);
566 if ((l > 0) && (gpgcharset[l - 1] == '\n'))
567 gpgcharset[l - 1] = 0;
568 if (!mutt_ch_check_charset(gpgcharset, false))
569 mutt_str_replace(&gpgcharset, "UTF-8");
570 }
571 }
572
573 /* leave fp_tmp open in case we still need it - but flush it! */
574 fflush(fp_tmp);
575
576 /* Invoke PGP if needed */
577 if (!clearsign || (s->flags & MUTT_VERIFY))
578 {
579 fp_pgp_out = mutt_file_mkstemp();
580 if (!fp_pgp_out)
581 {
582 mutt_perror(_("Can't create temporary file"));
583 goto out;
584 }
585
586 fp_pgp_err = mutt_file_mkstemp();
587 if (!fp_pgp_err)
588 {
589 mutt_perror(_("Can't create temporary file"));
590 goto out;
591 }
592
593 pid = pgp_invoke_decode(&fp_pgp_in, NULL, NULL, -1, fileno(fp_pgp_out),
594 fileno(fp_pgp_err),
595 mutt_buffer_string(tmpfname), (needpass != 0));
596 if (pid == -1)
597 {
598 mutt_file_fclose(&fp_pgp_out);
599 maybe_goodsig = false;
600 fp_pgp_in = NULL;
601 state_attach_puts(s, _("[-- Error: unable to create PGP subprocess --]\n"));
602 }
603 else /* PGP started successfully */
604 {
605 if (needpass)
606 {
609 if (pgp_use_gpg_agent())
610 *PgpPass = '\0';
611 fprintf(fp_pgp_in, "%s\n", PgpPass);
612 }
613
614 mutt_file_fclose(&fp_pgp_in);
615
616 int wait_filter_rc = filter_wait(pid);
617
618 fflush(fp_pgp_err);
619 /* If we are expecting an encrypted message, verify status fd output.
620 * Note that BEGIN PGP MESSAGE does not guarantee the content is encrypted,
621 * so we need to be more selective about the value of decrypt_okay_rc.
622 *
623 * -3 indicates we actively found a DECRYPTION_FAILED.
624 * -2 and -1 indicate part or all of the content was plaintext. */
625 if (needpass)
626 {
627 rewind(fp_pgp_err);
628 decrypt_okay_rc = pgp_check_decryption_okay(fp_pgp_err);
629 if (decrypt_okay_rc <= -3)
630 mutt_file_fclose(&fp_pgp_out);
631 }
632
633 if (s->flags & MUTT_DISPLAY)
634 {
635 rewind(fp_pgp_err);
636 crypt_current_time(s, "PGP");
637 int checksig_rc = pgp_copy_checksig(fp_pgp_err, s->fp_out);
638
639 if (checksig_rc == 0)
640 have_any_sigs = true;
641 /* Sig is bad if
642 * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
643 * Sig _is_ correct if
644 * gpg_good_sign="" && pgp_decode_command returned 0 */
645 if (checksig_rc == -1 || (wait_filter_rc != 0))
646 maybe_goodsig = false;
647
648 state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
649 }
650 if (pgp_use_gpg_agent())
651 {
653 }
654 }
655
656 /* treat empty result as sign of failure */
657 /* TODO: maybe on failure neomutt should include the original undecoded text. */
658 if (fp_pgp_out)
659 {
660 rewind(fp_pgp_out);
661 c = fgetc(fp_pgp_out);
662 ungetc(c, fp_pgp_out);
663 }
664 if (!clearsign && (!fp_pgp_out || (c == EOF)))
665 {
666 could_not_decrypt = true;
668 }
669
670 if ((could_not_decrypt || (decrypt_okay_rc <= -3)) && !(s->flags & MUTT_DISPLAY))
671 {
672 mutt_error(_("Could not decrypt PGP message"));
673 goto out;
674 }
675 }
676
677 /* Now, copy cleartext to the screen. */
678 if (s->flags & MUTT_DISPLAY)
679 {
680 if (needpass)
681 state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
682 else if (pgp_keyblock)
683 state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
684 else
685 state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
686 }
687
688 if (clearsign)
689 {
690 rewind(fp_tmp);
691 pgp_copy_clearsigned(fp_tmp, s, body_charset);
692 }
693 else if (fp_pgp_out)
694 {
695 struct FgetConv *fc = NULL;
696 int ch;
697 char *expected_charset = (gpgcharset && *gpgcharset) ? gpgcharset : "utf-8";
698
699 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
700 mutt_debug(LL_DEBUG3, "pgp: recoding inline from [%s] to [%s]\n",
701 expected_charset, c_charset);
702
703 rewind(fp_pgp_out);
705 fc = mutt_ch_fgetconv_open(fp_pgp_out, expected_charset, c_charset, MUTT_ICONV_HOOK_FROM);
706 while ((ch = mutt_ch_fgetconv(fc)) != EOF)
707 state_prefix_putc(s, ch);
709 }
710
711 /* Multiple PGP blocks can exist, so these need to be closed and
712 * unlinked inside the loop. */
713 mutt_file_fclose(&fp_tmp);
715 mutt_file_fclose(&fp_pgp_out);
716 mutt_file_fclose(&fp_pgp_err);
717
718 if (s->flags & MUTT_DISPLAY)
719 {
720 state_putc(s, '\n');
721 if (needpass)
722 {
723 state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
724 if (could_not_decrypt || (decrypt_okay_rc <= -3))
725 mutt_error(_("Could not decrypt PGP message"));
726 else if (decrypt_okay_rc < 0)
727 {
728 /* L10N: You will see this error message if (1) you are decrypting
729 (not encrypting) something and (2) it is a plaintext. So the
730 message does not mean "You failed to encrypt the message." */
731 mutt_error(_("PGP message is not encrypted"));
732 }
733 else
734 mutt_message(_("PGP message successfully decrypted"));
735 }
736 else if (pgp_keyblock)
737 state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
738 else
739 state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
740 }
741 }
742 else
743 {
744 /* A traditional PGP part may mix signed and unsigned content */
745 /* XXX we may wish to recode here */
746 if (s->prefix)
747 state_puts(s, s->prefix);
748 state_puts(s, buf);
749 }
750 }
751
752 rc = 0;
753
754out:
755 m->goodsig = (maybe_goodsig && have_any_sigs);
756
757 if (fp_tmp)
758 {
759 mutt_file_fclose(&fp_tmp);
761 }
762 mutt_file_fclose(&fp_pgp_out);
763 mutt_file_fclose(&fp_pgp_err);
764
765 mutt_buffer_pool_release(&tmpfname);
766
767 FREE(&gpgcharset);
768
769 if (needpass == -1)
770 {
771 state_attach_puts(s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
772 return -1;
773 }
774
775 return rc;
776}
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:70
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:162
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:634
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:193
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
bool pgp_class_valid_passphrase(void)
Implements CryptModuleSpecs::valid_passphrase() -.
Definition: pgp.c:84
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase() -.
Definition: pgp.c:75
#define mutt_error(...)
Definition: logging.h:87
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
bool mutt_ch_check_charset(const char *cs, bool strict)
Does iconv understand a character set?
Definition: charset.c:817
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
void state_prefix_putc(struct State *s, char c)
Write a prefixed character to the state.
Definition: state.c:161
#define state_set_prefix(state)
Definition: state.h:54
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
char PgpPass[1024]
Definition: pgp.c:69
static void pgp_copy_clearsigned(FILE *fp_in, struct State *s, char *charset)
Copy a clearsigned message, stripping the signature.
Definition: pgp.c:416
static int pgp_copy_checksig(FILE *fp_in, FILE *fp_out)
Copy PGP output and look for signs of a good signature.
Definition: pgp.c:251
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:127
static int pgp_check_decryption_okay(FILE *fp_in)
Check GPG output for status codes.
Definition: pgp.c:353
pid_t pgp_invoke_decode(FILE **fp_pgp_in, FILE **fp_pgp_out, FILE **fp_pgp_err, int fd_pgp_in, int fd_pgp_out, int fd_pgp_err, const char *fname, bool need_passphrase)
Use PGP to decode a message.
Definition: pgpinvoke.c:253
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
String manipulation buffer.
Definition: buffer.h:34
FILE * fp_out
File to write to.
Definition: state.h:48
+ Here is the call graph for this function:

◆ smime_class_application_handler()

int smime_class_application_handler ( struct Body m,
struct State s 
)

Implements CryptModuleSpecs::application_handler() -.

Definition at line 2138 of file smime.c.

2139{
2140 int rc = -1;
2141
2142 /* clear out any mime headers before the handler, so they can't be spoofed. */
2144
2145 struct Body *tattach = smime_handle_entity(m, s, NULL);
2146 if (tattach)
2147 {
2148 rc = 0;
2149 mutt_body_free(&tattach);
2150 }
2151 return rc;
2152}
static struct Body * smime_handle_entity(struct Body *m, struct State *s, FILE *fp_out_file)
Handle type application/pkcs7-mime.
Definition: smime.c:1840
+ Here is the call graph for this function: