NeoMutt  2022-04-29-81-g9c5a59
Teaching an old dog new tricks
DOXYGEN
pgp.c
Go to the documentation of this file.
1 
36 #include "config.h"
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 #include <unistd.h>
43 #include "mutt/lib.h"
44 #include "address/lib.h"
45 #include "config/lib.h"
46 #include "email/lib.h"
47 #include "core/lib.h"
48 #include "gui/lib.h"
49 #include "mutt.h"
50 #include "lib.h"
51 #include "attach/lib.h"
52 #include "question/lib.h"
53 #include "send/lib.h"
54 #include "crypt.h"
55 #include "cryptglue.h"
56 #include "handler.h"
57 #include "hook.h"
58 #include "muttlib.h"
59 #include "options.h"
60 #include "pgpinvoke.h"
61 #include "pgpkey.h"
62 #include "pgpmicalg.h"
63 #ifdef CRYPT_BACKEND_CLASSIC_PGP
64 #include "pgp.h"
65 #include "pgplib.h"
66 #endif
67 
68 char PgpPass[1024];
69 time_t PgpExptime = 0; /* when does the cached passphrase expire? */
70 
75 {
76  memset(PgpPass, 0, sizeof(PgpPass));
77  PgpExptime = 0;
78 }
79 
84 {
85  if (pgp_use_gpg_agent())
86  {
87  *PgpPass = '\0';
88  return true; /* handled by gpg-agent */
89  }
90 
92  {
93  /* Use cached copy. */
94  return true;
95  }
96 
98 
99  struct Buffer *buf = mutt_buffer_pool_get();
100  const int rc = mutt_get_field_unbuffered(_("Enter PGP passphrase:"), buf, MUTT_COMP_PASS);
103 
104  if (rc == 0)
105  {
106  const long c_pgp_timeout = cs_subset_long(NeoMutt->sub, "pgp_timeout");
108  return true;
109  }
110  else
111  {
112  PgpExptime = 0;
113  }
114 
115  return false;
116 }
117 
125 {
126  char *tty = NULL;
127 
128  /* GnuPG 2.1 no longer exports GPG_AGENT_INFO */
129  const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
130  if (!c_pgp_use_gpg_agent)
131  return false;
132 
133  tty = ttyname(0);
134  if (tty)
135  {
136  setenv("GPG_TTY", tty, 0);
137  mutt_envlist_set("GPG_TTY", tty, false);
138  }
139 
140  return true;
141 }
142 
148 static struct PgpKeyInfo *key_parent(struct PgpKeyInfo *k)
149 {
150  const bool c_pgp_ignore_subkeys = cs_subset_bool(NeoMutt->sub, "pgp_ignore_subkeys");
151  if ((k->flags & KEYFLAG_SUBKEY) && k->parent && c_pgp_ignore_subkeys)
152  k = k->parent;
153 
154  return k;
155 }
156 
162 char *pgp_long_keyid(struct PgpKeyInfo *k)
163 {
164  k = key_parent(k);
165 
166  return k->keyid;
167 }
168 
174 char *pgp_short_keyid(struct PgpKeyInfo *k)
175 {
176  k = key_parent(k);
177 
178  return k->keyid + 8;
179 }
180 
188 char *pgp_this_keyid(struct PgpKeyInfo *k)
189 {
190  const bool c_pgp_long_ids = cs_subset_bool(NeoMutt->sub, "pgp_long_ids");
191  if (c_pgp_long_ids)
192  return k->keyid;
193  return k->keyid + 8;
194 }
195 
201 char *pgp_keyid(struct PgpKeyInfo *k)
202 {
203  k = key_parent(k);
204 
205  return pgp_this_keyid(k);
206 }
207 
213 static char *pgp_fingerprint(struct PgpKeyInfo *k)
214 {
215  k = key_parent(k);
216 
217  return k->fingerprint;
218 }
219 
232 {
233  char *fingerprint = pgp_fingerprint(k);
234  return fingerprint ? fingerprint : pgp_long_keyid(k);
235 }
236 
237 /* ----------------------------------------------------------------------------
238  * Routines for handing PGP input.
239  */
240 
248 static int pgp_copy_checksig(FILE *fp_in, FILE *fp_out)
249 {
250  if (!fp_in || !fp_out)
251  return -1;
252 
253  int rc = -1;
254 
255  const struct Regex *c_pgp_good_sign = cs_subset_regex(NeoMutt->sub, "pgp_good_sign");
256  if (c_pgp_good_sign && c_pgp_good_sign->regex)
257  {
258  char *line = NULL;
259  size_t linelen;
260 
261  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
262  {
263  if (mutt_regex_match(c_pgp_good_sign, line))
264  {
265  mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
266  rc = 0;
267  }
268  else
269  mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
270 
271  if (mutt_strn_equal(line, "[GNUPG:] ", 9))
272  continue;
273  fputs(line, fp_out);
274  fputc('\n', fp_out);
275  }
276  FREE(&line);
277  }
278  else
279  {
280  mutt_debug(LL_DEBUG2, "No pattern\n");
281  mutt_file_copy_stream(fp_in, fp_out);
282  rc = 1;
283  }
284 
285  return rc;
286 }
287 
298 static int pgp_check_pgp_decryption_okay_regex(FILE *fp_in)
299 {
300  int rc = -1;
301 
302  const struct Regex *c_pgp_decryption_okay = cs_subset_regex(NeoMutt->sub, "pgp_decryption_okay");
303  if (c_pgp_decryption_okay && c_pgp_decryption_okay->regex)
304  {
305  char *line = NULL;
306  size_t linelen;
307 
308  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
309  {
310  if (mutt_regex_match(c_pgp_decryption_okay, line))
311  {
312  mutt_debug(LL_DEBUG2, "\"%s\" matches regex\n", line);
313  rc = 0;
314  break;
315  }
316  else
317  mutt_debug(LL_DEBUG2, "\"%s\" doesn't match regex\n", line);
318  }
319  FREE(&line);
320  }
321  else
322  {
323  mutt_debug(LL_DEBUG2, "No pattern\n");
324  rc = 1;
325  }
326 
327  return rc;
328 }
329 
350 static int pgp_check_decryption_okay(FILE *fp_in)
351 {
352  int rc = -1;
353  char *line = NULL, *s = NULL;
354  size_t linelen;
355  int inside_decrypt = 0;
356 
357  const bool c_pgp_check_gpg_decrypt_status_fd = cs_subset_bool(NeoMutt->sub, "pgp_check_gpg_decrypt_status_fd");
358  if (!c_pgp_check_gpg_decrypt_status_fd)
360 
361  while ((line = mutt_file_read_line(line, &linelen, fp_in, NULL, MUTT_RL_NO_FLAGS)))
362  {
363  size_t plen = mutt_str_startswith(line, "[GNUPG:] ");
364  if (plen == 0)
365  continue;
366  s = line + plen;
367  mutt_debug(LL_DEBUG2, "checking \"%s\"\n", line);
368  if (mutt_str_startswith(s, "BEGIN_DECRYPTION"))
369  inside_decrypt = 1;
370  else if (mutt_str_startswith(s, "END_DECRYPTION"))
371  inside_decrypt = 0;
372  else if (mutt_str_startswith(s, "PLAINTEXT"))
373  {
374  if (!inside_decrypt)
375  {
376  mutt_debug(LL_DEBUG2, " PLAINTEXT encountered outside of DECRYPTION\n");
377  rc = -2;
378  break;
379  }
380  }
381  else if (mutt_str_startswith(s, "DECRYPTION_FAILED"))
382  {
383  mutt_debug(LL_DEBUG2, " DECRYPTION_FAILED encountered. Failure\n");
384  rc = -3;
385  break;
386  }
387  else if (mutt_str_startswith(s, "DECRYPTION_OKAY"))
388  {
389  /* Don't break out because we still have to check for
390  * PLAINTEXT outside of the decryption boundaries. */
391  mutt_debug(LL_DEBUG2, " DECRYPTION_OKAY encountered\n");
392  rc = 0;
393  }
394  }
395  FREE(&line);
396 
397  return rc;
398 }
399 
413 static void pgp_copy_clearsigned(FILE *fp_in, struct State *s, char *charset)
414 {
415  char buf[8192];
416  bool complete, armor_header;
417 
418  rewind(fp_in);
419 
420  /* fromcode comes from the MIME Content-Type charset label. It might
421  * be a wrong label, so we want the ability to do corrections via
422  * charset-hooks. Therefore we set flags to MUTT_ICONV_HOOK_FROM. */
423  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
424  struct FgetConv *fc = mutt_ch_fgetconv_open(fp_in, charset, c_charset, MUTT_ICONV_HOOK_FROM);
425 
426  for (complete = true, armor_header = true;
427  mutt_ch_fgetconvs(buf, sizeof(buf), fc); complete = (strchr(buf, '\n')))
428  {
429  if (!complete)
430  {
431  if (!armor_header)
432  state_puts(s, buf);
433  continue;
434  }
435 
436  if (mutt_str_equal(buf, "-----BEGIN PGP SIGNATURE-----\n"))
437  break;
438 
439  if (armor_header)
440  {
441  char *p = mutt_str_skip_whitespace(buf);
442  if (*p == '\0')
443  armor_header = false;
444  continue;
445  }
446 
447  if (s->prefix)
448  state_puts(s, s->prefix);
449 
450  if ((buf[0] == '-') && (buf[1] == ' '))
451  state_puts(s, buf + 2);
452  else
453  state_puts(s, buf);
454  }
455 
457 }
458 
462 int pgp_class_application_handler(struct Body *m, struct State *s)
463 {
464  bool could_not_decrypt = false;
465  int decrypt_okay_rc = 0;
466  int needpass = -1;
467  bool pgp_keyblock = false;
468  bool clearsign = false;
469  int rc = -1;
470  int c = 1;
471  long bytes;
472  LOFF_T last_pos, offset;
473  char buf[8192];
474  FILE *fp_pgp_out = NULL, *fp_pgp_in = NULL, *fp_pgp_err = NULL;
475  FILE *fp_tmp = NULL;
476  pid_t pid;
477  struct Buffer *tmpfname = mutt_buffer_pool_get();
478 
479  bool maybe_goodsig = true;
480  bool have_any_sigs = false;
481 
482  char *gpgcharset = NULL;
483  char body_charset[256];
484  mutt_body_get_charset(m, body_charset, sizeof(body_charset));
485 
486  if (!mutt_file_seek(s->fp_in, m->offset, SEEK_SET))
487  {
488  return -1;
489  }
490  last_pos = m->offset;
491 
492  for (bytes = m->length; bytes > 0;)
493  {
494  if (!fgets(buf, sizeof(buf), s->fp_in))
495  break;
496 
497  offset = ftello(s->fp_in);
498  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
499  last_pos = offset;
500 
501  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
502  if (plen != 0)
503  {
504  clearsign = false;
505  could_not_decrypt = false;
506  decrypt_okay_rc = 0;
507 
508  if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
509  needpass = 1;
510  else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
511  {
512  clearsign = true;
513  needpass = 0;
514  }
515  else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
516  {
517  needpass = 0;
518  pgp_keyblock = true;
519  }
520  else
521  {
522  /* XXX we may wish to recode here */
523  if (s->prefix)
524  state_puts(s, s->prefix);
525  state_puts(s, buf);
526  continue;
527  }
528 
529  have_any_sigs = have_any_sigs || (clearsign && (s->flags & MUTT_VERIFY));
530 
531  /* Copy PGP material to temporary file */
532  mutt_buffer_mktemp(tmpfname);
533  fp_tmp = mutt_file_fopen(mutt_buffer_string(tmpfname), "w+");
534  if (!fp_tmp)
535  {
536  mutt_perror(mutt_buffer_string(tmpfname));
537  FREE(&gpgcharset);
538  goto out;
539  }
540 
541  fputs(buf, fp_tmp);
542  while ((bytes > 0) && fgets(buf, sizeof(buf) - 1, s->fp_in))
543  {
544  offset = ftello(s->fp_in);
545  bytes -= (offset - last_pos); /* don't rely on mutt_str_len(buf) */
546  last_pos = offset;
547 
548  fputs(buf, fp_tmp);
549 
550  if ((needpass && mutt_str_equal("-----END PGP MESSAGE-----\n", buf)) ||
551  (!needpass && (mutt_str_equal("-----END PGP SIGNATURE-----\n", buf) ||
552  mutt_str_equal("-----END PGP PUBLIC KEY BLOCK-----\n", buf))))
553  {
554  break;
555  }
556  /* remember optional Charset: armor header as defined by RFC4880 */
557  if (mutt_str_startswith(buf, "Charset: "))
558  {
559  size_t l = 0;
560  FREE(&gpgcharset);
561  gpgcharset = mutt_str_dup(buf + 9);
562  l = mutt_str_len(gpgcharset);
563  if ((l > 0) && (gpgcharset[l - 1] == '\n'))
564  gpgcharset[l - 1] = 0;
565  if (!mutt_ch_check_charset(gpgcharset, false))
566  mutt_str_replace(&gpgcharset, "UTF-8");
567  }
568  }
569 
570  /* leave fp_tmp open in case we still need it - but flush it! */
571  fflush(fp_tmp);
572 
573  /* Invoke PGP if needed */
574  if (!clearsign || (s->flags & MUTT_VERIFY))
575  {
576  fp_pgp_out = mutt_file_mkstemp();
577  if (!fp_pgp_out)
578  {
579  mutt_perror(_("Can't create temporary file"));
580  goto out;
581  }
582 
583  fp_pgp_err = mutt_file_mkstemp();
584  if (!fp_pgp_err)
585  {
586  mutt_perror(_("Can't create temporary file"));
587  goto out;
588  }
589 
590  pid = pgp_invoke_decode(&fp_pgp_in, NULL, NULL, -1, fileno(fp_pgp_out),
591  fileno(fp_pgp_err),
592  mutt_buffer_string(tmpfname), (needpass != 0));
593  if (pid == -1)
594  {
595  mutt_file_fclose(&fp_pgp_out);
596  maybe_goodsig = false;
597  fp_pgp_in = NULL;
598  state_attach_puts(s, _("[-- Error: unable to create PGP subprocess --]\n"));
599  }
600  else /* PGP started successfully */
601  {
602  if (needpass)
603  {
606  if (pgp_use_gpg_agent())
607  *PgpPass = '\0';
608  fprintf(fp_pgp_in, "%s\n", PgpPass);
609  }
610 
611  mutt_file_fclose(&fp_pgp_in);
612 
613  int wait_filter_rc = filter_wait(pid);
614 
615  fflush(fp_pgp_err);
616  /* If we are expecting an encrypted message, verify status fd output.
617  * Note that BEGIN PGP MESSAGE does not guarantee the content is encrypted,
618  * so we need to be more selective about the value of decrypt_okay_rc.
619  *
620  * -3 indicates we actively found a DECRYPTION_FAILED.
621  * -2 and -1 indicate part or all of the content was plaintext. */
622  if (needpass)
623  {
624  rewind(fp_pgp_err);
625  decrypt_okay_rc = pgp_check_decryption_okay(fp_pgp_err);
626  if (decrypt_okay_rc <= -3)
627  mutt_file_fclose(&fp_pgp_out);
628  }
629 
630  if (s->flags & MUTT_DISPLAY)
631  {
632  rewind(fp_pgp_err);
633  crypt_current_time(s, "PGP");
634  int checksig_rc = pgp_copy_checksig(fp_pgp_err, s->fp_out);
635 
636  if (checksig_rc == 0)
637  have_any_sigs = true;
638  /* Sig is bad if
639  * gpg_good_sign-pattern did not match || pgp_decode_command returned not 0
640  * Sig _is_ correct if
641  * gpg_good_sign="" && pgp_decode_command returned 0 */
642  if (checksig_rc == -1 || (wait_filter_rc != 0))
643  maybe_goodsig = false;
644 
645  state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
646  }
647  if (pgp_use_gpg_agent())
648  {
650  }
651  }
652 
653  /* treat empty result as sign of failure */
654  /* TODO: maybe on failure neomutt should include the original undecoded text. */
655  if (fp_pgp_out)
656  {
657  rewind(fp_pgp_out);
658  c = fgetc(fp_pgp_out);
659  ungetc(c, fp_pgp_out);
660  }
661  if (!clearsign && (!fp_pgp_out || (c == EOF)))
662  {
663  could_not_decrypt = true;
665  }
666 
667  if ((could_not_decrypt || (decrypt_okay_rc <= -3)) && !(s->flags & MUTT_DISPLAY))
668  {
669  mutt_error(_("Could not decrypt PGP message"));
670  goto out;
671  }
672  }
673 
674  /* Now, copy cleartext to the screen. */
675  if (s->flags & MUTT_DISPLAY)
676  {
677  if (needpass)
678  state_attach_puts(s, _("[-- BEGIN PGP MESSAGE --]\n\n"));
679  else if (pgp_keyblock)
680  state_attach_puts(s, _("[-- BEGIN PGP PUBLIC KEY BLOCK --]\n"));
681  else
682  state_attach_puts(s, _("[-- BEGIN PGP SIGNED MESSAGE --]\n\n"));
683  }
684 
685  if (clearsign)
686  {
687  rewind(fp_tmp);
688  pgp_copy_clearsigned(fp_tmp, s, body_charset);
689  }
690  else if (fp_pgp_out)
691  {
692  struct FgetConv *fc = NULL;
693  int ch;
694  char *expected_charset = (gpgcharset && *gpgcharset) ? gpgcharset : "utf-8";
695 
696  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
697  mutt_debug(LL_DEBUG3, "pgp: recoding inline from [%s] to [%s]\n",
698  expected_charset, c_charset);
699 
700  rewind(fp_pgp_out);
701  state_set_prefix(s);
702  fc = mutt_ch_fgetconv_open(fp_pgp_out, expected_charset, c_charset, MUTT_ICONV_HOOK_FROM);
703  while ((ch = mutt_ch_fgetconv(fc)) != EOF)
704  state_prefix_putc(s, ch);
706  }
707 
708  /* Multiple PGP blocks can exist, so these need to be closed and
709  * unlinked inside the loop. */
710  mutt_file_fclose(&fp_tmp);
712  mutt_file_fclose(&fp_pgp_out);
713  mutt_file_fclose(&fp_pgp_err);
714 
715  if (s->flags & MUTT_DISPLAY)
716  {
717  state_putc(s, '\n');
718  if (needpass)
719  {
720  state_attach_puts(s, _("[-- END PGP MESSAGE --]\n"));
721  if (could_not_decrypt || (decrypt_okay_rc <= -3))
722  mutt_error(_("Could not decrypt PGP message"));
723  else if (decrypt_okay_rc < 0)
724  {
725  /* L10N: You will see this error message if (1) you are decrypting
726  (not encrypting) something and (2) it is a plaintext. So the
727  message does not mean "You failed to encrypt the message." */
728  mutt_error(_("PGP message is not encrypted"));
729  }
730  else
731  mutt_message(_("PGP message successfully decrypted"));
732  }
733  else if (pgp_keyblock)
734  state_attach_puts(s, _("[-- END PGP PUBLIC KEY BLOCK --]\n"));
735  else
736  state_attach_puts(s, _("[-- END PGP SIGNED MESSAGE --]\n"));
737  }
738  }
739  else
740  {
741  /* A traditional PGP part may mix signed and unsigned content */
742  /* XXX we may wish to recode here */
743  if (s->prefix)
744  state_puts(s, s->prefix);
745  state_puts(s, buf);
746  }
747  }
748 
749  rc = 0;
750 
751 out:
752  m->goodsig = (maybe_goodsig && have_any_sigs);
753 
754  if (fp_tmp)
755  {
756  mutt_file_fclose(&fp_tmp);
758  }
759  mutt_file_fclose(&fp_pgp_out);
760  mutt_file_fclose(&fp_pgp_err);
761 
762  mutt_buffer_pool_release(&tmpfname);
763 
764  FREE(&gpgcharset);
765 
766  if (needpass == -1)
767  {
768  state_attach_puts(s, _("[-- Error: could not find beginning of PGP message --]\n\n"));
769  return -1;
770  }
771 
772  return rc;
773 }
774 
782 static bool pgp_check_traditional_one_body(FILE *fp, struct Body *b)
783 {
784  struct Buffer *tempfile = NULL;
785  char buf[8192];
786  bool rc = false;
787 
788  bool sgn = false;
789  bool enc = false;
790  bool key = false;
791 
792  if (b->type != TYPE_TEXT)
793  goto cleanup;
794 
795  tempfile = mutt_buffer_pool_get();
796  mutt_buffer_mktemp(tempfile);
797  if (mutt_decode_save_attachment(fp, b, mutt_buffer_string(tempfile), 0,
798  MUTT_SAVE_NO_FLAGS) != 0)
799  {
800  unlink(mutt_buffer_string(tempfile));
801  goto cleanup;
802  }
803 
804  FILE *fp_tmp = fopen(mutt_buffer_string(tempfile), "r");
805  if (!fp_tmp)
806  {
807  unlink(mutt_buffer_string(tempfile));
808  goto cleanup;
809  }
810 
811  while (fgets(buf, sizeof(buf), fp_tmp))
812  {
813  size_t plen = mutt_str_startswith(buf, "-----BEGIN PGP ");
814  if (plen != 0)
815  {
816  if (mutt_str_startswith(buf + plen, "MESSAGE-----\n"))
817  enc = true;
818  else if (mutt_str_startswith(buf + plen, "SIGNED MESSAGE-----\n"))
819  sgn = true;
820  else if (mutt_str_startswith(buf + plen, "PUBLIC KEY BLOCK-----\n"))
821  key = true;
822  }
823  }
824  mutt_file_fclose(&fp_tmp);
825  unlink(mutt_buffer_string(tempfile));
826 
827  if (!enc && !sgn && !key)
828  goto cleanup;
829 
830  /* fix the content type */
831 
832  mutt_param_set(&b->parameter, "format", "fixed");
833  if (enc)
834  mutt_param_set(&b->parameter, "x-action", "pgp-encrypted");
835  else if (sgn)
836  mutt_param_set(&b->parameter, "x-action", "pgp-signed");
837  else if (key)
838  mutt_param_set(&b->parameter, "x-action", "pgp-keys");
839 
840  rc = true;
841 
842 cleanup:
843  mutt_buffer_pool_release(&tempfile);
844  return rc;
845 }
846 
850 bool pgp_class_check_traditional(FILE *fp, struct Body *b, bool just_one)
851 {
852  bool rc = false;
853  int r;
854  for (; b; b = b->next)
855  {
856  if (!just_one && is_multipart(b))
857  rc = pgp_class_check_traditional(fp, b->parts, false) || rc;
858  else if (b->type == TYPE_TEXT)
859  {
861  if (r)
862  rc = rc || r;
863  else
864  rc = pgp_check_traditional_one_body(fp, b) || rc;
865  }
866 
867  if (just_one)
868  break;
869  }
870 
871  return rc;
872 }
873 
877 int pgp_class_verify_one(struct Body *sigbdy, struct State *s, const char *tempfile)
878 {
879  FILE *fp_pgp_out = NULL;
880  pid_t pid;
881  int badsig = -1;
882  struct Buffer *sigfile = mutt_buffer_pool_get();
883 
884  mutt_buffer_printf(sigfile, "%s.asc", tempfile);
885 
886  FILE *fp_sig = mutt_file_fopen(mutt_buffer_string(sigfile), "w");
887  if (!fp_sig)
888  {
890  goto cleanup;
891  }
892 
893  if (!mutt_file_seek(s->fp_in, sigbdy->offset, SEEK_SET))
894  {
895  mutt_file_fclose(&fp_sig);
896  goto cleanup;
897  }
898  mutt_file_copy_bytes(s->fp_in, fp_sig, sigbdy->length);
899  mutt_file_fclose(&fp_sig);
900 
901  FILE *fp_pgp_err = mutt_file_mkstemp();
902  if (!fp_pgp_err)
903  {
904  mutt_perror(_("Can't create temporary file"));
905  unlink(mutt_buffer_string(sigfile));
906  goto cleanup;
907  }
908 
909  crypt_current_time(s, "PGP");
910 
911  pid = pgp_invoke_verify(NULL, &fp_pgp_out, NULL, -1, -1, fileno(fp_pgp_err),
912  tempfile, mutt_buffer_string(sigfile));
913  if (pid != -1)
914  {
915  if (pgp_copy_checksig(fp_pgp_out, s->fp_out) >= 0)
916  badsig = 0;
917 
918  mutt_file_fclose(&fp_pgp_out);
919  fflush(fp_pgp_err);
920  rewind(fp_pgp_err);
921 
922  if (pgp_copy_checksig(fp_pgp_err, s->fp_out) >= 0)
923  badsig = 0;
924 
925  const int rv = filter_wait(pid);
926  if (rv)
927  badsig = -1;
928 
929  mutt_debug(LL_DEBUG1, "filter_wait returned %d\n", rv);
930  }
931 
932  mutt_file_fclose(&fp_pgp_err);
933 
934  state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
935 
937 
938 cleanup:
939  mutt_buffer_pool_release(&sigfile);
940 
941  mutt_debug(LL_DEBUG1, "returning %d\n", badsig);
942  return badsig;
943 }
944 
950 static void pgp_extract_keys_from_attachment(FILE *fp, struct Body *top)
951 {
952  struct State s = { 0 };
953  struct Buffer *tempfname = mutt_buffer_pool_get();
954 
955  mutt_buffer_mktemp(tempfname);
956  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tempfname), "w");
957  if (!fp_tmp)
958  {
959  mutt_perror(mutt_buffer_string(tempfname));
960  goto cleanup;
961  }
962 
963  s.fp_in = fp;
964  s.fp_out = fp_tmp;
965 
966  mutt_body_handler(top, &s);
967 
968  mutt_file_fclose(&fp_tmp);
969 
972 
974 
975 cleanup:
976  mutt_buffer_pool_release(&tempfname);
977 }
978 
982 void pgp_class_extract_key_from_attachment(FILE *fp, struct Body *top)
983 {
984  if (!fp)
985  {
986  mutt_error(_("Internal error. Please submit a bug report."));
987  return;
988  }
989 
990  mutt_endwin();
991 
992  OptDontHandlePgpKeys = true;
994  OptDontHandlePgpKeys = false;
995 }
996 
1005 static struct Body *pgp_decrypt_part(struct Body *a, struct State *s,
1006  FILE *fp_out, struct Body *p)
1007 {
1008  if (!a || !s || !fp_out || !p)
1009  return NULL;
1010 
1011  char buf[1024];
1012  FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_tmp = NULL;
1013  struct Body *tattach = NULL;
1014  pid_t pid;
1015  int rv;
1016  struct Buffer *pgptmpfile = mutt_buffer_pool_get();
1017 
1018  FILE *fp_pgp_err = mutt_file_mkstemp();
1019  if (!fp_pgp_err)
1020  {
1021  mutt_perror(_("Can't create temporary file"));
1022  goto cleanup;
1023  }
1024 
1025  mutt_buffer_mktemp(pgptmpfile);
1026  fp_pgp_tmp = mutt_file_fopen(mutt_buffer_string(pgptmpfile), "w");
1027  if (!fp_pgp_tmp)
1028  {
1029  mutt_perror(mutt_buffer_string(pgptmpfile));
1030  mutt_file_fclose(&fp_pgp_err);
1031  goto cleanup;
1032  }
1033 
1034  /* Position the stream at the beginning of the body, and send the data to
1035  * the temporary file. */
1036 
1037  if (!mutt_file_seek(s->fp_in, a->offset, SEEK_SET))
1038  {
1039  mutt_file_fclose(&fp_pgp_tmp);
1040  mutt_file_fclose(&fp_pgp_err);
1041  goto cleanup;
1042  }
1043  mutt_file_copy_bytes(s->fp_in, fp_pgp_tmp, a->length);
1044  mutt_file_fclose(&fp_pgp_tmp);
1045 
1046  pid = pgp_invoke_decrypt(&fp_pgp_in, &fp_pgp_out, NULL, -1, -1,
1047  fileno(fp_pgp_err), mutt_buffer_string(pgptmpfile));
1048  if (pid == -1)
1049  {
1050  mutt_file_fclose(&fp_pgp_err);
1051  unlink(mutt_buffer_string(pgptmpfile));
1052  if (s->flags & MUTT_DISPLAY)
1053  {
1054  state_attach_puts(s, _("[-- Error: could not create a PGP subprocess --]\n\n"));
1055  }
1056  goto cleanup;
1057  }
1058 
1059  /* send the PGP passphrase to the subprocess. Never do this if the agent is
1060  * active, because this might lead to a passphrase send as the message. */
1061  if (!pgp_use_gpg_agent())
1062  fputs(PgpPass, fp_pgp_in);
1063  fputc('\n', fp_pgp_in);
1064  mutt_file_fclose(&fp_pgp_in);
1065 
1066  /* Read the output from PGP, and make sure to change CRLF to LF, otherwise
1067  * read_mime_header has a hard time parsing the message. */
1068  while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1069  {
1070  size_t len = mutt_str_len(buf);
1071  if ((len > 1) && (buf[len - 2] == '\r'))
1072  strcpy(buf + len - 2, "\n");
1073  fputs(buf, fp_out);
1074  }
1075 
1076  mutt_file_fclose(&fp_pgp_out);
1077 
1078  rv = filter_wait(pid);
1079  const bool c_pgp_use_gpg_agent = cs_subset_bool(NeoMutt->sub, "pgp_use_gpg_agent");
1080  if (c_pgp_use_gpg_agent)
1082 
1083  mutt_file_unlink(mutt_buffer_string(pgptmpfile));
1084 
1085  fflush(fp_pgp_err);
1086  rewind(fp_pgp_err);
1087  if (pgp_check_decryption_okay(fp_pgp_err) < 0)
1088  {
1089  mutt_error(_("Decryption failed"));
1091  mutt_file_fclose(&fp_pgp_err);
1092  goto cleanup;
1093  }
1094 
1095  if (s->flags & MUTT_DISPLAY)
1096  {
1097  rewind(fp_pgp_err);
1098  if ((pgp_copy_checksig(fp_pgp_err, s->fp_out) == 0) && !rv)
1099  p->goodsig = true;
1100  else
1101  p->goodsig = false;
1102  state_attach_puts(s, _("[-- End of PGP output --]\n\n"));
1103  }
1104  mutt_file_fclose(&fp_pgp_err);
1105 
1106  fflush(fp_out);
1107  rewind(fp_out);
1108 
1109  if (fgetc(fp_out) == EOF)
1110  {
1111  mutt_error(_("Decryption failed"));
1113  goto cleanup;
1114  }
1115 
1116  rewind(fp_out);
1117  const long size = mutt_file_get_size_fp(fp_out);
1118  if (size == 0)
1119  {
1120  goto cleanup;
1121  }
1122 
1123  tattach = mutt_read_mime_header(fp_out, 0);
1124  if (tattach)
1125  {
1126  /* Need to set the length of this body part. */
1127  tattach->length = size - tattach->offset;
1128 
1129  /* See if we need to recurse on this MIME part. */
1130  mutt_parse_part(fp_out, tattach);
1131  }
1132 
1133 cleanup:
1134  mutt_buffer_pool_release(&pgptmpfile);
1135  return tattach;
1136 }
1137 
1141 int pgp_class_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
1142 {
1143  struct State s = { 0 };
1144  struct Body *p = b;
1145  bool need_decode = false;
1146  LOFF_T saved_offset = 0;
1147  size_t saved_length = 0;
1148  FILE *fp_decoded = NULL;
1149  int rc = 0;
1150 
1152  {
1153  b = b->parts->next;
1154  /* Some clients improperly encode the octetstream part. */
1155  if (b->encoding != ENC_7BIT)
1156  need_decode = true;
1157  }
1159  {
1160  b = b->parts->next->next;
1161  need_decode = true;
1162  }
1163  else
1164  return -1;
1165 
1166  s.fp_in = fp_in;
1167 
1168  if (need_decode)
1169  {
1170  saved_offset = b->offset;
1171  saved_length = b->length;
1172 
1173  fp_decoded = mutt_file_mkstemp();
1174  if (!fp_decoded)
1175  {
1176  mutt_perror(_("Can't create temporary file"));
1177  return -1;
1178  }
1179 
1180  if (!mutt_file_seek(s.fp_in, b->offset, SEEK_SET))
1181  {
1182  rc = -1;
1183  goto bail;
1184  }
1185  s.fp_out = fp_decoded;
1186 
1187  mutt_decode_attachment(b, &s);
1188 
1189  fflush(fp_decoded);
1190  b->length = ftello(fp_decoded);
1191  b->offset = 0;
1192  rewind(fp_decoded);
1193  s.fp_in = fp_decoded;
1194  s.fp_out = 0;
1195  }
1196 
1197  *fp_out = mutt_file_mkstemp();
1198  if (!*fp_out)
1199  {
1200  mutt_perror(_("Can't create temporary file"));
1201  rc = -1;
1202  goto bail;
1203  }
1204 
1205  *cur = pgp_decrypt_part(b, &s, *fp_out, p);
1206  if (!*cur)
1207  rc = -1;
1208  rewind(*fp_out);
1209 
1210 bail:
1211  if (need_decode)
1212  {
1213  b->length = saved_length;
1214  b->offset = saved_offset;
1215  mutt_file_fclose(&fp_decoded);
1216  }
1217 
1218  return rc;
1219 }
1220 
1224 int pgp_class_encrypted_handler(struct Body *a, struct State *s)
1225 {
1226  FILE *fp_in = NULL;
1227  struct Body *tattach = NULL;
1228  int rc = 0;
1229 
1230  FILE *fp_out = mutt_file_mkstemp();
1231  if (!fp_out)
1232  {
1233  mutt_perror(_("Can't create temporary file"));
1234  if (s->flags & MUTT_DISPLAY)
1235  {
1236  state_attach_puts(s, _("[-- Error: could not create temporary file --]\n"));
1237  }
1238  return -1;
1239  }
1240 
1241  if (s->flags & MUTT_DISPLAY)
1242  crypt_current_time(s, "PGP");
1243 
1244  tattach = pgp_decrypt_part(a, s, fp_out, a);
1245  if (tattach)
1246  {
1247  if (s->flags & MUTT_DISPLAY)
1248  {
1249  state_attach_puts(s, _("[-- The following data is PGP/MIME encrypted --]\n\n"));
1250  mutt_protected_headers_handler(tattach, s);
1251  }
1252 
1253  /* Store any protected headers in the parent so they can be
1254  * accessed for index updates after the handler recursion is done.
1255  * This is done before the handler to prevent a nested encrypted
1256  * handler from freeing the headers. */
1258  a->mime_headers = tattach->mime_headers;
1259  tattach->mime_headers = NULL;
1260 
1261  fp_in = s->fp_in;
1262  s->fp_in = fp_out;
1263  rc = mutt_body_handler(tattach, s);
1264  s->fp_in = fp_in;
1265 
1266  /* Embedded multipart signed protected headers override the
1267  * encrypted headers. We need to do this after the handler so
1268  * they can be printed in the pager. */
1269  if (mutt_is_multipart_signed(tattach) && tattach->parts && tattach->parts->mime_headers)
1270  {
1272  a->mime_headers = tattach->parts->mime_headers;
1273  tattach->parts->mime_headers = NULL;
1274  }
1275 
1276  /* if a multipart/signed is the _only_ sub-part of a
1277  * multipart/encrypted, cache signature verification
1278  * status. */
1279  if (mutt_is_multipart_signed(tattach) && !tattach->next)
1280  a->goodsig |= tattach->goodsig;
1281 
1282  if (s->flags & MUTT_DISPLAY)
1283  {
1284  state_puts(s, "\n");
1285  state_attach_puts(s, _("[-- End of PGP/MIME encrypted data --]\n"));
1286  }
1287 
1288  mutt_body_free(&tattach);
1289  /* clear 'Invoking...' message, since there's no error */
1290  mutt_message(_("PGP message successfully decrypted"));
1291  }
1292  else
1293  {
1294  mutt_error(_("Could not decrypt PGP message"));
1295  /* void the passphrase, even if it's not necessarily the problem */
1297  rc = -1;
1298  }
1299 
1300  mutt_file_fclose(&fp_out);
1301 
1302  return rc;
1303 }
1304 
1305 /* ----------------------------------------------------------------------------
1306  * Routines for sending PGP/MIME messages.
1307  */
1308 
1312 struct Body *pgp_class_sign_message(struct Body *a, const struct AddressList *from)
1313 {
1314  struct Body *t = NULL, *rv = NULL;
1315  char buf[1024];
1316  FILE *fp_pgp_in = NULL, *fp_pgp_out = NULL, *fp_pgp_err = NULL, *fp_signed = NULL;
1317  bool err = false;
1318  bool empty = true;
1319  pid_t pid;
1320  struct Buffer *sigfile = mutt_buffer_pool_get();
1321  struct Buffer *signedfile = mutt_buffer_pool_get();
1322 
1323  crypt_convert_to_7bit(a); /* Signed data _must_ be in 7-bit format. */
1324 
1325  mutt_buffer_mktemp(sigfile);
1326  FILE *fp_sig = mutt_file_fopen(mutt_buffer_string(sigfile), "w");
1327  if (!fp_sig)
1328  {
1329  goto cleanup;
1330  }
1331 
1332  mutt_buffer_mktemp(signedfile);
1333  fp_signed = mutt_file_fopen(mutt_buffer_string(signedfile), "w");
1334  if (!fp_signed)
1335  {
1336  mutt_perror(mutt_buffer_string(signedfile));
1337  mutt_file_fclose(&fp_sig);
1338  unlink(mutt_buffer_string(sigfile));
1339  goto cleanup;
1340  }
1341 
1342  mutt_write_mime_header(a, fp_signed, NeoMutt->sub);
1343  fputc('\n', fp_signed);
1344  mutt_write_mime_body(a, fp_signed, NeoMutt->sub);
1345  mutt_file_fclose(&fp_signed);
1346 
1347  pid = pgp_invoke_sign(&fp_pgp_in, &fp_pgp_out, &fp_pgp_err, -1, -1, -1,
1348  mutt_buffer_string(signedfile));
1349  if (pid == -1)
1350  {
1351  mutt_perror(_("Can't open PGP subprocess"));
1352  mutt_file_fclose(&fp_sig);
1353  unlink(mutt_buffer_string(sigfile));
1354  unlink(mutt_buffer_string(signedfile));
1355  goto cleanup;
1356  }
1357 
1358  if (!pgp_use_gpg_agent())
1359  fputs(PgpPass, fp_pgp_in);
1360  fputc('\n', fp_pgp_in);
1361  mutt_file_fclose(&fp_pgp_in);
1362 
1363  /* Read back the PGP signature. Also, change MESSAGE=>SIGNATURE as
1364  * recommended for future releases of PGP. */
1365  while (fgets(buf, sizeof(buf) - 1, fp_pgp_out))
1366  {
1367  if (mutt_str_equal("-----BEGIN PGP MESSAGE-----\n", buf))
1368  fputs("-----BEGIN PGP SIGNATURE-----\n", fp_sig);
1369  else if (mutt_str_equal("-----END PGP MESSAGE-----\n", buf))
1370  fputs("-----END PGP SIGNATURE-----\n", fp_sig);
1371  else
1372  fputs(buf, fp_sig);
1373  empty = false; /* got some output, so we're ok */
1374  }
1375 
1376  /* check for errors from PGP */
1377  err = false;
1378  while (fgets(buf, sizeof(buf) - 1, fp_pgp_err))
1379  {
1380  err = true;
1381  fputs(buf, stdout);
1382  }
1383 
1384  const bool c_pgp_check_exit = cs_subset_bool(NeoMutt->sub, "pgp_check_exit");
1385  if (filter_wait(pid) && c_pgp_check_exit)
1386  empty = true;
1387 
1388  mutt_file_fclose(&fp_pgp_err);
1389  mutt_file_fclose(&fp_pgp_out);
1390  unlink(mutt_buffer_string(signedfile));
1391 
1392  if (mutt_file_fclose(&fp_sig) != 0)
1393  {
1394  mutt_perror("fclose");
1395  unlink(mutt_buffer_string(sigfile));
1396  goto cleanup;
1397  }
1398 
1399  if (err)
1401  if (empty)
1402  {
1403  unlink(mutt_buffer_string(sigfile));
1404  /* most likely error is a bad passphrase, so automatically forget it */
1406  goto cleanup; /* fatal error while signing */
1407  }
1408 
1409  t = mutt_body_new();
1410  t->type = TYPE_MULTIPART;
1411  t->subtype = mutt_str_dup("signed");
1412  t->encoding = ENC_7BIT;
1413  t->use_disp = false;
1414  t->disposition = DISP_INLINE;
1415  rv = t;
1416 
1418  mutt_param_set(&t->parameter, "protocol", "application/pgp-signature");
1419  mutt_param_set(&t->parameter, "micalg", pgp_micalg(mutt_buffer_string(sigfile)));
1420 
1421  t->parts = a;
1422 
1423  t->parts->next = mutt_body_new();
1424  t = t->parts->next;
1425  t->type = TYPE_APPLICATION;
1426  t->subtype = mutt_str_dup("pgp-signature");
1427  t->filename = mutt_buffer_strdup(sigfile);
1428  t->use_disp = false;
1429  t->disposition = DISP_NONE;
1430  t->encoding = ENC_7BIT;
1431  t->unlink = true; /* ok to remove this file after sending. */
1432  mutt_param_set(&t->parameter, "name", "signature.asc");
1433 
1434 cleanup:
1435  mutt_buffer_pool_release(&sigfile);
1436  mutt_buffer_pool_release(&signedfile);
1437  return rv;
1438 }
1439 
1443 char *pgp_class_find_keys(const struct AddressList *addrlist, bool oppenc_mode)
1444 {
1445  struct ListHead crypt_hook_list = STAILQ_HEAD_INITIALIZER(crypt_hook_list);
1446  struct ListNode *crypt_hook = NULL;
1447  const char *keyid = NULL;
1448  char *keylist = NULL;
1449  size_t keylist_size = 0;
1450  size_t keylist_used = 0;
1451  struct Address *p = NULL;
1452  struct PgpKeyInfo *k_info = NULL;
1453  const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
1454  char buf[1024];
1455  bool key_selected;
1456  struct AddressList hookal = TAILQ_HEAD_INITIALIZER(hookal);
1457 
1458  struct Address *a = NULL;
1459  TAILQ_FOREACH(a, addrlist, entries)
1460  {
1461  key_selected = false;
1462  mutt_crypt_hook(&crypt_hook_list, a);
1463  crypt_hook = STAILQ_FIRST(&crypt_hook_list);
1464  do
1465  {
1466  p = a;
1467  k_info = NULL;
1468 
1469  if (crypt_hook)
1470  {
1471  keyid = crypt_hook->data;
1472  enum QuadOption ans = MUTT_YES;
1473  const bool c_crypt_confirm_hook = cs_subset_bool(NeoMutt->sub, "crypt_confirm_hook");
1474  if (!oppenc_mode && c_crypt_confirm_hook)
1475  {
1476  snprintf(buf, sizeof(buf), _("Use keyID = \"%s\" for %s?"), keyid, p->mailbox);
1477  ans = mutt_yesorno(buf, MUTT_YES);
1478  }
1479  if (ans == MUTT_YES)
1480  {
1481  if (crypt_is_numerical_keyid(keyid))
1482  {
1483  if (mutt_strn_equal(keyid, "0x", 2))
1484  keyid += 2;
1485  goto bypass_selection; /* you don't see this. */
1486  }
1487 
1488  /* check for e-mail address */
1489  mutt_addrlist_clear(&hookal);
1490  if (strchr(keyid, '@') && (mutt_addrlist_parse(&hookal, keyid) != 0))
1491  {
1492  mutt_addrlist_qualify(&hookal, fqdn);
1493  p = TAILQ_FIRST(&hookal);
1494  }
1495  else if (!oppenc_mode)
1496  {
1498  }
1499  }
1500  else if (ans == MUTT_NO)
1501  {
1502  if (key_selected || STAILQ_NEXT(crypt_hook, entries))
1503  {
1504  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
1505  continue;
1506  }
1507  }
1508  else if (ans == MUTT_ABORT)
1509  {
1510  FREE(&keylist);
1511  mutt_addrlist_clear(&hookal);
1512  mutt_list_free(&crypt_hook_list);
1513  return NULL;
1514  }
1515  }
1516 
1517  if (!k_info)
1518  {
1520  k_info = pgp_getkeybyaddr(p, KEYFLAG_CANENCRYPT, PGP_PUBRING, oppenc_mode);
1521  }
1522 
1523  if (!k_info && !oppenc_mode)
1524  {
1525  snprintf(buf, sizeof(buf), _("Enter keyID for %s: "), p->mailbox);
1527  }
1528 
1529  if (!k_info)
1530  {
1531  FREE(&keylist);
1532  mutt_addrlist_clear(&hookal);
1533  mutt_list_free(&crypt_hook_list);
1534  return NULL;
1535  }
1536 
1537  keyid = pgp_fpr_or_lkeyid(k_info);
1538 
1539  bypass_selection:
1540  keylist_size += mutt_str_len(keyid) + 4;
1541  mutt_mem_realloc(&keylist, keylist_size);
1542  sprintf(keylist + keylist_used, "%s0x%s", keylist_used ? " " : "", keyid);
1543  keylist_used = mutt_str_len(keylist);
1544 
1545  key_selected = true;
1546 
1547  pgp_key_free(&k_info);
1548  mutt_addrlist_clear(&hookal);
1549 
1550  if (crypt_hook)
1551  crypt_hook = STAILQ_NEXT(crypt_hook, entries);
1552 
1553  } while (crypt_hook);
1554 
1555  mutt_list_free(&crypt_hook_list);
1556  }
1557  return keylist;
1558 }
1559 
1566 struct Body *pgp_class_encrypt_message(struct Body *a, char *keylist, bool sign,
1567  const struct AddressList *from)
1568 {
1569  char buf[1024];
1570  FILE *fp_pgp_in = NULL, *fp_tmp = NULL;
1571  struct Body *t = NULL;
1572  int err = 0;
1573  bool empty = false;
1574  pid_t pid;
1575  struct Buffer *tempfile = mutt_buffer_pool_get();
1576  struct Buffer *pgpinfile = mutt_buffer_pool_get();
1577 
1578  mutt_buffer_mktemp(tempfile);
1579  FILE *fp_out = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
1580  if (!fp_out)
1581  {
1582  mutt_perror(mutt_buffer_string(tempfile));
1583  goto cleanup;
1584  }
1585 
1586  FILE *fp_pgp_err = mutt_file_mkstemp();
1587  if (!fp_pgp_err)
1588  {
1589  mutt_perror(_("Can't create temporary file"));
1590  unlink(mutt_buffer_string(tempfile));
1591  mutt_file_fclose(&fp_out);
1592  goto cleanup;
1593  }
1594 
1595  mutt_buffer_mktemp(pgpinfile);
1596  fp_tmp = mutt_file_fopen(mutt_buffer_string(pgpinfile), "w");
1597  if (!fp_tmp)
1598  {
1599  mutt_perror(mutt_buffer_string(pgpinfile));
1600  unlink(mutt_buffer_string(tempfile));
1601  mutt_file_fclose(&fp_out);
1602  mutt_file_fclose(&fp_pgp_err);
1603  goto cleanup;
1604  }
1605 
1606  if (sign)
1608 
1609  mutt_write_mime_header(a, fp_tmp, NeoMutt->sub);
1610  fputc('\n', fp_tmp);
1611  mutt_write_mime_body(a, fp_tmp, NeoMutt->sub);
1612  mutt_file_fclose(&fp_tmp);
1613 
1614  pid = pgp_invoke_encrypt(&fp_pgp_in, NULL, NULL, -1, fileno(fp_out), fileno(fp_pgp_err),
1615  mutt_buffer_string(pgpinfile), keylist, sign);
1616  if (pid == -1)
1617  {
1618  mutt_file_fclose(&fp_out);
1619  mutt_file_fclose(&fp_pgp_err);
1620  unlink(mutt_buffer_string(pgpinfile));
1621  goto cleanup;
1622  }
1623 
1624  if (sign)
1625  {
1626  if (!pgp_use_gpg_agent())
1627  fputs(PgpPass, fp_pgp_in);
1628  fputc('\n', fp_pgp_in);
1629  }
1630  mutt_file_fclose(&fp_pgp_in);
1631 
1632  const bool c_pgp_check_exit = cs_subset_bool(NeoMutt->sub, "pgp_check_exit");
1633  if (filter_wait(pid) && c_pgp_check_exit)
1634  empty = true;
1635 
1636  unlink(mutt_buffer_string(pgpinfile));
1637 
1638  fflush(fp_out);
1639  rewind(fp_out);
1640  if (!empty)
1641  empty = (fgetc(fp_out) == EOF);
1642  mutt_file_fclose(&fp_out);
1643 
1644  fflush(fp_pgp_err);
1645  rewind(fp_pgp_err);
1646  while (fgets(buf, sizeof(buf) - 1, fp_pgp_err))
1647  {
1648  err = 1;
1649  fputs(buf, stdout);
1650  }
1651  mutt_file_fclose(&fp_pgp_err);
1652 
1653  /* pause if there is any error output from PGP */
1654  if (err)
1656 
1657  if (empty)
1658  {
1659  /* fatal error while trying to encrypt message */
1660  if (sign)
1661  pgp_class_void_passphrase(); /* just in case */
1662  unlink(mutt_buffer_string(tempfile));
1663  goto cleanup;
1664  }
1665 
1666  t = mutt_body_new();
1667  t->type = TYPE_MULTIPART;
1668  t->subtype = mutt_str_dup("encrypted");
1669  t->encoding = ENC_7BIT;
1670  t->use_disp = false;
1671  t->disposition = DISP_INLINE;
1672 
1674  mutt_param_set(&t->parameter, "protocol", "application/pgp-encrypted");
1675 
1676  t->parts = mutt_body_new();
1677  t->parts->type = TYPE_APPLICATION;
1678  t->parts->subtype = mutt_str_dup("pgp-encrypted");
1679  t->parts->encoding = ENC_7BIT;
1680 
1681  t->parts->next = mutt_body_new();
1683  t->parts->next->subtype = mutt_str_dup("octet-stream");
1684  t->parts->next->encoding = ENC_7BIT;
1685  t->parts->next->filename = mutt_buffer_strdup(tempfile);
1686  t->parts->next->use_disp = true;
1688  t->parts->next->unlink = true; /* delete after sending the message */
1689  t->parts->next->d_filename = mutt_str_dup("msg.asc"); /* non pgp/mime can save */
1690 
1691 cleanup:
1692  mutt_buffer_pool_release(&tempfile);
1693  mutt_buffer_pool_release(&pgpinfile);
1694  return t;
1695 }
1696 
1700 struct Body *pgp_class_traditional_encryptsign(struct Body *a, SecurityFlags flags, char *keylist)
1701 {
1702  struct Body *b = NULL;
1703  char body_charset[256];
1704  const char *from_charset = NULL;
1705  const char *send_charset = NULL;
1706  bool empty = false;
1707  bool err;
1708  char buf[256];
1709  pid_t pid;
1710  struct Buffer *pgpinfile = mutt_buffer_pool_get();
1711  struct Buffer *pgpoutfile = mutt_buffer_pool_get();
1712 
1713  if (a->type != TYPE_TEXT)
1714  goto cleanup;
1715  if (!mutt_istr_equal(a->subtype, "plain"))
1716  goto cleanup;
1717 
1718  FILE *fp_body = fopen(a->filename, "r");
1719  if (!fp_body)
1720  {
1721  mutt_perror(a->filename);
1722  goto cleanup;
1723  }
1724 
1725  mutt_buffer_mktemp(pgpinfile);
1726  FILE *fp_pgp_in = mutt_file_fopen(mutt_buffer_string(pgpinfile), "w");
1727  if (!fp_pgp_in)
1728  {
1729  mutt_perror(mutt_buffer_string(pgpinfile));
1730  mutt_file_fclose(&fp_body);
1731  goto cleanup;
1732  }
1733 
1734  /* The following code is really correct: If noconv is set,
1735  * a's charset parameter contains the on-disk character set, and
1736  * we have to convert from that to utf-8. If noconv is not set,
1737  * we have to convert from $charset to utf-8. */
1738 
1739  mutt_body_get_charset(a, body_charset, sizeof(body_charset));
1740  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
1741  if (a->noconv)
1742  from_charset = body_charset;
1743  else
1744  from_charset = c_charset;
1745 
1746  if (!mutt_ch_is_us_ascii(body_charset))
1747  {
1748  int c;
1749  struct FgetConv *fc = NULL;
1750 
1751  if (flags & SEC_ENCRYPT)
1752  send_charset = "us-ascii";
1753  else
1754  send_charset = "utf-8";
1755 
1756  /* fromcode is assumed to be correct: we set flags to 0 */
1757  fc = mutt_ch_fgetconv_open(fp_body, from_charset, "utf-8", MUTT_ICONV_NO_FLAGS);
1758  while ((c = mutt_ch_fgetconv(fc)) != EOF)
1759  fputc(c, fp_pgp_in);
1760 
1762  }
1763  else
1764  {
1765  send_charset = "us-ascii";
1766  mutt_file_copy_stream(fp_body, fp_pgp_in);
1767  }
1768  mutt_file_fclose(&fp_body);
1769  mutt_file_fclose(&fp_pgp_in);
1770 
1771  mutt_buffer_mktemp(pgpoutfile);
1772  FILE *fp_pgp_out = mutt_file_fopen(mutt_buffer_string(pgpoutfile), "w+");
1773  FILE *fp_pgp_err = mutt_file_mkstemp();
1774  if (!fp_pgp_out || !fp_pgp_err)
1775  {
1776  mutt_perror(fp_pgp_out ? "Can't create temporary file" : mutt_buffer_string(pgpoutfile));
1777  unlink(mutt_buffer_string(pgpinfile));
1778  if (fp_pgp_out)
1779  {
1780  mutt_file_fclose(&fp_pgp_out);
1781  unlink(mutt_buffer_string(pgpoutfile));
1782  }
1783  mutt_file_fclose(&fp_pgp_err);
1784  goto cleanup;
1785  }
1786 
1787  pid = pgp_invoke_traditional(&fp_pgp_in, NULL, NULL, -1, fileno(fp_pgp_out),
1788  fileno(fp_pgp_err),
1789  mutt_buffer_string(pgpinfile), keylist, flags);
1790  if (pid == -1)
1791  {
1792  mutt_perror(_("Can't invoke PGP"));
1793  mutt_file_fclose(&fp_pgp_out);
1794  mutt_file_fclose(&fp_pgp_err);
1796  unlink(mutt_buffer_string(pgpoutfile));
1797  goto cleanup;
1798  }
1799 
1800  if (pgp_use_gpg_agent())
1801  *PgpPass = '\0';
1802  if (flags & SEC_SIGN)
1803  fprintf(fp_pgp_in, "%s\n", PgpPass);
1804  mutt_file_fclose(&fp_pgp_in);
1805 
1806  const bool c_pgp_check_exit = cs_subset_bool(NeoMutt->sub, "pgp_check_exit");
1807  if (filter_wait(pid) && c_pgp_check_exit)
1808  empty = true;
1809 
1811 
1812  fflush(fp_pgp_out);
1813  fflush(fp_pgp_err);
1814 
1815  rewind(fp_pgp_out);
1816  rewind(fp_pgp_err);
1817 
1818  if (!empty)
1819  empty = (fgetc(fp_pgp_out) == EOF);
1820  mutt_file_fclose(&fp_pgp_out);
1821 
1822  err = false;
1823 
1824  while (fgets(buf, sizeof(buf), fp_pgp_err))
1825  {
1826  err = true;
1827  fputs(buf, stdout);
1828  }
1829 
1830  mutt_file_fclose(&fp_pgp_err);
1831 
1832  if (err)
1834 
1835  if (empty)
1836  {
1837  if (flags & SEC_SIGN)
1838  pgp_class_void_passphrase(); /* just in case */
1839  unlink(mutt_buffer_string(pgpoutfile));
1840  goto cleanup;
1841  }
1842 
1843  b = mutt_body_new();
1844 
1845  b->encoding = ENC_7BIT;
1846 
1847  b->type = TYPE_TEXT;
1848  b->subtype = mutt_str_dup("plain");
1849 
1850  mutt_param_set(&b->parameter, "x-action",
1851  (flags & SEC_ENCRYPT) ? "pgp-encrypted" : "pgp-signed");
1852  mutt_param_set(&b->parameter, "charset", send_charset);
1853 
1854  b->filename = mutt_buffer_strdup(pgpoutfile);
1855 
1856  b->disposition = DISP_NONE;
1857  b->unlink = true;
1858 
1859  b->noconv = true;
1860  b->use_disp = false;
1861 
1862  if (!(flags & SEC_ENCRYPT))
1863  b->encoding = a->encoding;
1864 
1865 cleanup:
1866  mutt_buffer_pool_release(&pgpinfile);
1867  mutt_buffer_pool_release(&pgpoutfile);
1868  return b;
1869 }
1870 
1875 {
1876  struct PgpKeyInfo *p = NULL;
1877  const char *prompt = NULL;
1878  const char *letters = NULL;
1879  const char *choices = NULL;
1880  char promptbuf[1024];
1881  int choice;
1882 
1883  if (!(WithCrypto & APPLICATION_PGP))
1884  return e->security;
1885 
1886  /* If autoinline and no crypto options set, then set inline. */
1887  const bool c_pgp_auto_inline = cs_subset_bool(NeoMutt->sub, "pgp_auto_inline");
1888  if (c_pgp_auto_inline &&
1889  !((e->security & APPLICATION_PGP) && (e->security & (SEC_SIGN | SEC_ENCRYPT))))
1890  {
1891  e->security |= SEC_INLINE;
1892  }
1893 
1894  e->security |= APPLICATION_PGP;
1895 
1896  char *mime_inline = NULL;
1897  if (e->security & SEC_INLINE)
1898  {
1899  /* L10N: The next string MUST have the same highlighted letter
1900  One of them will appear in each of the three strings marked "(inline"), below. */
1901  mime_inline = _("PGP/M(i)ME");
1902  }
1903  else
1904  {
1905  /* L10N: The previous string MUST have the same highlighted letter
1906  One of them will appear in each of the three strings marked "(inline"), below. */
1907  mime_inline = _("(i)nline");
1908  }
1909  /* Opportunistic encrypt is controlling encryption. Allow to toggle
1910  * between inline and mime, but not turn encryption on or off.
1911  * NOTE: "Signing" and "Clearing" only adjust the sign bit, so we have different
1912  * letter choices for those. */
1913  const bool c_crypt_opportunistic_encrypt = cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
1914  if (c_crypt_opportunistic_encrypt && (e->security & SEC_OPPENCRYPT))
1915  {
1916  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
1917  {
1918  snprintf(promptbuf, sizeof(promptbuf),
1919  /* L10N: PGP options (inline) (opportunistic encryption is on) */
1920  _("PGP (s)ign, sign (a)s, %s format, (c)lear, or (o)ppenc mode off?"),
1921  mime_inline);
1922  prompt = promptbuf;
1923  /* L10N: PGP options (inline) (opportunistic encryption is on)
1924  The 'i' is from the "PGP/M(i)ME" or "(i)nline", above. */
1925  letters = _("saico");
1926  choices = "SaiCo";
1927  }
1928  else
1929  {
1930  /* L10N: PGP options (opportunistic encryption is on) */
1931  prompt = _("PGP (s)ign, sign (a)s, (c)lear, or (o)ppenc mode off?");
1932  /* L10N: PGP options (opportunistic encryption is on) */
1933  letters = _("saco");
1934  choices = "SaCo";
1935  }
1936  }
1937  /* Opportunistic encryption option is set, but is toggled off
1938  * for this message. */
1939  else if (c_crypt_opportunistic_encrypt)
1940  {
1941  /* When the message is not selected for signing or encryption, the toggle
1942  * between PGP/MIME and Traditional doesn't make sense. */
1943  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
1944  {
1945  snprintf(promptbuf, sizeof(promptbuf),
1946  /* L10N: PGP options (inline) (opportunistic encryption is off) */
1947  _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, (c)lear, or (o)ppenc mode?"),
1948  mime_inline);
1949  prompt = promptbuf;
1950  /* L10N: PGP options (inline) (opportunistic encryption is off)
1951  The 'i' is from the "PGP/M(i)ME" or "(i)nline", above. */
1952  letters = _("esabico");
1953  choices = "esabicO";
1954  }
1955  else
1956  {
1957  /* L10N: PGP options (opportunistic encryption is off) */
1958  prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, (c)lear, or (o)ppenc mode?");
1959  /* L10N: PGP options (opportunistic encryption is off) */
1960  letters = _("esabco");
1961  choices = "esabcO";
1962  }
1963  }
1964  /* Opportunistic encryption is unset */
1965  else
1966  {
1967  if (e->security & (SEC_ENCRYPT | SEC_SIGN))
1968  {
1969  snprintf(promptbuf, sizeof(promptbuf),
1970  /* L10N: PGP options (inline) */
1971  _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, %s format, or (c)lear?"),
1972  mime_inline);
1973  prompt = promptbuf;
1974  /* L10N: PGP options (inline)
1975  The 'i' is from the "PGP/M(i)ME" or "(i)nline", above. */
1976  letters = _("esabic");
1977  choices = "esabic";
1978  }
1979  else
1980  {
1981  /* L10N: PGP options */
1982  prompt = _("PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, or (c)lear?");
1983  /* L10N: PGP options */
1984  letters = _("esabc");
1985  choices = "esabc";
1986  }
1987  }
1988 
1989  choice = mutt_multi_choice(prompt, letters);
1990  if (choice > 0)
1991  {
1992  switch (choices[choice - 1])
1993  {
1994  case 'a': /* sign (a)s */
1995  OptPgpCheckTrust = false;
1996 
1997  p = pgp_ask_for_key(_("Sign as: "), NULL, KEYFLAG_NO_FLAGS, PGP_SECRING);
1998  if (p)
1999  {
2000  char input_signas[128];
2001  snprintf(input_signas, sizeof(input_signas), "0x%s", pgp_fpr_or_lkeyid(p));
2002  cs_subset_str_string_set(NeoMutt->sub, "pgp_sign_as", input_signas, NULL);
2003  pgp_key_free(&p);
2004 
2005  e->security |= SEC_SIGN;
2006 
2007  crypt_pgp_void_passphrase(); /* probably need a different passphrase */
2008  }
2009  break;
2010 
2011  case 'b': /* (b)oth */
2012  e->security |= (SEC_ENCRYPT | SEC_SIGN);
2013  break;
2014 
2015  case 'C':
2016  e->security &= ~SEC_SIGN;
2017  break;
2018 
2019  case 'c': /* (c)lear */
2020  e->security &= ~(SEC_ENCRYPT | SEC_SIGN);
2021  break;
2022 
2023  case 'e': /* (e)ncrypt */
2024  e->security |= SEC_ENCRYPT;
2025  e->security &= ~SEC_SIGN;
2026  break;
2027 
2028  case 'i': /* toggle (i)nline */
2029  e->security ^= SEC_INLINE;
2030  break;
2031 
2032  case 'O': /* oppenc mode on */
2033  e->security |= SEC_OPPENCRYPT;
2035  break;
2036 
2037  case 'o': /* oppenc mode off */
2038  e->security &= ~SEC_OPPENCRYPT;
2039  break;
2040 
2041  case 'S': /* (s)ign in oppenc mode */
2042  e->security |= SEC_SIGN;
2043  break;
2044 
2045  case 's': /* (s)ign */
2046  e->security &= ~SEC_ENCRYPT;
2047  e->security |= SEC_SIGN;
2048  break;
2049  }
2050  }
2051 
2052  return e->security;
2053 }
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
Email Address Handling.
GUI display the mailboxes in a side panel.
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:432
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:70
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:544
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1025
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1352
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:402
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:463
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:795
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:500
Signing/encryption multiplexor.
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:191
Wrapper around crypto functions.
int mutt_get_field_unbuffered(const char *msg, struct Buffer *buf, CompletionFlags flags)
Ask the user for a string (ignoring macro buffer)
Definition: curs_lib.c:402
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:498
void mutt_need_hard_redraw(void)
Force a hard refresh.
Definition: curs_lib.c:178
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:465
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
time_t mutt_date_add_timeout(time_t now, time_t timeout)
Safely add a timeout to a given time_t value.
Definition: date.c:636
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
char * mutt_body_get_charset(struct Body *b, char *buf, size_t buflen)
Get a body's character set.
Definition: body.c:131
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
Structs that make up an email.
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:260
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:230
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:720
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1569
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
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
#define mutt_file_mkstemp()
Definition: file.h:112
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
int pgp_class_application_handler(struct Body *m, struct State *s)
Implements CryptModuleSpecs::application_handler() -.
Definition: pgp.c:462
int pgp_class_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
Implements CryptModuleSpecs::decrypt_mime() -.
Definition: pgp.c:1141
int pgp_class_encrypted_handler(struct Body *a, struct State *s)
Implements CryptModuleSpecs::encrypted_handler() -.
Definition: pgp.c:1224
char * pgp_class_find_keys(const struct AddressList *addrlist, bool oppenc_mode)
Implements CryptModuleSpecs::find_keys() -.
Definition: pgp.c:1443
bool pgp_class_check_traditional(FILE *fp, struct Body *b, bool just_one)
Implements CryptModuleSpecs::pgp_check_traditional() -.
Definition: pgp.c:850
struct Body * pgp_class_encrypt_message(struct Body *a, char *keylist, bool sign, const struct AddressList *from)
Implements CryptModuleSpecs::pgp_encrypt_message() -.
Definition: pgp.c:1566
void pgp_class_extract_key_from_attachment(FILE *fp, struct Body *top)
Implements CryptModuleSpecs::pgp_extract_key_from_attachment() -.
Definition: pgp.c:982
void pgp_class_invoke_getkeys(struct Address *addr)
Implements CryptModuleSpecs::pgp_invoke_getkeys() -.
Definition: pgpinvoke.c:435
void pgp_class_invoke_import(const char *fname)
Implements CryptModuleSpecs::pgp_invoke_import() -.
Definition: pgpinvoke.c:408
struct Body * pgp_class_traditional_encryptsign(struct Body *a, SecurityFlags flags, char *keylist)
Implements CryptModuleSpecs::pgp_traditional_encryptsign() -.
Definition: pgp.c:1700
SecurityFlags pgp_class_send_menu(struct Email *e)
Implements CryptModuleSpecs::send_menu() -.
Definition: pgp.c:1874
struct Body * pgp_class_sign_message(struct Body *a, const struct AddressList *from)
Implements CryptModuleSpecs::sign_message() -.
Definition: pgp.c:1312
bool pgp_class_valid_passphrase(void)
Implements CryptModuleSpecs::valid_passphrase() -.
Definition: pgp.c:83
int pgp_class_verify_one(struct Body *sigbdy, struct State *s, const char *tempfile)
Implements CryptModuleSpecs::verify_one() -.
Definition: pgp.c:877
void pgp_class_void_passphrase(void)
Implements CryptModuleSpecs::void_passphrase() -.
Definition: pgp.c:74
int mutt_protected_headers_handler(struct Body *b, struct State *s)
Process a protected header - Implements handler_t -.
Definition: crypt.c:1095
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#define mutt_perror(...)
Definition: logging.h:88
Convenience wrapper for the gui headers.
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email's attachment.
Definition: handler.c:1867
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
Decide how to display email content.
int mutt_write_mime_header(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Create a MIME header.
Definition: header.c:760
long cs_subset_long(const struct ConfigSubset *sub, const char *name)
Get a long config item by name.
Definition: helpers.c:121
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
void mutt_crypt_hook(struct ListHead *list, struct Address *addr)
Find crypto hooks for an Address.
Definition: hook.c:807
Parse and execute user-defined hooks.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define FREE(x)
Definition: memory.h:40
@ ENC_7BIT
7-bit text
Definition: mime.h:49
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
@ DISP_ATTACH
Content is attached.
Definition: mime.h:63
@ DISP_INLINE
Content is inline.
Definition: mime.h:62
@ DISP_NONE
No preferred disposition.
Definition: mime.h:65
#define is_multipart(body)
Definition: mime.h:82
void mutt_generate_boundary(struct ParameterList *pl)
Create a unique boundary id for a MIME part.
Definition: multipart.c:86
bool mutt_ch_check_charset(const char *cs, bool strict)
Does iconv understand a character set?
Definition: charset.c:817
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
char * mutt_ch_fgetconvs(char *buf, size_t buflen, struct FgetConv *fc)
Convert a file's charset into a string buffer.
Definition: charset.c:969
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
#define mutt_ch_is_us_ascii(str)
Definition: charset.h:96
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:71
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:631
void state_prefix_putc(struct State *s, char c)
Write a prefixed character to the state.
Definition: state.c:161
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 state_set_prefix(state)
Definition: state.h:54
#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
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:796
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
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:473
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:599
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_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:544
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
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
Many unsorted constants and some structs.
#define MUTT_COMP_PASS
Password mode (no echo)
Definition: mutt.h:63
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1031
@ MUTT_SAVE_NO_FLAGS
No flags set.
Definition: mutt_attach.h:57
Some miscellaneous functions.
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:85
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:74
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:86
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define KEYFLAG_CANENCRYPT
Key is suitable for encryption.
Definition: lib.h:128
#define KEYFLAG_SUBKEY
Key is a subkey.
Definition: lib.h:134
#define KEYFLAG_NO_FLAGS
No flags are set.
Definition: lib.h:126
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define WithCrypto
Definition: lib.h:116
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
Handling of global boolean variables.
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:41
bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: options.h:54
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1737
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1318
char * pgp_fpr_or_lkeyid(struct PgpKeyInfo *k)
Get the fingerprint or long keyid.
Definition: pgp.c:231
static void pgp_extract_keys_from_attachment(FILE *fp, struct Body *top)
Extract pgp keys from messages/attachments.
Definition: pgp.c:950
static struct Body * pgp_decrypt_part(struct Body *a, struct State *s, FILE *fp_out, struct Body *p)
Decrypt part of a PGP message.
Definition: pgp.c:1005
static int pgp_check_pgp_decryption_okay_regex(FILE *fp_in)
Check PGP output to look for successful outcome.
Definition: pgp.c:298
char PgpPass[1024]
Definition: pgp.c:68
static char * pgp_fingerprint(struct PgpKeyInfo *k)
Get the key's fingerprint.
Definition: pgp.c:213
static void pgp_copy_clearsigned(FILE *fp_in, struct State *s, char *charset)
Copy a clearsigned message, stripping the signature.
Definition: pgp.c:413
char * pgp_long_keyid(struct PgpKeyInfo *k)
Get a key's long id.
Definition: pgp.c:162
time_t PgpExptime
Definition: pgp.c:69
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:248
char * pgp_keyid(struct PgpKeyInfo *k)
Get the ID of the main (parent) key.
Definition: pgp.c:201
char * pgp_this_keyid(struct PgpKeyInfo *k)
Get the ID of this key.
Definition: pgp.c:188
static struct PgpKeyInfo * key_parent(struct PgpKeyInfo *k)
Find a key's parent (if it's a subkey)
Definition: pgp.c:148
bool pgp_use_gpg_agent(void)
Does the user want to use the gpg agent?
Definition: pgp.c:124
char * pgp_short_keyid(struct PgpKeyInfo *k)
Get a key's short id.
Definition: pgp.c:174
static int pgp_check_decryption_okay(FILE *fp_in)
Check GPG output for status codes.
Definition: pgp.c:350
static bool pgp_check_traditional_one_body(FILE *fp, struct Body *b)
Check the body of an inline PGP message.
Definition: pgp.c:782
PGP sign, encrypt, check routines.
pid_t pgp_invoke_encrypt(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, const char *uids, bool sign)
Use PGP to encrypt a file.
Definition: pgpinvoke.c:350
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
pid_t pgp_invoke_traditional(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, const char *uids, SecurityFlags flags)
Use PGP to create in inline-signed message.
Definition: pgpinvoke.c:385
pid_t pgp_invoke_sign(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)
Use PGP to sign a file.
Definition: pgpinvoke.c:325
pid_t pgp_invoke_verify(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, const char *sig_fname)
Use PGP to verify a message.
Definition: pgpinvoke.c:278
pid_t pgp_invoke_decrypt(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)
Use PGP to decrypt a file.
Definition: pgpinvoke.c:302
Wrapper around calls to external PGP program.
struct PgpKeyInfo * pgp_getkeybystr(const char *cp, KeyFlags abilities, enum PgpRing keyring)
Find a PGP key by string.
Definition: pgpkey.c:491
struct PgpKeyInfo * pgp_getkeybyaddr(struct Address *a, KeyFlags abilities, enum PgpRing keyring, bool oppenc_mode)
Find a PGP key by address.
Definition: pgpkey.c:355
struct PgpKeyInfo * pgp_ask_for_key(char *tag, char *whatfor, KeyFlags abilities, enum PgpRing keyring)
Ask the user for a PGP key.
Definition: pgpkey.c:180
PGP key management routines.
@ PGP_SECRING
Secret keys.
Definition: pgpkey.h:40
@ PGP_PUBRING
Public keys.
Definition: pgpkey.h:39
void pgp_key_free(struct PgpKeyInfo **kpp)
Free a PGP key info.
Definition: pgplib.c:199
Misc PGP helper routines.
const char * pgp_micalg(const char *fname)
Find the hash algorithm of a file.
Definition: pgpmicalg.c:227
Identify the hash algorithm from a PGP signature.
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
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
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
Ask the user a question.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:54
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
int mutt_write_mime_body(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Write a MIME part.
Definition: body.c:314
Convenience wrapper for the send headers.
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:698
Key value store.
An email address.
Definition: address.h:36
char * mailbox
Mailbox and host address.
Definition: address.h:38
The body of an email.
Definition: body.h:36
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
bool noconv
Don't do character set conversion.
Definition: body.h:46
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:67
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:75
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:47
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
struct Body * next
next attachment in the list
Definition: body.h:71
char * subtype
content-type subtype
Definition: body.h:60
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
bool goodsig
Good cryptographic signature.
Definition: body.h:45
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:34
The envelope/body of an email.
Definition: email.h:37
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
Cursor for converting a file's encoding.
Definition: charset.h:41
FILE * fp
Definition: charset.h:42
char * p
Definition: charset.h:46
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Information about a PGP key.
Definition: pgplib.h:47
char * keyid
Definition: pgplib.h:48
KeyFlags flags
Definition: pgplib.h:51
char * fingerprint
Definition: pgplib.h:49
struct PgpKeyInfo * parent
Definition: pgplib.h:56
Cached regular expression.
Definition: regex3.h:89
regex_t * regex
compiled expression
Definition: regex3.h:91
Keep track when processing files.
Definition: state.h:46
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
FILE * fp_out
File to write to.
Definition: state.h:48
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
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:408