2472{
2473 int needpass = -1;
2474 bool pgp_keyblock = false;
2475 bool clearsign = false;
2476 long bytes;
2477 LOFF_T last_pos;
2478 LOFF_T block_begin;
2479 LOFF_T block_end;
2480 char buf[8192] = { 0 };
2481 FILE *fp_out = NULL;
2482
2483 gpgme_error_t err = GPG_ERR_NO_ERROR;
2484 gpgme_data_t armored_data = NULL;
2485
2486 bool maybe_goodsig = true;
2487 bool have_any_sigs = false;
2488
2489 char body_charset[256] = { 0 };
2490 char *gpgcharset = NULL;
2491
2493
2494
2495
2497 mutt_str_copy(body_charset,
"iso-8859-1",
sizeof(body_charset));
2498
2500 {
2501 return -1;
2502 }
2504
2505 for (bytes = b->
length; bytes > 0;)
2506 {
2507
2508 block_begin = last_pos;
2509
2510 if (!fgets(buf,
sizeof(buf), state->
fp_in))
2511 break;
2512
2513 LOFF_T offset = ftello(state->
fp_in);
2514 if (offset < 0)
2515 {
2517 offset = 0;
2518 }
2519 bytes -= (offset - last_pos);
2520 last_pos = offset;
2521
2523 if (plen != 0)
2524 {
2525 needpass = 0;
2526 clearsign = false;
2527 pgp_keyblock = false;
2528
2530 {
2531 needpass = 1;
2532 }
2534 {
2535 clearsign = true;
2536 }
2538 {
2539 pgp_keyblock = true;
2540 }
2541 else
2542 {
2543
2547 continue;
2548 }
2549
2550
2551 while ((bytes > 0) && (fgets(buf,
sizeof(buf) - 1, state->
fp_in) != NULL))
2552 {
2553 offset = ftello(state->
fp_in);
2554 if (offset < 0)
2555 {
2557 offset = 0;
2558 }
2559 bytes -= (offset - last_pos);
2560 last_pos = offset;
2561
2562 if (needpass &&
mutt_str_equal(
"-----END PGP MESSAGE-----\n", buf))
2563 {
2564 break;
2565 }
2566
2567 if (!needpass && (
mutt_str_equal(
"-----END PGP SIGNATURE-----\n", buf) ||
2569 {
2570 break;
2571 }
2572
2573
2575 {
2576 size_t l = 0;
2579 if ((l =
mutt_str_len(gpgcharset)) > 0 && gpgcharset[l - 1] ==
'\n')
2580 gpgcharset[l - 1] = 0;
2583 }
2584 }
2585 block_end = ftello(state->
fp_in);
2586 if (block_end < 0)
2587 {
2589 block_end = 0;
2590 }
2591
2592 have_any_sigs = (have_any_sigs || (clearsign && (state->
flags &
STATE_VERIFY)));
2593
2594
2596 fseeko(state->
fp_in, block_end, 0);
2597
2598
2599 if (pgp_keyblock)
2600 {
2602 }
2604 {
2607
2608 if (clearsign)
2609 {
2610 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2611 }
2612 else
2613 {
2614 err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
2615 if (gpg_err_code(err) == GPG_ERR_NO_DATA)
2616 {
2617
2618 gpgme_data_seek(armored_data, 0, SEEK_SET);
2619
2620 gpgme_data_release(plaintext);
2622 err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2623 }
2624 }
2626
2628 gpgme_decrypt_result_t result = gpgme_op_decrypt_result(ctx);
2631
2632 if (err != GPG_ERR_NO_ERROR)
2633 {
2634 char errbuf[200] = { 0 };
2635
2636 snprintf(errbuf, sizeof(errbuf) - 1,
2637 _(
"Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
2639 }
2640 else
2641 {
2642
2643
2645
2646 bool sig_stat = false;
2647 char *tmpfname = NULL;
2648
2649
2650 gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2651 if (verify_result->signatures)
2652 sig_stat = true;
2653
2654 have_any_sigs = false;
2655 maybe_goodsig = false;
2657 {
2658 int res, idx;
2659 bool anybad = false;
2660
2662 have_any_sigs = true;
2664 {
2665 if (res == 1)
2666 anybad = true;
2667 }
2668 if (!anybad && idx)
2669 maybe_goodsig = true;
2670
2672 }
2673
2675 if (tmpfname)
2676 {
2677 unlink(tmpfname);
2679 }
2680 else
2681 {
2683 state_puts(state,
_(
"Error: copy data failed\n"));
2684 }
2685 }
2686 gpgme_data_release(plaintext);
2687 gpgme_release(ctx);
2688 }
2689
2690
2691
2692
2694 {
2695 if (needpass)
2697 else if (pgp_keyblock)
2699 else
2701 }
2702
2703 if (clearsign)
2704 {
2706 }
2707 else if (fp_out)
2708 {
2709 int c;
2710 char *expected_charset = gpgcharset && *gpgcharset ? gpgcharset : "utf-8";
2711 rewind(fp_out);
2715 {
2717 if ((c ==
'\n') && state->
prefix)
2719 }
2721 }
2722
2724 {
2726 if (needpass)
2728 else if (pgp_keyblock)
2730 else
2732 }
2733
2734
2735 gpgme_data_release(armored_data);
2737 }
2738 else
2739 {
2740
2741
2745 }
2746 }
2748
2749 b->
goodsig = (maybe_goodsig && have_any_sigs);
2750
2751 if (needpass == -1)
2752 {
2753 state_attach_puts(state,
_(
"[-- Error: could not find beginning of PGP message --]\n\n"));
2754 return 1;
2755 }
2757
2758 return err;
2759}
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.