2471{
2472 int needpass = -1;
2473 bool pgp_keyblock = false;
2474 bool clearsign = false;
2475 long bytes;
2476 LOFF_T last_pos;
2477 LOFF_T block_begin;
2478 LOFF_T block_end;
2479 char buf[8192] = { 0 };
2480 FILE *fp_out = NULL;
2481
2482 gpgme_error_t err = GPG_ERR_NO_ERROR;
2483 gpgme_data_t armored_data = NULL;
2484
2485 bool maybe_goodsig = true;
2486 bool have_any_sigs = false;
2487
2488 char body_charset[256] = { 0 };
2489 char *gpgcharset = NULL;
2490
2492
2493
2494
2496 mutt_str_copy(body_charset,
"iso-8859-1",
sizeof(body_charset));
2497
2499 {
2500 return -1;
2501 }
2503
2504 for (bytes = b->
length; bytes > 0;)
2505 {
2506
2507 block_begin = last_pos;
2508
2509 if (!fgets(buf,
sizeof(buf), state->
fp_in))
2510 break;
2511
2512 LOFF_T offset = ftello(state->
fp_in);
2513 if (offset < 0)
2514 {
2516 offset = 0;
2517 }
2518 bytes -= (offset - last_pos);
2519 last_pos = offset;
2520
2522 if (plen != 0)
2523 {
2524 needpass = 0;
2525 clearsign = false;
2526 pgp_keyblock = false;
2527
2529 {
2530 needpass = 1;
2531 }
2533 {
2534 clearsign = true;
2535 }
2537 {
2538 pgp_keyblock = true;
2539 }
2540 else
2541 {
2542
2546 continue;
2547 }
2548
2549
2550 while ((bytes > 0) && (fgets(buf,
sizeof(buf) - 1, state->
fp_in) != NULL))
2551 {
2552 offset = ftello(state->
fp_in);
2553 if (offset < 0)
2554 {
2556 offset = 0;
2557 }
2558 bytes -= (offset - last_pos);
2559 last_pos = offset;
2560
2561 if (needpass &&
mutt_str_equal(
"-----END PGP MESSAGE-----\n", buf))
2562 {
2563 break;
2564 }
2565
2566 if (!needpass && (
mutt_str_equal(
"-----END PGP SIGNATURE-----\n", buf) ||
2568 {
2569 break;
2570 }
2571
2572
2574 {
2575 size_t l = 0;
2578 if ((l =
mutt_str_len(gpgcharset)) > 0 && gpgcharset[l - 1] ==
'\n')
2579 gpgcharset[l - 1] = 0;
2582 }
2583 }
2584 block_end = ftello(state->
fp_in);
2585 if (block_end < 0)
2586 {
2588 block_end = 0;
2589 }
2590
2591 have_any_sigs = (have_any_sigs || (clearsign && (state->
flags &
STATE_VERIFY)));
2592
2593
2595 fseeko(state->
fp_in, block_end, 0);
2596
2597
2598 if (pgp_keyblock)
2599 {
2601 }
2603 {
2606
2607 if (clearsign)
2608 {
2609 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2610 }
2611 else
2612 {
2613 err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
2614 if (gpg_err_code(err) == GPG_ERR_NO_DATA)
2615 {
2616
2617 gpgme_data_seek(armored_data, 0, SEEK_SET);
2618
2619 gpgme_data_release(plaintext);
2621 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2622 }
2623 }
2625
2627 gpgme_decrypt_result_t result = gpgme_op_decrypt_result(ctx);
2630
2631 if (err != GPG_ERR_NO_ERROR)
2632 {
2633 char errbuf[200] = { 0 };
2634
2635 snprintf(errbuf, sizeof(errbuf) - 1,
2636 _(
"Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
2638 }
2639 else
2640 {
2641
2642
2644
2645 bool sig_stat = false;
2646 char *tmpfname = NULL;
2647
2648
2649 gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2650 if (verify_result->signatures)
2651 sig_stat = true;
2652
2653 have_any_sigs = false;
2654 maybe_goodsig = false;
2656 {
2657 int res, idx;
2658 bool anybad = false;
2659
2661 have_any_sigs = true;
2663 {
2664 if (res == 1)
2665 anybad = true;
2666 }
2667 if (!anybad && idx)
2668 maybe_goodsig = true;
2669
2671 }
2672
2674 if (tmpfname)
2675 {
2676 unlink(tmpfname);
2678 }
2679 else
2680 {
2682 state_puts(state,
_(
"Error: copy data failed\n"));
2683 }
2684 }
2685 gpgme_data_release(plaintext);
2686 gpgme_release(ctx);
2687 }
2688
2689
2690
2691
2693 {
2694 if (needpass)
2696 else if (pgp_keyblock)
2698 else
2700 }
2701
2702 if (clearsign)
2703 {
2705 }
2706 else if (fp_out)
2707 {
2708 int c;
2709 char *expected_charset = gpgcharset && *gpgcharset ? gpgcharset : "utf-8";
2710 rewind(fp_out);
2714 {
2716 if ((c ==
'\n') && state->
prefix)
2718 }
2720 }
2721
2723 {
2725 if (needpass)
2727 else if (pgp_keyblock)
2729 else
2731 }
2732
2733
2734 gpgme_data_release(armored_data);
2736 }
2737 else
2738 {
2739
2740
2744 }
2745 }
2747
2748 b->
goodsig = (maybe_goodsig && have_any_sigs);
2749
2750 if (needpass == -1)
2751 {
2752 state_attach_puts(state,
_(
"[-- Error: could not find beginning of PGP message --]\n\n"));
2753 return 1;
2754 }
2756
2757 return err;
2758}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
const char * cc_charset(void)
Get the cached value of $charset.
static void show_encryption_info(struct State *state, gpgme_decrypt_result_t result)
Show encryption information.
static gpgme_data_t create_gpgme_data(void)
Create a new GPGME data object.
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
#define SIGNED_MESSAGE(_y)
static gpgme_data_t file_to_data_object(FILE *fp, long offset, size_t length)
Create GPGME data object from file.
#define PUBLIC_KEY_BLOCK(_y)
static char * data_object_to_tempfile(gpgme_data_t data, FILE **fp_ret)
Copy a data object to a temporary file.
static void redraw_if_needed(gpgme_ctx_t ctx)
Accommodate for a redraw if needed.
static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
Write PGP keys to a file.
static void copy_clearsigned(gpgme_data_t data, struct State *state, char *charset)
Copy a clearsigned message.
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *state)
Show information about one signature.
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
#define mutt_file_fclose(FP)
#define mutt_message(...)
#define mutt_debug(LEVEL,...)
@ LL_DEBUG2
Log at debug level 2.
@ LL_DEBUG1
Log at debug level 1.
bool mutt_ch_check_charset(const char *cs, bool strict)
Does iconv understand a character set?
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file's character set.
struct FgetConv * mutt_ch_fgetconv_open(FILE *fp, const char *from, const char *to, uint8_t flags)
Prepare a file for charset conversion.
void mutt_ch_fgetconv_close(struct FgetConv **ptr)
Close an fgetconv handle.
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
void state_attach_puts(struct State *state, const char *t)
Write a string to the state.
#define state_puts(STATE, STR)
#define STATE_DISPLAY
Output is displayed to the user.
#define state_putc(STATE, STR)
#define STATE_VERIFY
Perform signature verification.
char * mutt_str_dup(const char *str)
Copy a string, safely.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
LOFF_T offset
offset where the actual data begins
LOFF_T length
length (in bytes) of attachment
bool goodsig
Good cryptographic signature.
Cursor for converting a file's encoding.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
StateFlags flags
Flags, e.g. STATE_DISPLAY.
FILE * fp_in
File to read from.
const char * prefix
String to add to the beginning of each output line.