NeoMutt  2019-12-07-60-g0cfa53
Teaching an old dog new tricks
DOXYGEN
crypt.c
Go to the documentation of this file.
1 
35 #include "config.h"
36 #include <locale.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include "mutt/mutt.h"
41 #include "address/lib.h"
42 #include "config/lib.h"
43 #include "email/lib.h"
44 #include "gui/lib.h"
45 #include "mutt.h"
46 #include "crypt.h"
47 #include "alias.h"
48 #include "copy.h"
49 #include "cryptglue.h"
50 #include "globals.h"
51 #include "handler.h"
52 #include "mutt_parse.h"
53 #include "muttlib.h"
54 #include "ncrypt.h"
55 #include "options.h"
56 #include "send.h"
57 #include "sendlib.h"
58 #include "state.h"
59 #ifdef USE_AUTOCRYPT
60 #include "autocrypt/autocrypt.h"
61 #endif
62 
63 struct Mailbox;
64 
65 /* These Config Variables are only used in ncrypt/crypt.c */
66 bool C_CryptTimestamp;
67 unsigned char C_PgpEncryptSelf;
68 unsigned char C_PgpMimeAuto;
72 unsigned char C_SmimeEncryptSelf;
74 
82 void crypt_current_time(struct State *s, const char *app_name)
83 {
84  char p[256], tmp[256];
85 
86  if (!WithCrypto)
87  return;
88 
89  if (C_CryptTimestamp)
90  {
91  mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), MUTT_DATE_NOW);
92  }
93  else
94  *p = '\0';
95 
96  snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
97  state_attach_puts(s, tmp);
98 }
99 
104 {
107 
110 
111  if (WithCrypto)
112  {
113  /* L10N: Due to the implementation details (e.g. some passwords are managed
114  by gpg-agent) we can't know whether we forgot zero, 1, 12, ...
115  passwords. So in English we use "Passphrases". Your language might
116  have other means to express this. */
117  mutt_message(_("Passphrases forgotten"));
118  }
119 }
120 
121 #ifndef DEBUG
122 #include <sys/resource.h>
126 static void disable_coredumps(void)
127 {
128  struct rlimit rl = { 0, 0 };
129  static bool done = false;
130 
131  if (!done)
132  {
133  setrlimit(RLIMIT_CORE, &rl);
134  done = true;
135  }
136 }
137 #endif
138 
146 {
147  bool rc = false;
148 
149 #ifndef DEBUG
150  disable_coredumps();
151 #endif
152 
153  if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & APPLICATION_PGP))
155 
156  if (((WithCrypto & APPLICATION_SMIME) != 0) && (flags & APPLICATION_SMIME))
158 
159  return rc;
160 }
161 
170 int mutt_protect(struct Email *e, char *keylist, bool postpone)
171 {
172  struct Body *pbody = NULL, *tmp_pbody = NULL;
173  struct Body *tmp_smime_pbody = NULL;
174  struct Body *tmp_pgp_pbody = NULL;
175  bool has_retainable_sig = false;
176 
177  if (!WithCrypto)
178  return -1;
179 
180  int security = e->security;
181  int sign = security & (SEC_AUTOCRYPT | SEC_SIGN);
182  if (postpone)
183  {
184  sign = SEC_NO_FLAGS;
185  security &= ~SEC_SIGN;
186  }
187 
188  if (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) && !sign)
189  return 0;
190 
191  if (sign && !(security & SEC_AUTOCRYPT) && !crypt_valid_passphrase(security))
192  return -1;
193 
194  if (((WithCrypto & APPLICATION_PGP) != 0) && !(security & SEC_AUTOCRYPT) &&
195  ((security & PGP_INLINE) == PGP_INLINE))
196  {
197  if ((e->content->type != TYPE_TEXT) ||
198  (mutt_str_strcasecmp(e->content->subtype, "plain") != 0))
199  {
201  _("Inline PGP can't be used with attachments. "
202  "Revert to PGP/MIME?")) != MUTT_YES)
203  {
204  mutt_error(
205  _("Mail not sent: inline PGP can't be used with attachments"));
206  return -1;
207  }
208  }
209  else if (mutt_str_strcasecmp("flowed", mutt_param_get(&e->content->parameter, "format")) == 0)
210  {
212  _("Inline PGP can't be used with format=flowed. "
213  "Revert to PGP/MIME?"))) != MUTT_YES)
214  {
215  mutt_error(
216  _("Mail not sent: inline PGP can't be used with format=flowed"));
217  return -1;
218  }
219  }
220  else
221  {
222  /* they really want to send it inline... go for it */
223  if (!isendwin())
224  {
225  mutt_endwin();
226  puts(_("Invoking PGP..."));
227  }
228  pbody = crypt_pgp_traditional_encryptsign(e->content, security, keylist);
229  if (pbody)
230  {
231  e->content = pbody;
232  return 0;
233  }
234 
235  /* otherwise inline won't work...ask for revert */
236  if (query_quadoption(
238  _("Message can't be sent inline. Revert to using PGP/MIME?")) != MUTT_YES)
239  {
240  mutt_error(_("Mail not sent"));
241  return -1;
242  }
243  }
244 
245  /* go ahead with PGP/MIME */
246  }
247 
248  if (!isendwin())
249  mutt_endwin();
250 
252  tmp_smime_pbody = e->content;
253  if (WithCrypto & APPLICATION_PGP)
254  tmp_pgp_pbody = e->content;
255 
256  if (C_CryptUsePka && sign)
257  {
258  /* Set sender (necessary for e.g. PKA). */
259  const char *mailbox = NULL;
260  struct Address *from = TAILQ_FIRST(&e->env->from);
261  bool free_from = false;
262 
263  if (!from)
264  {
265  free_from = true;
266  from = mutt_default_from();
267  }
268 
269  mailbox = from->mailbox;
270  if (!mailbox && C_EnvelopeFromAddress)
271  mailbox = C_EnvelopeFromAddress->mailbox;
272 
273  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
274  crypt_smime_set_sender(mailbox);
275  else if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
276  crypt_pgp_set_sender(mailbox);
277 
278  if (free_from)
279  mutt_addr_free(&from);
280  }
281 
283  {
284  struct Envelope *protected_headers = mutt_env_new();
285  mutt_str_replace(&protected_headers->subject, e->env->subject);
286  /* Note: if other headers get added, such as to, cc, then a call to
287  * mutt_env_to_intl() will need to be added here too. */
288  mutt_prepare_envelope(protected_headers, 0);
289 
291  e->content->mime_headers = protected_headers;
292  }
293 
294  /* A note about e->content->mime_headers. If postpone or send
295  * fails, the mime_headers is cleared out before returning to the
296  * compose menu. So despite the "robustness" code above and in the
297  * gen_gossip_list function below, mime_headers will not be set when
298  * entering mutt_protect().
299  *
300  * This is important to note because the user could toggle
301  * $crypt_protected_headers_write or $autocrypt off back in the
302  * compose menu. We don't want mutt_write_rfc822_header() to write
303  * stale data from one option if the other is set.
304  */
305 #ifdef USE_AUTOCRYPT
306  if (C_Autocrypt && !postpone && (security & SEC_AUTOCRYPT))
307  {
309  }
310 #endif
311 
312  if (sign)
313  {
314  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
315  {
316  tmp_pbody = crypt_smime_sign_message(e->content, &e->env->from);
317  if (!tmp_pbody)
318  goto bail;
319  pbody = tmp_pbody;
320  tmp_smime_pbody = tmp_pbody;
321  }
322 
323  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP) &&
324  (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) || C_PgpRetainableSigs))
325  {
326  tmp_pbody = crypt_pgp_sign_message(e->content, &e->env->from);
327  if (!tmp_pbody)
328  goto bail;
329 
330  has_retainable_sig = true;
331  sign = SEC_NO_FLAGS;
332  pbody = tmp_pbody;
333  tmp_pgp_pbody = tmp_pbody;
334  }
335 
336  if ((WithCrypto != 0) && (security & APPLICATION_SMIME) && (security & APPLICATION_PGP))
337  {
338  /* here comes the draft ;-) */
339  }
340  }
341 
342  if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
343  {
344  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
345  {
346  tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
347  if (!tmp_pbody)
348  {
349  /* signed ? free it! */
350  goto bail;
351  }
352  /* free tmp_body if messages was signed AND encrypted ... */
353  if ((tmp_smime_pbody != e->content) && (tmp_smime_pbody != tmp_pbody))
354  {
355  /* detach and don't delete e->content,
356  * which tmp_smime_pbody->parts after signing. */
357  tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
358  e->content->next = NULL;
359  mutt_body_free(&tmp_smime_pbody);
360  }
361  pbody = tmp_pbody;
362  }
363 
364  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
365  {
366  pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign, &e->env->from);
367  if (!pbody)
368  {
369  /* did we perform a retainable signature? */
370  if (has_retainable_sig)
371  {
372  /* remove the outer multipart layer */
373  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
374  /* get rid of the signature */
375  mutt_body_free(&tmp_pgp_pbody->next);
376  }
377 
378  goto bail;
379  }
380 
381  /* destroy temporary signature envelope when doing retainable
382  * signatures.
383 
384  */
385  if (has_retainable_sig)
386  {
387  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
388  mutt_body_free(&tmp_pgp_pbody->next);
389  }
390  }
391  }
392 
393  if (pbody)
394  {
395  e->content = pbody;
396  return 0;
397  }
398 
399 bail:
401  return -1;
402 }
403 
411 {
412  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
413  (mutt_str_strcasecmp(b->subtype, "signed") != 0))
414  {
415  return SEC_NO_FLAGS;
416  }
417 
418  char *p = mutt_param_get(&b->parameter, "protocol");
419  if (!p)
420  return SEC_NO_FLAGS;
421 
422  if (!(mutt_str_strcasecmp(p, "multipart/mixed") != 0))
423  return SEC_SIGN;
424 
425  if (((WithCrypto & APPLICATION_PGP) != 0) &&
426  !(mutt_str_strcasecmp(p, "application/pgp-signature") != 0))
427  {
428  return PGP_SIGN;
429  }
430 
431  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
432  !(mutt_str_strcasecmp(p, "application/x-pkcs7-signature") != 0))
433  {
434  return SMIME_SIGN;
435  }
436  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
437  !(mutt_str_strcasecmp(p, "application/pkcs7-signature") != 0))
438  {
439  return SMIME_SIGN;
440  }
441 
442  return SEC_NO_FLAGS;
443 }
444 
452 {
453  if ((WithCrypto & APPLICATION_PGP) == 0)
454  return SEC_NO_FLAGS;
455 
456  char *p = NULL;
457 
458  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
459  (mutt_str_strcasecmp(b->subtype, "encrypted") != 0) ||
460  !(p = mutt_param_get(&b->parameter, "protocol")) ||
461  (mutt_str_strcasecmp(p, "application/pgp-encrypted") != 0))
462  {
463  return SEC_NO_FLAGS;
464  }
465 
466  return PGP_ENCRYPT;
467 }
468 
476 {
478  return 0;
479 
480  b = b->parts;
481  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
482  (mutt_str_strcasecmp(b->subtype, "pgp-encrypted") != 0))
483  {
484  return 0;
485  }
486 
487  b = b->next;
488  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
489  (mutt_str_strcasecmp(b->subtype, "octet-stream") != 0))
490  {
491  return 0;
492  }
493 
494  return PGP_ENCRYPT;
495 }
496 
513 {
514  if (!(WithCrypto & APPLICATION_PGP))
515  return SEC_NO_FLAGS;
516 
517  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
518  (mutt_str_strcasecmp(b->subtype, "mixed") != 0))
519  {
520  return SEC_NO_FLAGS;
521  }
522 
523  b = b->parts;
524  if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
525  (mutt_str_strcasecmp(b->subtype, "plain") != 0) || (b->length != 0))
526  {
527  return SEC_NO_FLAGS;
528  }
529 
530  b = b->next;
531  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
532  (mutt_str_strcasecmp(b->subtype, "pgp-encrypted") != 0))
533  {
534  return SEC_NO_FLAGS;
535  }
536 
537  b = b->next;
538  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
539  (mutt_str_strcasecmp(b->subtype, "octet-stream") != 0))
540  {
541  return SEC_NO_FLAGS;
542  }
543 
544  b = b->next;
545  if (b)
546  return SEC_NO_FLAGS;
547 
548  return PGP_ENCRYPT;
549 }
550 
558 {
560  char *p = NULL;
561 
562  if (m->type == TYPE_APPLICATION)
563  {
564  if ((mutt_str_strcasecmp(m->subtype, "pgp") == 0) ||
565  (mutt_str_strcasecmp(m->subtype, "x-pgp-message") == 0))
566  {
567  p = mutt_param_get(&m->parameter, "x-action");
568  if (p && ((mutt_str_strcasecmp(p, "sign") == 0) ||
569  (mutt_str_strcasecmp(p, "signclear") == 0)))
570  {
571  t |= PGP_SIGN;
572  }
573 
574  p = mutt_param_get(&m->parameter, "format");
575  if (p && (mutt_str_strcasecmp(p, "keys-only") == 0))
576  {
577  t |= PGP_KEY;
578  }
579 
580  if (t == SEC_NO_FLAGS)
581  t |= PGP_ENCRYPT; /* not necessarily correct, but... */
582  }
583 
584  if (mutt_str_strcasecmp(m->subtype, "pgp-signed") == 0)
585  t |= PGP_SIGN;
586 
587  if (mutt_str_strcasecmp(m->subtype, "pgp-keys") == 0)
588  t |= PGP_KEY;
589  }
590  else if ((m->type == TYPE_TEXT) && (mutt_str_strcasecmp("plain", m->subtype) == 0))
591  {
592  if (((p = mutt_param_get(&m->parameter, "x-mutt-action")) ||
593  (p = mutt_param_get(&m->parameter, "x-action")) ||
594  (p = mutt_param_get(&m->parameter, "action"))) &&
595  mutt_str_startswith(p, "pgp-sign", CASE_IGNORE))
596  {
597  t |= PGP_SIGN;
598  }
599  else if (p && mutt_str_startswith(p, "pgp-encrypt", CASE_IGNORE))
600  t |= PGP_ENCRYPT;
601  else if (p && mutt_str_startswith(p, "pgp-keys", CASE_IGNORE))
602  t |= PGP_KEY;
603  }
604  if (t)
605  t |= PGP_INLINE;
606 
607  return t;
608 }
609 
617 {
618  if (!m)
619  return SEC_NO_FLAGS;
620 
621  if (((m->type & TYPE_APPLICATION) == 0) || !m->subtype)
622  return SEC_NO_FLAGS;
623 
624  char *t = NULL;
625  bool complain = false;
626  /* S/MIME MIME types don't need x- anymore, see RFC2311 */
627  if ((mutt_str_strcasecmp(m->subtype, "x-pkcs7-mime") == 0) ||
628  (mutt_str_strcasecmp(m->subtype, "pkcs7-mime") == 0))
629  {
630  t = mutt_param_get(&m->parameter, "smime-type");
631  if (t)
632  {
633  if (mutt_str_strcasecmp(t, "enveloped-data") == 0)
634  return SMIME_ENCRYPT;
635  if (mutt_str_strcasecmp(t, "signed-data") == 0)
636  return SMIME_SIGN | SMIME_OPAQUE;
637  return SEC_NO_FLAGS;
638  }
639  /* Netscape 4.7 uses
640  * Content-Description: S/MIME Encrypted Message
641  * instead of Content-Type parameter */
642  if (mutt_str_strcasecmp(m->description, "S/MIME Encrypted Message") == 0)
643  return SMIME_ENCRYPT;
644  complain = true;
645  }
646  else if (mutt_str_strcasecmp(m->subtype, "octet-stream") != 0)
647  return SEC_NO_FLAGS;
648 
649  t = mutt_param_get(&m->parameter, "name");
650 
651  if (!t)
652  t = m->d_filename;
653  if (!t)
654  t = m->filename;
655  if (!t)
656  {
657  if (complain)
658  {
659  mutt_message(
660  _("S/MIME messages with no hints on content are unsupported"));
661  }
662  return SEC_NO_FLAGS;
663  }
664 
665  /* no .p7c, .p10 support yet. */
666 
667  int len = mutt_str_strlen(t) - 4;
668  if ((len > 0) && (*(t + len) == '.'))
669  {
670  len++;
671  if (mutt_str_strcasecmp((t + len), "p7m") == 0)
672  {
673  /* Not sure if this is the correct thing to do, but
674  * it's required for compatibility with Outlook */
675  return SMIME_SIGN | SMIME_OPAQUE;
676  }
677  else if (mutt_str_strcasecmp((t + len), "p7s") == 0)
678  return SMIME_SIGN | SMIME_OPAQUE;
679  }
680 
681  return SEC_NO_FLAGS;
682 }
683 
693 {
694  if (!WithCrypto || !m)
695  return SEC_NO_FLAGS;
696 
698 
699  if (m->type == TYPE_APPLICATION)
700  {
702  rc |= mutt_is_application_pgp(m);
703 
705  {
706  rc |= mutt_is_application_smime(m);
707  if (rc && m->goodsig)
708  rc |= SEC_GOODSIGN;
709  if (rc && m->badsig)
710  rc |= SEC_BADSIGN;
711  }
712  }
713  else if (((WithCrypto & APPLICATION_PGP) != 0) && (m->type == TYPE_TEXT))
714  {
715  rc |= mutt_is_application_pgp(m);
716  if (rc && m->goodsig)
717  rc |= SEC_GOODSIGN;
718  }
719 
720  if (m->type == TYPE_MULTIPART)
721  {
723  rc |= mutt_is_multipart_signed(m);
725 
726  if (rc && m->goodsig)
727  rc |= SEC_GOODSIGN;
728 #ifdef USE_AUTOCRYPT
729  if (rc && m->is_autocrypt)
730  rc |= SEC_AUTOCRYPT;
731 #endif
732  }
733 
734  if ((m->type == TYPE_MULTIPART) || (m->type == TYPE_MESSAGE))
735  {
736  SecurityFlags u = m->parts ? SEC_ALL_FLAGS : SEC_NO_FLAGS; /* Bits set in all parts */
737  SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */
738 
739  for (struct Body *b = m->parts; b; b = b->next)
740  {
741  const SecurityFlags v = crypt_query(b);
742  u &= v;
743  w |= v;
744  }
745  rc |= u | (w & ~SEC_GOODSIGN);
746 
747  if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
748  rc |= SEC_PARTSIGN;
749  }
750 
751  return rc;
752 }
753 
764 int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
765 {
766  if (!WithCrypto)
767  return -1;
768 
769  FILE *fp = mutt_file_fopen(tempfile, "w");
770  if (!fp)
771  {
772  mutt_perror(tempfile);
773  return -1;
774  }
775 
776  fseeko(s->fp_in, a->hdr_offset, SEEK_SET);
777  size_t bytes = a->length + a->offset - a->hdr_offset;
778  bool hadcr = false;
779  while (bytes > 0)
780  {
781  const int c = fgetc(s->fp_in);
782  if (c == EOF)
783  break;
784 
785  bytes--;
786 
787  if (c == '\r')
788  hadcr = true;
789  else
790  {
791  if ((c == '\n') && !hadcr)
792  fputc('\r', fp);
793 
794  hadcr = false;
795  }
796 
797  fputc(c, fp);
798  }
799  mutt_file_fclose(&fp);
800 
801  return 0;
802 }
803 
809 {
810  if (!WithCrypto)
811  return;
812 
813  while (a)
814  {
815  if (a->type == TYPE_MULTIPART)
816  {
817  if (a->encoding != ENC_7BIT)
818  {
819  a->encoding = ENC_7BIT;
821  }
822  else if (((WithCrypto & APPLICATION_PGP) != 0) && C_PgpStrictEnc)
824  }
825  else if ((a->type == TYPE_MESSAGE) &&
826  (mutt_str_strcasecmp(a->subtype, "delivery-status") != 0))
827  {
828  if (a->encoding != ENC_7BIT)
829  mutt_message_to_7bit(a, NULL);
830  }
831  else if (a->encoding == ENC_8BIT)
833  else if (a->encoding == ENC_BINARY)
834  a->encoding = ENC_BASE64;
835  else if (a->content && (a->encoding != ENC_BASE64) &&
836  (a->content->from || (a->content->space && C_PgpStrictEnc)))
837  {
839  }
840  a = a->next;
841  }
842 }
843 
851 void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
852 {
853  if (!WithCrypto)
854  return;
855 
856  struct Buffer *tempfname = mutt_buffer_pool_get();
857  mutt_buffer_mktemp(tempfname);
858  FILE *fp_out = mutt_file_fopen(mutt_b2s(tempfname), "w");
859  if (!fp_out)
860  {
861  mutt_perror(mutt_b2s(tempfname));
862  goto cleanup;
863  }
864 
866  OptDontHandlePgpKeys = true;
867 
868  struct EmailNode *en = NULL;
869  STAILQ_FOREACH(en, el, entries)
870  {
871  struct Email *e = en->email;
872 
875  {
876  mutt_file_fclose(&fp_out);
877  break;
878  }
879 
880  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
881  {
883  fflush(fp_out);
884 
885  mutt_endwin();
886  puts(_("Trying to extract PGP keys...\n"));
887  crypt_pgp_invoke_import(mutt_b2s(tempfname));
888  }
889 
890  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
891  {
892  if (e->security & SEC_ENCRYPT)
893  {
895  CH_NO_FLAGS, 0);
896  }
897  else
899  fflush(fp_out);
900 
901  char *mbox = NULL;
902  if (!TAILQ_EMPTY(&e->env->from))
903  {
905  mbox = TAILQ_FIRST(&e->env->from)->mailbox;
906  }
907  else if (!TAILQ_EMPTY(&e->env->sender))
908  {
910  mbox = TAILQ_FIRST(&e->env->sender)->mailbox;
911  }
912  if (mbox)
913  {
914  mutt_endwin();
915  puts(_("Trying to extract S/MIME certificates..."));
916  crypt_smime_invoke_import(mutt_b2s(tempfname), mbox);
917  }
918  }
919 
920  rewind(fp_out);
921  }
922 
923  mutt_file_fclose(&fp_out);
924  if (isendwin())
926 
927  mutt_file_unlink(mutt_b2s(tempfname));
928 
929  if (WithCrypto & APPLICATION_PGP)
930  OptDontHandlePgpKeys = false;
931 
932 cleanup:
933  mutt_buffer_pool_release(&tempfname);
934 }
935 
950 int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
951 {
952  if (!WithCrypto)
953  return 0;
954 
955  struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
956  const char *fqdn = mutt_fqdn(true);
957  char *self_encrypt = NULL;
958 
959  /* Do a quick check to make sure that we can find all of the encryption
960  * keys if the user has requested this service. */
961 
962  *keylist = NULL;
963 
964 #ifdef USE_AUTOCRYPT
965  if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
966  {
968  return -1;
969  return 0;
970  }
971 #endif
972 
974  OptPgpCheckTrust = true;
975 
976  mutt_addrlist_copy(&addrlist, &e->env->to, false);
977  mutt_addrlist_copy(&addrlist, &e->env->cc, false);
978  mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
979  mutt_addrlist_qualify(&addrlist, fqdn);
980  mutt_addrlist_dedupe(&addrlist);
981 
982  if (oppenc_mode || (e->security & SEC_ENCRYPT))
983  {
984  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
985  {
986  *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
987  if (!*keylist)
988  {
989  mutt_addrlist_clear(&addrlist);
990  return -1;
991  }
992  OptPgpCheckTrust = false;
994  self_encrypt = C_PgpDefaultKey;
995  }
996  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
997  {
998  *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
999  if (!*keylist)
1000  {
1001  mutt_addrlist_clear(&addrlist);
1002  return -1;
1003  }
1005  self_encrypt = C_SmimeDefaultKey;
1006  }
1007  }
1008 
1009  if (!oppenc_mode && self_encrypt)
1010  {
1011  const size_t keylist_size = mutt_str_strlen(*keylist);
1012  mutt_mem_realloc(keylist, keylist_size + mutt_str_strlen(self_encrypt) + 2);
1013  sprintf(*keylist + keylist_size, " %s", self_encrypt);
1014  }
1015 
1016  mutt_addrlist_clear(&addrlist);
1017 
1018  return 0;
1019 }
1020 
1029 {
1030  if (!WithCrypto)
1031  return;
1032 
1034  return;
1035 
1036  char *pgpkeylist = NULL;
1037 
1038  crypt_get_keys(e, &pgpkeylist, 1);
1039  if (pgpkeylist)
1040  {
1041  e->security |= SEC_ENCRYPT;
1042  FREE(&pgpkeylist);
1043  }
1044  else
1045  {
1046  e->security &= ~SEC_ENCRYPT;
1047  }
1048 }
1049 
1056 static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
1057 {
1058  if (!WithCrypto)
1059  return;
1060 
1061  for (; a; a = a->next)
1062  {
1063  if (a->type == TYPE_MULTIPART)
1064  crypt_fetch_signatures(signatures, a->parts, n);
1065  else
1066  {
1067  if ((*n % 5) == 0)
1068  mutt_mem_realloc(signatures, (*n + 6) * sizeof(struct Body **));
1069 
1070  (*signatures)[(*n)++] = a;
1071  }
1072  }
1073 }
1074 
1081 {
1084  {
1085  return true;
1086  }
1087 
1088  return false;
1089 }
1090 
1094 int mutt_protected_headers_handler(struct Body *a, struct State *s)
1095 {
1097  {
1098  if (a->mime_headers->subject)
1099  {
1100  const bool display = (s->flags & MUTT_DISPLAY);
1101 
1102  if (display && C_Weed && mutt_matches_ignore("subject"))
1103  return 0;
1104 
1106  int wraplen = display ? mutt_window_wrap_cols(s->wraplen, C_Wrap) : 0;
1107 
1108  mutt_write_one_header(s->fp_out, "Subject", a->mime_headers->subject,
1109  s->prefix, wraplen, display ? CH_DISPLAY : CH_NO_FLAGS);
1110  state_puts(s, "\n");
1111  }
1112  }
1113 
1114  return 0;
1115 }
1116 
1120 int mutt_signed_handler(struct Body *a, struct State *s)
1121 {
1122  if (!WithCrypto)
1123  return -1;
1124 
1125  bool inconsistent = false;
1126  struct Body *b = a;
1127  struct Body **signatures = NULL;
1128  int sigcnt = 0;
1129  int rc = 0;
1130  struct Buffer *tempfile = NULL;
1131 
1132  a = a->parts;
1133  SecurityFlags signed_type = mutt_is_multipart_signed(b);
1134  if (signed_type == SEC_NO_FLAGS)
1135  {
1136  /* A null protocol value is already checked for in mutt_body_handler() */
1137  state_printf(s,
1138  _("[-- Error: "
1139  "Unknown multipart/signed protocol %s --]\n\n"),
1140  mutt_param_get(&b->parameter, "protocol"));
1141  return mutt_body_handler(a, s);
1142  }
1143 
1144  if (!(a && a->next))
1145  inconsistent = true;
1146  else
1147  {
1148  switch (signed_type)
1149  {
1150  case SEC_SIGN:
1151  if ((a->next->type != TYPE_MULTIPART) ||
1152  (mutt_str_strcasecmp(a->next->subtype, "mixed") != 0))
1153  {
1154  inconsistent = true;
1155  }
1156  break;
1157  case PGP_SIGN:
1158  if ((a->next->type != TYPE_APPLICATION) ||
1159  (mutt_str_strcasecmp(a->next->subtype, "pgp-signature") != 0))
1160  {
1161  inconsistent = true;
1162  }
1163  break;
1164  case SMIME_SIGN:
1165  if ((a->next->type != TYPE_APPLICATION) ||
1166  ((mutt_str_strcasecmp(a->next->subtype, "x-pkcs7-signature") != 0) &&
1167  (mutt_str_strcasecmp(a->next->subtype, "pkcs7-signature") != 0)))
1168  {
1169  inconsistent = true;
1170  }
1171  break;
1172  default:
1173  inconsistent = true;
1174  }
1175  }
1176  if (inconsistent)
1177  {
1178  state_attach_puts(s, _("[-- Error: Missing or bad-format multipart/signed "
1179  "signature --]\n\n"));
1180  return mutt_body_handler(a, s);
1181  }
1182 
1183  if (s->flags & MUTT_DISPLAY)
1184  {
1185  crypt_fetch_signatures(&signatures, a->next, &sigcnt);
1186 
1187  if (sigcnt != 0)
1188  {
1189  tempfile = mutt_buffer_pool_get();
1190  mutt_buffer_mktemp(tempfile);
1191  bool goodsig = true;
1192  if (crypt_write_signed(a, s, mutt_b2s(tempfile)) == 0)
1193  {
1194  for (int i = 0; i < sigcnt; i++)
1195  {
1196  if (((WithCrypto & APPLICATION_PGP) != 0) &&
1197  (signatures[i]->type == TYPE_APPLICATION) &&
1198  (mutt_str_strcasecmp(signatures[i]->subtype, "pgp-signature") == 0))
1199  {
1200  if (crypt_pgp_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1201  goodsig = false;
1202 
1203  continue;
1204  }
1205 
1206  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1207  (signatures[i]->type == TYPE_APPLICATION) &&
1208  ((mutt_str_strcasecmp(signatures[i]->subtype,
1209  "x-pkcs7-signature") == 0) ||
1210  (mutt_str_strcasecmp(signatures[i]->subtype,
1211  "pkcs7-signature") == 0)))
1212  {
1213  if (crypt_smime_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1214  goodsig = false;
1215 
1216  continue;
1217  }
1218 
1219  state_printf(s,
1220  _("[-- Warning: "
1221  "We can't verify %s/%s signatures. --]\n\n"),
1222  TYPE(signatures[i]), signatures[i]->subtype);
1223  }
1224  }
1225 
1226  mutt_file_unlink(mutt_b2s(tempfile));
1227  mutt_buffer_pool_release(&tempfile);
1228 
1229  b->goodsig = goodsig;
1230  b->badsig = !goodsig;
1231 
1232  /* Now display the signed body */
1233  state_attach_puts(s, _("[-- The following data is signed --]\n\n"));
1234 
1236 
1237  FREE(&signatures);
1238  }
1239  else
1241  _("[-- Warning: Can't find any signatures. --]\n\n"));
1242  }
1243 
1244  rc = mutt_body_handler(a, s);
1245 
1246  if ((s->flags & MUTT_DISPLAY) && (sigcnt != 0))
1247  state_attach_puts(s, _("\n[-- End of signed data --]\n"));
1248 
1249  return rc;
1250 }
1251 
1266 const char *crypt_get_fingerprint_or_id(const char *p, const char **pphint,
1267  const char **ppl, const char **pps)
1268 {
1269  const char *ps = NULL, *pl = NULL, *phint = NULL;
1270  char *pfcopy = NULL, *s1 = NULL, *s2 = NULL;
1271  char c;
1272  int isid;
1273  size_t hexdigits;
1274 
1275  /* User input may be partial name, fingerprint or short or long key ID,
1276  * independent of C_PgpLongIds.
1277  * Fingerprint without spaces is 40 hex digits (SHA-1) or 32 hex digits (MD5).
1278  * Strip leading "0x" for key ID detection and prepare pl and ps to indicate
1279  * if an ID was found and to simplify logic in the key loop's inner
1280  * condition of the caller. */
1281 
1282  char *pf = mutt_str_skip_whitespace(p);
1283  if (mutt_str_startswith(pf, "0x", CASE_IGNORE))
1284  pf += 2;
1285 
1286  /* Check if a fingerprint is given, must be hex digits only, blanks
1287  * separating groups of 4 hex digits are allowed. Also pre-check for ID. */
1288  isid = 2; /* unknown */
1289  hexdigits = 0;
1290  s1 = pf;
1291  do
1292  {
1293  c = *(s1++);
1294  if ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) ||
1295  (('a' <= c) && (c <= 'f')))
1296  {
1297  hexdigits++;
1298  if (isid == 2)
1299  isid = 1; /* it is an ID so far */
1300  }
1301  else if (c)
1302  {
1303  isid = 0; /* not an ID */
1304  if ((c == ' ') && ((hexdigits % 4) == 0))
1305  ; /* skip blank before or after 4 hex digits */
1306  else
1307  break; /* any other character or position */
1308  }
1309  } while (c);
1310 
1311  /* If at end of input, check for correct fingerprint length and copy if. */
1312  pfcopy = (!c && ((hexdigits == 40) || (hexdigits == 32)) ? mutt_str_strdup(pf) : NULL);
1313 
1314  if (pfcopy)
1315  {
1316  /* Use pfcopy to strip all spaces from fingerprint and as hint. */
1317  s1 = pfcopy;
1318  s2 = pfcopy;
1319  do
1320  {
1321  *(s1++) = *(s2 = mutt_str_skip_whitespace(s2));
1322  } while (*(s2++));
1323 
1324  phint = pfcopy;
1325  ps = NULL;
1326  pl = NULL;
1327  }
1328  else
1329  {
1330  phint = p;
1331  ps = NULL;
1332  pl = NULL;
1333  if (isid == 1)
1334  {
1335  if (mutt_str_strlen(pf) == 16)
1336  pl = pf; /* long key ID */
1337  else if (mutt_str_strlen(pf) == 8)
1338  ps = pf; /* short key ID */
1339  }
1340  }
1341 
1342  *pphint = phint;
1343  *ppl = pl;
1344  *pps = ps;
1345  return pfcopy;
1346 }
1347 
1355 bool crypt_is_numerical_keyid(const char *s)
1356 {
1357  /* or should we require the "0x"? */
1358  if (strncmp(s, "0x", 2) == 0)
1359  s += 2;
1360  if (strlen(s) % 8)
1361  return false;
1362  while (*s)
1363  if (!strchr("0123456789ABCDEFabcdef", *s++))
1364  return false;
1365 
1366  return true;
1367 }
#define MUTT_CM_DECODE_CRYPT
Definition: copy.h:47
int mutt_protected_headers_handler(struct Body *a, struct State *s)
Process a protected header - Implements handler_t.
Definition: crypt.c:1094
Convenience wrapper for the gui headers.
bool mutt_matches_ignore(const char *s)
Does the string match the ignore list.
Definition: parse.c:309
const char * crypt_get_fingerprint_or_id(const char *p, const char **pphint, const char **ppl, const char **pps)
Get the fingerprint or long key ID.
Definition: crypt.c:1266
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:153
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:720
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:78
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
void mutt_message_to_7bit(struct Body *a, FILE *fp)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:1303
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
#define SEC_AUTOCRYPT
Message will be, or was Autocrypt encrypt+signed.
Definition: ncrypt.h:131
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:198
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
Miscellaneous email parsing routines.
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1772
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:303
#define PGP_INLINE
Definition: ncrypt.h:144
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:774
The envelope/body of an email.
Definition: email.h:37
#define state_puts(STATE, STR)
Definition: state.h:55
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
char * crypt_smime_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:471
#define TAILQ_FIRST(head)
Definition: queue.h:716
#define mutt_perror(...)
Definition: logging.h:85
struct Content * content
Detailed info about the content of the attachment.
Definition: body.h:51
Structs that make up an email.
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:3360
7-bit text
Definition: mime.h:49
#define mutt_message(...)
Definition: logging.h:83
int mutt_signed_handler(struct Body *a, struct State *s)
Verify a "multipart/signed" body - Implements handler_t.
Definition: crypt.c:1120
WHERE char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: globals.h:163
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct AddressList bcc
Email&#39;s &#39;Bcc&#39; list.
Definition: envelope.h:60
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1382
WHERE char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: globals.h:105
Wrapper around crypto functions.
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:183
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:808
bool crypt_smime_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:416
#define SEC_NO_FLAGS
No flags are set.
Definition: ncrypt.h:121
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1080
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:728
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1355
struct Body * content
List of MIME parts.
Definition: email.h:90
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:103
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
String manipulation buffer.
Definition: buffer.h:33
WHERE bool C_CryptUsePka
Config: Use GPGME to use PKA (lookup PGP keys using DNS)
Definition: globals.h:264
char * prefix
String to add to the beginning of each output line.
Definition: state.h:48
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:49
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:475
int mutt_copy_message(FILE *fp_out, struct Mailbox *m, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
Copy a message from a Mailbox.
Definition: copy.c:810
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
WHERE bool C_CryptProtectedHeadersWrite
Config: Generate protected header (Memory Hole) for signed and encrypted emails.
Definition: globals.h:272
void crypt_pgp_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:398
#define _(a)
Definition: message.h:28
bool is_autocrypt
Flag autocrypt-decrypted messages for replying.
Definition: body.h:79
WHERE short C_Wrap
Config: Width to wrap text in the pager.
Definition: globals.h:152
struct Body * next
next attachment in the list
Definition: body.h:53
An email address.
Definition: address.h:34
8-bit text
Definition: mime.h:50
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:37
FILE * fp_out
File to write to.
Definition: state.h:47
char * mailbox
Mailbox and host address.
Definition: address.h:37
#define SEC_INLINE
Email has an inline signature.
Definition: ncrypt.h:129
#define SMIME_SIGN
Definition: ncrypt.h:147
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:950
bool C_PgpStrictEnc
Config: Encode PGP signed messages with quoted-printable (don&#39;t unset)
Definition: crypt.c:71
int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
Write the message body/part.
Definition: crypt.c:764
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:122
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:440
FILE * fp_in
File to read from.
Definition: state.h:46
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: ncrypt.h:126
bool C_PgpSelfEncrypt
Config: Encrypted messages will also be encrypted to C_PgpDefaultKey too.
Definition: crypt.c:70
Representation of a single alias to an email address.
The body of an email.
Definition: body.h:34
void mutt_prepare_envelope(struct Envelope *env, bool final)
Prepare an email header.
Definition: sendlib.c:3001
Convenience wrapper for the config headers.
#define SEC_BADSIGN
Email has a bad signature.
Definition: ncrypt.h:125
Prepare and send an email.
Hundreds of global variables to back the user variables.
Email Address Handling.
void crypt_smime_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:535
Some miscellaneous functions.
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
#define SEC_ALL_FLAGS
Definition: ncrypt.h:138
struct Body * crypt_smime_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:482
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:145
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1319
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:451
#define SEC_GOODSIGN
Email has a valid signature.
Definition: ncrypt.h:124
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
unsigned char C_PgpEncryptSelf
Deprecated, see C_PgpSelfEncrypt.
Definition: crypt.c:67
#define SMIME_OPAQUE
Definition: ncrypt.h:150
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
bool C_PgpRetainableSigs
Config: Create nested multipart/signed or encrypted messages.
Definition: crypt.c:69
struct Envelope * env
Envelope information.
Definition: email.h:89
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:82
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:77
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:59
WHERE bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:34
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:410
int wraplen
Width to wrap lines to (when flags & MUTT_DISPLAY)
Definition: state.h:50
unsigned int encoding
content-transfer-encoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
void crypt_smime_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:407
#define PGP_SIGN
Definition: ncrypt.h:141
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
char * subtype
content-type subtype
Definition: body.h:37
struct Body * crypt_pgp_encrypt_message(struct Email *e, struct Body *a, char *keylist, int sign, const struct AddressList *from)
Wrapper for CryptModuleSpecs::pgp_encrypt_message()
Definition: cryptglue.c:332
bool C_SmimeSelfEncrypt
Config: Encrypted messages will also be encrypt to C_SmimeDefaultKey too.
Definition: crypt.c:73
#define mutt_b2s(buf)
Definition: buffer.h:41
bool goodsig
Good cryptographic signature.
Definition: body.h:75
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:557
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:123
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1334
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:269
Signing/encryption multiplexor.
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:545
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void crypt_pgp_invoke_import(const char *fname)
Wrapper for CryptModuleSpecs::pgp_invoke_import()
Definition: cryptglue.c:358
A mailbox.
Definition: mailbox.h:80
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
#define MUTT_CM_DECODE
Decode the message body into text/plain.
Definition: copy.h:37
#define PGP_KEY
Definition: ncrypt.h:143
Type: &#39;text/*&#39;.
Definition: mime.h:38
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
#define MUTT_CM_CHARCONV
Perform character set conversions.
Definition: copy.h:41
int mutt_protect(struct Email *e, char *keylist, bool postpone)
Encrypt and/or sign a message.
Definition: crypt.c:170
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define CH_DISPLAY
Display result to user.
Definition: copy.h:69
struct Body * crypt_pgp_traditional_encryptsign(struct Body *a, int flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign()
Definition: cryptglue.c:288
Do no use Autocrypt.
Definition: autocrypt.h:104
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
Definition: mutt_window.c:383
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:512
Ignore case when comparing strings.
Definition: string2.h:68
void state_mark_protected_header(struct State *s)
Write a unique marker around protected headers.
Definition: state.c:56
unsigned char C_SmimeEncryptSelf
Deprecated, see C_SmimeSelfEncrypt.
Definition: crypt.c:72
WHERE bool OptPgpCheckTrust
(pseudo) used by pgp_select_key()
Definition: options.h:47
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:616
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1056
API for encryption/signing of emails.
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * description
content-description
Definition: body.h:40
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:39
WHERE bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: globals.h:270
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2531
unsigned int type
content-type primary type
Definition: body.h:65
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: ncrypt.h:130
bool from
Has a line beginning with "From "?
Definition: content.h:43
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:134
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
bool C_CryptTimestamp
Config: Add a timestamp to PGP or SMIME output to prevent spoofing.
Definition: crypt.c:63
Type: &#39;message/*&#39;.
Definition: mime.h:35
unsigned char C_PgpMimeAuto
Config: Prompt the user to use MIME if inline PGP fails.
Definition: crypt.c:68
#define MUTT_CM_DECODE_SMIME
Used for decoding S/MIME messages.
Definition: copy.h:45
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:578
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:70
Keep track when processing files.
#define TYPE(body)
Definition: mime.h:83
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1028
struct Body * crypt_smime_build_smime_entity(struct Body *a, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity()
Definition: cryptglue.c:493
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:641
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:310
void crypt_smime_invoke_import(const char *infile, const char *mailbox)
Wrapper for CryptModuleSpecs::smime_invoke_import()
Definition: cryptglue.c:504
char * subject
Email&#39;s subject.
Definition: envelope.h:66
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
enum AutocryptRec mutt_autocrypt_ui_recommendation(struct Email *e, char **keylist)
Get the recommended action for an Email.
Definition: autocrypt.c:561
Duplicate the structure of an entire email.
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:797
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
Autocrypt end-to-end encryption.
struct Email * email
Email in the list.
Definition: email.h:116
#define SMIME_ENCRYPT
Definition: ncrypt.h:146
#define mutt_error(...)
Definition: logging.h:84
WHERE struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: globals.h:93
Binary.
Definition: mime.h:53
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
Quoted-printable text.
Definition: mime.h:51
struct Body * crypt_pgp_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:321
WHERE char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: globals.h:159
#define FREE(x)
Definition: memory.h:40
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
int crypt_smime_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:513
bool space
Whitespace at the end of lines?
Definition: content.h:41
void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
Extract keys from a message.
Definition: crypt.c:851
Keep track when processing files.
Definition: state.h:44
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:61
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1551
List of Emails.
Definition: email.h:114
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
Handling of global boolean variables.
Miscellaneous functions for sending an email.
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
#define TAILQ_EMPTY(head)
Definition: queue.h:714
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: ncrypt.h:120
#define MUTT_CM_NOHEADER
Don&#39;t copy the message header.
Definition: copy.h:35
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:585
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
Decide how to display email content.
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
#define WithCrypto
Definition: ncrypt.h:160
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:692
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags)
Write one header line to a file.
Definition: sendlib.c:2154
Type: &#39;application/*&#39;.
Definition: mime.h:33
#define PGP_ENCRYPT
Definition: ncrypt.h:140
bool crypt_pgp_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:192
The header of an Email.
Definition: envelope.h:54
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: email_globals.c:40
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: ncrypt.h:135
int crypt_pgp_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:367