NeoMutt  2022-04-29-145-g9b6a0e
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 2836 of file crypt_gpgme.c.

2837 {
2838  int needpass = -1;
2839  bool pgp_keyblock = false;
2840  bool clearsign = false;
2841  long bytes;
2842  LOFF_T last_pos;
2843  char buf[8192];
2844  FILE *fp_out = NULL;
2845 
2846  gpgme_error_t err = 0;
2847  gpgme_data_t armored_data = NULL;
2848 
2849  bool maybe_goodsig = true;
2850  bool have_any_sigs = false;
2851 
2852  char body_charset[256]; /* Only used for clearsigned messages. */
2853 
2854  mutt_debug(LL_DEBUG2, "Entering handler\n");
2855 
2856  /* For clearsigned messages we won't be able to get a character set
2857  * but we know that this may only be text thus we assume Latin-1 here. */
2858  if (!mutt_body_get_charset(m, body_charset, sizeof(body_charset)))
2859  mutt_str_copy(body_charset, "iso-8859-1", sizeof(body_charset));
2860 
2861  if (!mutt_file_seek(s->fp_in, m->offset, SEEK_SET))
2862  {
2863  return -1;
2864  }
2865  last_pos = m->offset;
2866 
2867  for (bytes = m->length; bytes > 0;)
2868  {
2869  if (!fgets(buf, sizeof(buf), s->fp_in))
2870  break;
2871 
2872  LOFF_T offset = ftello(s->fp_in);
2873  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
2874  last_pos = offset;
2875 
2876  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
2877  if (plen != 0)
2878  {
2879  clearsign = false;
2880 
2881  if (MESSAGE(buf + plen))
2882  needpass = 1;
2883  else if (SIGNED_MESSAGE(buf + plen))
2884  {
2885  clearsign = true;
2886  needpass = 0;
2887  }
2888  else if (PUBLIC_KEY_BLOCK(buf + plen))
2889  {
2890  needpass = 0;
2891  pgp_keyblock = true;
2892  }
2893  else
2894  {
2895  /* XXX we may wish to recode here */
2896  if (s->prefix)
2897  state_puts(s, s->prefix);
2898  state_puts(s, buf);
2899  continue;
2900  }
2901 
2902  have_any_sigs = (have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY)));
2903 
2904  /* Copy PGP material to an data container */
2905  armored_data = file_to_data_object(s->fp_in, m->offset, m->length);
2906  /* Invoke PGP if needed */
2907  if (pgp_keyblock)
2908  {
2909  pgp_gpgme_extract_keys(armored_data, &fp_out);
2910  }
2911  else if (!clearsign || (s->flags & MUTT_VERIFY))
2912  {
2913  gpgme_data_t plaintext = create_gpgme_data();
2914  gpgme_ctx_t ctx = create_gpgme_context(false);
2915 
2916  if (clearsign)
2917  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2918  else
2919  {
2920  err = gpgme_op_decrypt_verify(ctx, armored_data, plaintext);
2921  if (gpg_err_code(err) == GPG_ERR_NO_DATA)
2922  {
2923  /* Decrypt verify can't handle signed only messages. */
2924  gpgme_data_seek(armored_data, 0, SEEK_SET);
2925  /* Must release plaintext so that we supply an uninitialized object. */
2926  gpgme_data_release(plaintext);
2927  plaintext = create_gpgme_data();
2928  err = gpgme_op_verify(ctx, armored_data, NULL, plaintext);
2929  }
2930  }
2931  redraw_if_needed(ctx);
2932 
2933  if (err != 0)
2934  {
2935  char errbuf[200];
2936 
2937  snprintf(errbuf, sizeof(errbuf) - 1,
2938  _("Error: decryption/verification failed: %s\n"), gpgme_strerror(err));
2939  state_puts(s, errbuf);
2940  }
2941  else
2942  {
2943  /* Decryption/Verification succeeded */
2944 
2945  mutt_message(_("PGP message successfully decrypted"));
2946 
2947  bool sig_stat = false;
2948  char *tmpfname = NULL;
2949 
2950  {
2951  /* Check whether signatures have been verified. */
2952  gpgme_verify_result_t verify_result = gpgme_op_verify_result(ctx);
2953  if (verify_result->signatures)
2954  sig_stat = true;
2955  }
2956 
2957  have_any_sigs = false;
2958  maybe_goodsig = false;
2959  if ((s->flags & MUTT_DISPLAY) && sig_stat)
2960  {
2961  int res, idx;
2962  bool anybad = false;
2963 
2964  state_attach_puts(s, _("[-- Begin signature information --]\n"));
2965  have_any_sigs = true;
2966  for (idx = 0; (res = show_one_sig_status(ctx, idx, s)) != -1; idx++)
2967  {
2968  if (res == 1)
2969  anybad = true;
2970  }
2971  if (!anybad && idx)
2972  maybe_goodsig = true;
2973 
2974  state_attach_puts(s, _("[-- End signature information --]\n\n"));
2975  }
2976 
2977  tmpfname = data_object_to_tempfile(plaintext, &fp_out);
2978  if (tmpfname)
2979  {
2980  unlink(tmpfname);
2981  FREE(&tmpfname);
2982  }
2983  else
2984  {
2985  mutt_file_fclose(&fp_out);
2986  state_puts(s, _("Error: copy data failed\n"));
2987  }
2988  }
2989  gpgme_data_release(plaintext);
2990  gpgme_release(ctx);
2991  }
2992 
2993  /* Now, copy cleartext to the screen. NOTE - we expect that PGP
2994  * outputs utf-8 cleartext. This may not always be true, but it
2995  * seems to be a reasonable guess. */
2996  if (s->flags & MUTT_DISPLAY)
2997  {
2998  if (needpass)
2999  state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
3000  else if (pgp_keyblock)
3001  state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
3002  else
3003  state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
3004  }
3005 
3006  if (clearsign)
3007  {
3008  copy_clearsigned(armored_data, s, body_charset);
3009  }
3010  else if (fp_out)
3011  {
3012  int c;
3013  rewind(fp_out);
3014  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
3015  struct FgetConv *fc = mutt_ch_fgetconv_open(fp_out, "utf-8", c_charset,
3017  while ((c = mutt_ch_fgetconv(fc)) != EOF)
3018  {
3019  state_putc(s, c);
3020  if ((c == '\n') && s->prefix)
3021  state_puts(s, s->prefix);
3022  }
3024  }
3025 
3026  if (s->flags & MUTT_DISPLAY)
3027  {
3028  state_putc(s, '\n');
3029  if (needpass)
3030  state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
3031  else if (pgp_keyblock)
3032  state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
3033  else
3034  state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
3035  }
3036 
3037  gpgme_data_release(armored_data);
3038  mutt_file_fclose(&fp_out);
3039  }
3040  else
3041  {
3042  /* A traditional PGP part may mix signed and unsigned content */
3043  /* XXX we may wish to recode here */
3044  if (s->prefix)
3045  state_puts(s, s->prefix);
3046  state_puts(s, buf);
3047  }
3048  }
3049 
3050  m->goodsig = (maybe_goodsig && have_any_sigs);
3051 
3052  if (needpass == -1)
3053  {
3054  state_attach_puts(s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
3055  return 1;
3056  }
3057  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3058 
3059  return err;
3060 }
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:621
gpgme_ctx_t create_gpgme_context(bool for_smime)
Create a new GPGME context.
Definition: crypt_gpgme.c:582
#define SIGNED_MESSAGE(_y)
Definition: crypt_gpgme.c:111
static int show_one_sig_status(gpgme_ctx_t ctx, int idx, struct State *s)
Show information about one signature.
Definition: crypt_gpgme.c:1781
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:749
#define PUBLIC_KEY_BLOCK(_y)
Definition: crypt_gpgme.c:112
static void copy_clearsigned(gpgme_data_t data, struct State *s, char *charset)
Copy a clearsigned message.
Definition: crypt_gpgme.c:2779
static void redraw_if_needed(gpgme_ctx_t ctx)
Accommodate for a redraw if needed.
Definition: crypt_gpgme.c:130
static int pgp_gpgme_extract_keys(gpgme_data_t keydata, FILE **fp)
Write PGP keys to a file.
Definition: crypt_gpgme.c:2425
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:817
#define MESSAGE(_y)
Definition: crypt_gpgme.c:110
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:690
#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
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
int mutt_ch_fgetconv(struct FgetConv *fc)
Convert a file's character set.
Definition: charset.c:907
#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:629
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 3160 of file crypt_gpgme.c.

3161 {
3162  int is_signed = 0;
3163  int rc = 0;
3164 
3165  mutt_debug(LL_DEBUG2, "Entering handler\n");
3166 
3167  /* clear out any mime headers before the handler, so they can't be spoofed. */
3169  a->warnsig = false;
3170  FILE *fp_out = mutt_file_mkstemp();
3171  if (!fp_out)
3172  {
3173  mutt_perror(_("Can't create temporary file"));
3174  if (s->flags & MUTT_DISPLAY)
3175  {
3176  state_attach_puts(s, _("[-- Error: could not create temporary file --]\n"));
3177  }
3178  return -1;
3179  }
3180 
3181  struct Body *tattach = decrypt_part(a, s, fp_out, true, &is_signed);
3182  if (tattach)
3183  {
3184  tattach->goodsig = is_signed > 0;
3185 
3186  if (s->flags & MUTT_DISPLAY)
3187  {
3188  state_attach_puts(s, is_signed ?
3189  _("[-- The following data is S/MIME signed --]\n\n") :
3190  _("[-- The following data is S/MIME encrypted --]\n\n"));
3191  mutt_protected_headers_handler(tattach, s);
3192  }
3193 
3194  /* Store any protected headers in the parent so they can be
3195  * accessed for index updates after the handler recursion is done.
3196  * This is done before the handler to prevent a nested encrypted
3197  * handler from freeing the headers. */
3199  a->mime_headers = tattach->mime_headers;
3200  tattach->mime_headers = NULL;
3201 
3202  {
3203  FILE *fp_save = s->fp_in;
3204  s->fp_in = fp_out;
3205  rc = mutt_body_handler(tattach, s);
3206  s->fp_in = fp_save;
3207  }
3208 
3209  /* Embedded multipart signed protected headers override the
3210  * encrypted headers. We need to do this after the handler so
3211  * they can be printed in the pager. */
3212  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
3213  {
3215  a->mime_headers = tattach->parts->mime_headers;
3216  tattach->parts->mime_headers = NULL;
3217  }
3218 
3219  /* if a multipart/signed is the _only_ sub-part of a multipart/encrypted,
3220  * cache signature verification status. */
3221  if (mutt_is_multipart_signed(tattach) && !tattach->next)
3222  {
3223  a->goodsig = tattach->goodsig;
3224  if (!a->goodsig)
3225  a->warnsig = tattach->warnsig;
3226  }
3227  else if (tattach->goodsig)
3228  {
3229  a->goodsig = true;
3230  a->warnsig = tattach->warnsig;
3231  }
3232 
3233  if (s->flags & MUTT_DISPLAY)
3234  {
3235  state_puts(s, "\n");
3236  state_attach_puts(s, is_signed ? _("[-- End of S/MIME signed data --]\n") :
3237  _("[-- End of S/MIME encrypted data --]\n"));
3238  }
3239 
3240  mutt_body_free(&tattach);
3241  }
3242 
3243  mutt_file_fclose(&fp_out);
3244  mutt_debug(LL_DEBUG2, "Leaving handler\n");
3245 
3246  return rc;
3247 }
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:2053
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:112
int mutt_protected_headers_handler(struct Body *b, struct State *s)
Process a protected header - Implements handler_t -.
Definition: crypt.c:1095
#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:1597
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];
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];
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  {
539  mutt_perror(mutt_buffer_string(tmpfname));
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);
704  state_set_prefix(s);
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 
754 out:
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:618
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
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:784
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
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: