NeoMutt  2023-11-03-85-g512e01
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 *b, struct State *state)
 Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.
 
int smime_gpgme_application_handler (struct Body *b, struct State *state)
 Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.
 
int pgp_class_application_handler (struct Body *b, struct State *state)
 Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.
 
int smime_class_application_handler (struct Body *b, struct State *state)
 Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.
 

Detailed Description

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

Parameters
bBody of the email
stateState of text being processed
Return values
0Success
-1Error

Function Documentation

◆ pgp_gpgme_application_handler()

int pgp_gpgme_application_handler ( struct Body b,
struct State state 
)

Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.

Definition at line 2426 of file crypt_gpgme.c.

2427{
2428 int needpass = -1;
2429 bool pgp_keyblock = false;
2430 bool clearsign = false;
2431 long bytes;
2432 LOFF_T last_pos;
2433 char buf[8192] = { 0 };
2434 FILE *fp_out = NULL;
2435
2436 gpgme_error_t err = 0;
2437 gpgme_data_t armored_data = NULL;
2438
2439 bool maybe_goodsig = true;
2440 bool have_any_sigs = false;
2441
2442 char body_charset[256] = { 0 }; /* Only used for clearsigned messages. */
2443
2444 mutt_debug(LL_DEBUG2, "Entering handler\n");
2445
2446 /* For clearsigned messages we won't be able to get a character set
2447 * but we know that this may only be text thus we assume Latin-1 here. */
2448 if (!mutt_body_get_charset(b, body_charset, sizeof(body_charset)))
2449 mutt_str_copy(body_charset, "iso-8859-1", sizeof(body_charset));
2450
2451 if (!mutt_file_seek(state->fp_in, b->offset, SEEK_SET))
2452 {
2453 return -1;
2454 }
2455 last_pos = b->offset;
2456
2457 for (bytes = b->length; bytes > 0;)
2458 {
2459 if (!fgets(buf, sizeof(buf), state->fp_in))
2460 break;
2461
2462 LOFF_T offset = ftello(state->fp_in);
2463 bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
2464 last_pos = offset;
2465
2466 size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2467 if (plen != 0)
2468 {
2469 clearsign = false;
2470
2471 if (MESSAGE(buf + plen))
2472 {
2473 needpass = 1;
2474 }
2475 else if (SIGNED_MESSAGE(buf + plen))
2476 {
2477 clearsign = true;
2478 needpass = 0;
2479 }
2480 else if (PUBLIC_KEY_BLOCK(buf + plen))
2481 {
2482 needpass = 0;
2483 pgp_keyblock = true;
2484 }
2485 else
2486 {
2487 /* XXX we may wish to recode here */
2488 if (state->prefix)
2489 state_puts(state, state->prefix);
2490 state_puts(state, buf);
2491 continue;
2492 }
2493
2494 have_any_sigs = (have_any_sigs || (clearsign && (state->flags & STATE_VERIFY)));
2495
2496 /* Copy PGP material to an data container */
2497 armored_data = file_to_data_object(state->fp_in, b->offset, b->length);
2498 /* Invoke PGP if needed */
2499 if (pgp_keyblock)
2500 {
2501 pgp_gpgme_extract_keys(armored_data, &fp_out);
2502 }
2503 else if (!clearsign || (state->flags & STATE_VERIFY))
2504 {
2505 gpgme_data_t plaintext = create_gpgme_data();
2506 gpgme_ctx_t ctx = create_gpgme_context(false);
2507
2508 if (clearsign)
2509 {
2510 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2511 }
2512 else
2513 {
2514 err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
2515 if (gpg_err_code(err) == GPG_ERR_NO_DATA)
2516 {
2517 /* Decrypt verify can't handle signed only messages. */
2518 gpgme_data_seek(armored_data, 0, SEEK_SET);
2519 /* Must release plaintext so that we supply an uninitialized object. */
2520 gpgme_data_release(plaintext);
2521 plaintext = create_gpgme_data();
2522 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2523 }
2524 }
2525 redraw_if_needed(ctx);
2526
2527 if (err != 0)
2528 {
2529 char errbuf[200] = { 0 };
2530
2531 snprintf(errbuf, sizeof(errbuf) - 1,
2532 _("Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
2533 state_puts(state, errbuf);
2534 }
2535 else
2536 {
2537 /* Decryption/Verification succeeded */
2538
2539 mutt_message(_("PGP message successfully decrypted"));
2540
2541 bool sig_stat = false;
2542 char *tmpfname = NULL;
2543
2544 /* Check whether signatures have been verified. */
2545 gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2546 if (verify_result->signatures)
2547 sig_stat = true;
2548
2549 have_any_sigs = false;
2550 maybe_goodsig = false;
2551 if ((state->flags & STATE_DISPLAY) && sig_stat)
2552 {
2553 int res, idx;
2554 bool anybad = false;
2555
2556 state_attach_puts(state, _("[-- Begin signature information --]\n"));
2557 have_any_sigs = true;
2558 for (idx = 0; (res = show_one_sig_status(ctx, idx, state)) != -1; idx++)
2559 {
2560 if (res == 1)
2561 anybad = true;
2562 }
2563 if (!anybad && idx)
2564 maybe_goodsig = true;
2565
2566 state_attach_puts(state, _("[-- End signature information --]\n\n"));
2567 }
2568
2569 tmpfname = data_object_to_tempfile(plaintext, &fp_out);
2570 if (tmpfname)
2571 {
2572 unlink(tmpfname);
2573 FREE(&tmpfname);
2574 }
2575 else
2576 {
2577 mutt_file_fclose(&fp_out);
2578 state_puts(state, _("Error: copy data failed\n"));
2579 }
2580 }
2581 gpgme_data_release(plaintext);
2582 gpgme_release(ctx);
2583 }
2584
2585 /* Now, copy cleartext to the screen. NOTE - we expect that PGP
2586 * outputs utf-8 cleartext. This may not always be true, but it
2587 * seems to be a reasonable guess. */
2588 if (state->flags & STATE_DISPLAY)
2589 {
2590 if (needpass)
2591 state_attach_puts(state, _("[-- BEGIN PGP MESSAGE --]\n\n"));
2592 else if (pgp_keyblock)
2593 state_attach_puts(state, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
2594 else
2595 state_attach_puts(state, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
2596 }
2597
2598 if (clearsign)
2599 {
2600 copy_clearsigned(armored_data, state, body_charset);
2601 }
2602 else if (fp_out)
2603 {
2604 int c;
2605 rewind(fp_out);
2606 struct FgetConv *fc = mutt_ch_fgetconv_open(fp_out, "utf-8", cc_charset(),
2608 while ((c = mutt_ch_fgetconv(fc)) != EOF)
2609 {
2610 state_putc(state, c);
2611 if ((c == '\n') && state->prefix)
2612 state_puts(state, state->prefix);
2613 }
2615 }
2616
2617 if (state->flags & STATE_DISPLAY)
2618 {
2619 state_putc(state, '\n');
2620 if (needpass)
2621 state_attach_puts(state, _("[-- END PGP MESSAGE --]\n"));
2622 else if (pgp_keyblock)
2623 state_attach_puts(state, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
2624 else
2625 state_attach_puts(state, _("[-- END PGP SIGNED MESSAGE --]\n"));
2626 }
2627
2628 gpgme_data_release(armored_data);
2629 mutt_file_fclose(&fp_out);
2630 }
2631 else
2632 {
2633 /* A traditional PGP part may mix signed and unsigned content */
2634 /* XXX we may wish to recode here */
2635 if (state->prefix)
2636 state_puts(state, state->prefix);
2637 state_puts(state, buf);
2638 }
2639 }
2640
2641 b->goodsig = (maybe_goodsig && have_any_sigs);
2642
2643 if (needpass == -1)
2644 {
2645 state_attach_puts(state, _("[-- Error: could not find beginning of PGP message --]\n\n"));
2646 return 1;
2647 }
2648 mutt_debug(LL_DEBUG2, "Leaving handler\n");
2649
2650 return err;
2651}
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:115
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
Definition: crypt_gpgme.c:399
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:360
#define SIGNED_MESSAGE(_y)
Definition: crypt_gpgme.c:101
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:492
#define PUBLIC_KEY_BLOCK(_y)
Definition: crypt_gpgme.c:102
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:560
static void redraw_if_needed(gpgme_ctx_t ctx)
Accommodate for a redraw if needed.
Definition: crypt_gpgme.c:120
static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
Write PGP keys to a file.
Definition: crypt_gpgme.c:2067
static void copy_clearsigned(gpgme_data_t data, struct State *state, char *charset)
Copy a clearsigned message.
Definition: crypt_gpgme.c:2370
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *state)
Show information about one signature.
Definition: crypt_gpgme.c:1418
#define MESSAGE(_y)
Definition: crypt_gpgme.c:100
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:152
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:733
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
#define FREE(x)
Definition: memory.h:45
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file's character set.
Definition: charset.c:978
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:928
void mutt_ch_fgetconv_close(struct FgetConv **ptr)
Close an fgetconv handle.
Definition: charset.c:960
#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 *state, const char *t)
Write a string to the state.
Definition: state.c:102
#define state_puts(STATE, STR)
Definition: state.h:57
#define STATE_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define state_putc(STATE, STR)
Definition: state.h:58
#define STATE_VERIFY
Perform signature verification.
Definition: state.h:33
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:228
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:653
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
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition: state.h:51
char * prefix
String to add to the beginning of each output line.
Definition: state.h:50
FILE * fp_in
File to read from.
Definition: state.h:48
+ Here is the call graph for this function:

◆ smime_gpgme_application_handler()

int smime_gpgme_application_handler ( struct Body b,
struct State state 
)

Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.

Definition at line 2750 of file crypt_gpgme.c.

2751{
2752 int is_signed = 0;
2753 int rc = 0;
2754
2755 mutt_debug(LL_DEBUG2, "Entering handler\n");
2756
2757 /* clear out any mime headers before the handler, so they can't be spoofed. */
2759 b->warnsig = false;
2760 FILE *fp_out = mutt_file_mkstemp();
2761 if (!fp_out)
2762 {
2763 mutt_perror(_("Can't create temporary file"));
2764 if (state->flags & STATE_DISPLAY)
2765 {
2766 state_attach_puts(state, _("[-- Error: could not create temporary file --]\n"));
2767 }
2768 return -1;
2769 }
2770
2771 struct Body *tattach = decrypt_part(b, state, fp_out, true, &is_signed);
2772 if (tattach)
2773 {
2774 tattach->goodsig = is_signed > 0;
2775
2776 if (state->flags & STATE_DISPLAY)
2777 {
2778 state_attach_puts(state, is_signed ?
2779 _("[-- The following data is S/MIME signed --]\n\n") :
2780 _("[-- The following data is S/MIME encrypted --]\n\n"));
2781 mutt_protected_headers_handler(tattach, state);
2782 }
2783
2784 /* Store any protected headers in the parent so they can be
2785 * accessed for index updates after the handler recursion is done.
2786 * This is done before the handler to prevent a nested encrypted
2787 * handler from freeing the headers. */
2789 b->mime_headers = tattach->mime_headers;
2790 tattach->mime_headers = NULL;
2791
2792 FILE *fp_save = state->fp_in;
2793 state->fp_in = fp_out;
2794 rc = mutt_body_handler(tattach, state);
2795 state->fp_in = fp_save;
2796
2797 /* Embedded multipart signed protected headers override the
2798 * encrypted headers. We need to do this after the handler so
2799 * they can be printed in the pager. */
2800 if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
2801 {
2803 b->mime_headers = tattach->parts->mime_headers;
2804 tattach->parts->mime_headers = NULL;
2805 }
2806
2807 /* if a multipart/signed is the _only_ sub-part of a multipart/encrypted,
2808 * cache signature verification status. */
2809 if (mutt_is_multipart_signed(tattach) && !tattach->next)
2810 {
2811 b->goodsig = tattach->goodsig;
2812 if (!b->goodsig)
2813 b->warnsig = tattach->warnsig;
2814 }
2815 else if (tattach->goodsig)
2816 {
2817 b->goodsig = true;
2818 b->warnsig = tattach->warnsig;
2819 }
2820
2821 if (state->flags & STATE_DISPLAY)
2822 {
2823 state_puts(state, "\n");
2824 state_attach_puts(state, is_signed ? _("[-- End of S/MIME signed data --]\n") :
2825 _("[-- End of S/MIME encrypted data --]\n"));
2826 }
2827
2828 mutt_body_free(&tattach);
2829 }
2830
2831 mutt_file_fclose(&fp_out);
2832 mutt_debug(LL_DEBUG2, "Leaving handler\n");
2833
2834 return rc;
2835}
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:397
static struct Body * decrypt_part(struct Body *b, struct State *state, FILE *fp_out, bool is_smime, int *r_is_signed)
Decrypt a PGP or SMIME message.
Definition: crypt_gpgme.c:1692
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
int mutt_protected_headers_handler(struct Body *b_email, struct State *state)
Handler for protected headers - Implements handler_t -.
Definition: crypt.c:1106
#define mutt_perror(...)
Definition: logging2.h:93
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition: handler.c:1624
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
#define mutt_file_mkstemp()
Definition: tmp.h:36
+ Here is the call graph for this function:

◆ pgp_class_application_handler()

int pgp_class_application_handler ( struct Body b,
struct State state 
)

Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.

Definition at line 473 of file pgp.c.

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

◆ smime_class_application_handler()

int smime_class_application_handler ( struct Body b,
struct State state 
)

Manage the MIME type "application/pgp" or "application/smime" - Implements CryptModuleSpecs::application_handler() -.

Definition at line 2157 of file smime.c.

2158{
2159 int rc = -1;
2160
2161 /* clear out any mime headers before the handler, so they can't be spoofed. */
2163
2164 struct Body *tattach = smime_handle_entity(b, state, NULL);
2165 if (tattach)
2166 {
2167 rc = 0;
2168 mutt_body_free(&tattach);
2169 }
2170 return rc;
2171}
static struct Body * smime_handle_entity(struct Body *b, struct State *state, FILE *fp_out_file)
Handle type application/pkcs7-mime.
Definition: smime.c:1856
+ Here is the call graph for this function: