NeoMutt  2020-08-07-1-gab41a1
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 "private.h"
41 #include "mutt/lib.h"
42 #include "address/lib.h"
43 #include "config/lib.h"
44 #include "email/lib.h"
45 #include "core/lib.h"
46 #include "alias/lib.h"
47 #include "gui/lib.h"
48 #include "mutt.h"
49 #include "crypt.h"
50 #include "ncrypt/lib.h"
51 #include "send/lib.h"
52 #include "copy.h"
53 #include "cryptglue.h"
54 #include "handler.h"
55 #include "mutt_globals.h"
56 #include "mutt_parse.h"
57 #include "muttlib.h"
58 #include "options.h"
59 #include "state.h"
60 #ifdef USE_AUTOCRYPT
61 #include "autocrypt/lib.h"
62 #endif
63 
71 void crypt_current_time(struct State *s, const char *app_name)
72 {
73  char p[256], tmp[256];
74 
75  if (!WithCrypto)
76  return;
77 
78  if (C_CryptTimestamp)
79  {
80  mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), MUTT_DATE_NOW);
81  }
82  else
83  *p = '\0';
84 
85  snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
86  state_attach_puts(s, tmp);
87 }
88 
93 {
96 
99 
100  if (WithCrypto)
101  {
102  /* L10N: Due to the implementation details (e.g. some passwords are managed
103  by gpg-agent) we can't know whether we forgot zero, 1, 12, ...
104  passwords. So in English we use "Passphrases". Your language might
105  have other means to express this. */
106  mutt_message(_("Passphrases forgotten"));
107  }
108 }
109 
110 #ifndef DEBUG
111 #include <sys/resource.h>
115 static void disable_coredumps(void)
116 {
117  struct rlimit rl = { 0, 0 };
118  static bool done = false;
119 
120  if (!done)
121  {
122  setrlimit(RLIMIT_CORE, &rl);
123  done = true;
124  }
125 }
126 #endif
127 
135 {
136  bool rc = false;
137 
138 #ifndef DEBUG
139  disable_coredumps();
140 #endif
141 
142  if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & APPLICATION_PGP))
144 
145  if (((WithCrypto & APPLICATION_SMIME) != 0) && (flags & APPLICATION_SMIME))
147 
148  return rc;
149 }
150 
159 int mutt_protect(struct Email *e, char *keylist, bool postpone)
160 {
161  struct Body *pbody = NULL, *tmp_pbody = NULL;
162  struct Body *tmp_smime_pbody = NULL;
163  struct Body *tmp_pgp_pbody = NULL;
164  bool has_retainable_sig = false;
165 
166  if (!WithCrypto)
167  return -1;
168 
169  int security = e->security;
170  int sign = security & (SEC_AUTOCRYPT | SEC_SIGN);
171  if (postpone)
172  {
173  sign = SEC_NO_FLAGS;
174  security &= ~SEC_SIGN;
175  }
176 
177  if (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) && !sign)
178  return 0;
179 
180  if (sign && !(security & SEC_AUTOCRYPT) && !crypt_valid_passphrase(security))
181  return -1;
182 
183  if (((WithCrypto & APPLICATION_PGP) != 0) && !(security & SEC_AUTOCRYPT) &&
184  ((security & PGP_INLINE) == PGP_INLINE))
185  {
186  if ((e->body->type != TYPE_TEXT) ||
187  !mutt_istr_equal(e->body->subtype, "plain"))
188  {
190  _("Inline PGP can't be used with attachments. "
191  "Revert to PGP/MIME?")) != MUTT_YES)
192  {
193  mutt_error(
194  _("Mail not sent: inline PGP can't be used with attachments"));
195  return -1;
196  }
197  }
198  else if (mutt_istr_equal("flowed",
199  mutt_param_get(&e->body->parameter, "format")))
200  {
202  _("Inline PGP can't be used with format=flowed. "
203  "Revert to PGP/MIME?"))) != MUTT_YES)
204  {
205  mutt_error(
206  _("Mail not sent: inline PGP can't be used with format=flowed"));
207  return -1;
208  }
209  }
210  else
211  {
212  /* they really want to send it inline... go for it */
213  if (!isendwin())
214  {
215  mutt_endwin();
216  puts(_("Invoking PGP..."));
217  }
218  pbody = crypt_pgp_traditional_encryptsign(e->body, security, keylist);
219  if (pbody)
220  {
221  e->body = pbody;
222  return 0;
223  }
224 
225  /* otherwise inline won't work...ask for revert */
226  if (query_quadoption(
228  _("Message can't be sent inline. Revert to using PGP/MIME?")) != MUTT_YES)
229  {
230  mutt_error(_("Mail not sent"));
231  return -1;
232  }
233  }
234 
235  /* go ahead with PGP/MIME */
236  }
237 
238  if (!isendwin())
239  mutt_endwin();
240 
242  tmp_smime_pbody = e->body;
243  if (WithCrypto & APPLICATION_PGP)
244  tmp_pgp_pbody = e->body;
245 
246 #ifdef CRYPT_BACKEND_GPGME
247  if (sign && C_CryptUsePka)
248 #else
249  if (sign)
250 #endif
251  {
252  /* Set sender (necessary for e.g. PKA). */
253  const char *mailbox = NULL;
254  struct Address *from = TAILQ_FIRST(&e->env->from);
255  bool free_from = false;
256 
257  if (!from)
258  {
259  free_from = true;
260  from = mutt_default_from(NeoMutt->sub);
261  }
262 
263  mailbox = from->mailbox;
264  if (!mailbox && C_EnvelopeFromAddress)
265  mailbox = C_EnvelopeFromAddress->mailbox;
266 
267  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
268  crypt_smime_set_sender(mailbox);
269  else if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
270  crypt_pgp_set_sender(mailbox);
271 
272  if (free_from)
273  mutt_addr_free(&from);
274  }
275 
277  {
278  struct Envelope *protected_headers = mutt_env_new();
279  mutt_str_replace(&protected_headers->subject, e->env->subject);
280  /* Note: if other headers get added, such as to, cc, then a call to
281  * mutt_env_to_intl() will need to be added here too. */
282  mutt_prepare_envelope(protected_headers, 0, NeoMutt->sub);
283 
285  e->body->mime_headers = protected_headers;
286  /* Optional part of the draft RFC, but required by Enigmail */
287  mutt_param_set(&e->body->parameter, "protected-headers", "v1");
288  }
289  else
290  {
291  mutt_param_delete(&e->body->parameter, "protected-headers");
292  }
293 
294 #ifdef USE_AUTOCRYPT
295  /* A note about e->body->mime_headers. If postpone or send
296  * fails, the mime_headers is cleared out before returning to the
297  * compose menu. So despite the "robustness" code above and in the
298  * gen_gossip_list function below, mime_headers will not be set when
299  * entering mutt_protect().
300  *
301  * This is important to note because the user could toggle
302  * $crypt_protected_headers_write or $autocrypt off back in the
303  * compose menu. We don't want mutt_write_rfc822_header() to write
304  * stale data from one option if the other is set.
305  */
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->body, &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->body, &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->body) && (tmp_smime_pbody != tmp_pbody))
354  {
355  /* detach and don't delete e->body,
356  * which tmp_smime_pbody->parts after signing. */
357  tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
358  e->body->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 signatures.
382  if (has_retainable_sig)
383  {
384  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
385  mutt_body_free(&tmp_pgp_pbody->next);
386  }
387  }
388  }
389 
390  if (pbody)
391  {
392  e->body = pbody;
393  return 0;
394  }
395 
396 bail:
398  return -1;
399 }
400 
408 {
409  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "signed"))
410  {
411  return SEC_NO_FLAGS;
412  }
413 
414  char *p = mutt_param_get(&b->parameter, "protocol");
415  if (!p)
416  return SEC_NO_FLAGS;
417 
418  if (mutt_istr_equal(p, "multipart/mixed"))
419  return SEC_SIGN;
420 
421  if (((WithCrypto & APPLICATION_PGP) != 0) &&
422  mutt_istr_equal(p, "application/pgp-signature"))
423  {
424  return PGP_SIGN;
425  }
426 
427  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
428  mutt_istr_equal(p, "application/x-pkcs7-signature"))
429  {
430  return SMIME_SIGN;
431  }
432  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
433  mutt_istr_equal(p, "application/pkcs7-signature"))
434  {
435  return SMIME_SIGN;
436  }
437 
438  return SEC_NO_FLAGS;
439 }
440 
448 {
449  if ((WithCrypto & APPLICATION_PGP) == 0)
450  return SEC_NO_FLAGS;
451 
452  char *p = NULL;
453 
454  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
455  !mutt_istr_equal(b->subtype, "encrypted") ||
456  !(p = mutt_param_get(&b->parameter, "protocol")) ||
457  !mutt_istr_equal(p, "application/pgp-encrypted"))
458  {
459  return SEC_NO_FLAGS;
460  }
461 
462  return PGP_ENCRYPT;
463 }
464 
472 {
474  return 0;
475 
476  b = b->parts;
477  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
478  !mutt_istr_equal(b->subtype, "pgp-encrypted"))
479  {
480  return 0;
481  }
482 
483  b = b->next;
484  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
485  !mutt_istr_equal(b->subtype, "octet-stream"))
486  {
487  return 0;
488  }
489 
490  return PGP_ENCRYPT;
491 }
492 
509 {
510  if (!(WithCrypto & APPLICATION_PGP))
511  return SEC_NO_FLAGS;
512 
513  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype || !mutt_istr_equal(b->subtype, "mixed"))
514  {
515  return SEC_NO_FLAGS;
516  }
517 
518  b = b->parts;
519  if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
520  !mutt_istr_equal(b->subtype, "plain") || (b->length != 0))
521  {
522  return SEC_NO_FLAGS;
523  }
524 
525  b = b->next;
526  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
527  !mutt_istr_equal(b->subtype, "pgp-encrypted"))
528  {
529  return SEC_NO_FLAGS;
530  }
531 
532  b = b->next;
533  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
534  !mutt_istr_equal(b->subtype, "octet-stream"))
535  {
536  return SEC_NO_FLAGS;
537  }
538 
539  b = b->next;
540  if (b)
541  return SEC_NO_FLAGS;
542 
543  return PGP_ENCRYPT;
544 }
545 
553 {
555  char *p = NULL;
556 
557  if (m->type == TYPE_APPLICATION)
558  {
559  if (mutt_istr_equal(m->subtype, "pgp") ||
560  mutt_istr_equal(m->subtype, "x-pgp-message"))
561  {
562  p = mutt_param_get(&m->parameter, "x-action");
563  if (p && (mutt_istr_equal(p, "sign") || mutt_istr_equal(p, "signclear")))
564  {
565  t |= PGP_SIGN;
566  }
567 
568  p = mutt_param_get(&m->parameter, "format");
569  if (p && mutt_istr_equal(p, "keys-only"))
570  {
571  t |= PGP_KEY;
572  }
573 
574  if (t == SEC_NO_FLAGS)
575  t |= PGP_ENCRYPT; /* not necessarily correct, but... */
576  }
577 
578  if (mutt_istr_equal(m->subtype, "pgp-signed"))
579  t |= PGP_SIGN;
580 
581  if (mutt_istr_equal(m->subtype, "pgp-keys"))
582  t |= PGP_KEY;
583  }
584  else if ((m->type == TYPE_TEXT) && mutt_istr_equal("plain", m->subtype))
585  {
586  if (((p = mutt_param_get(&m->parameter, "x-mutt-action")) ||
587  (p = mutt_param_get(&m->parameter, "x-action")) ||
588  (p = mutt_param_get(&m->parameter, "action"))) &&
589  mutt_istr_startswith(p, "pgp-sign"))
590  {
591  t |= PGP_SIGN;
592  }
593  else if (p && mutt_istr_startswith(p, "pgp-encrypt"))
594  t |= PGP_ENCRYPT;
595  else if (p && mutt_istr_startswith(p, "pgp-keys"))
596  t |= PGP_KEY;
597  }
598  if (t)
599  t |= PGP_INLINE;
600 
601  return t;
602 }
603 
611 {
612  if (!m)
613  return SEC_NO_FLAGS;
614 
615  if (((m->type & TYPE_APPLICATION) == 0) || !m->subtype)
616  return SEC_NO_FLAGS;
617 
618  char *t = NULL;
619  bool complain = false;
620  /* S/MIME MIME types don't need x- anymore, see RFC2311 */
621  if (mutt_istr_equal(m->subtype, "x-pkcs7-mime") || mutt_istr_equal(m->subtype, "pkcs7-mime"))
622  {
623  t = mutt_param_get(&m->parameter, "smime-type");
624  if (t)
625  {
626  if (mutt_istr_equal(t, "enveloped-data"))
627  return SMIME_ENCRYPT;
628  if (mutt_istr_equal(t, "signed-data"))
629  return SMIME_SIGN | SMIME_OPAQUE;
630  return SEC_NO_FLAGS;
631  }
632  /* Netscape 4.7 uses
633  * Content-Description: S/MIME Encrypted Message
634  * instead of Content-Type parameter */
635  if (mutt_istr_equal(m->description, "S/MIME Encrypted Message"))
636  return SMIME_ENCRYPT;
637  complain = true;
638  }
639  else if (!mutt_istr_equal(m->subtype, "octet-stream"))
640  return SEC_NO_FLAGS;
641 
642  t = mutt_param_get(&m->parameter, "name");
643 
644  if (!t)
645  t = m->d_filename;
646  if (!t)
647  t = m->filename;
648  if (!t)
649  {
650  if (complain)
651  {
652  mutt_message(
653  _("S/MIME messages with no hints on content are unsupported"));
654  }
655  return SEC_NO_FLAGS;
656  }
657 
658  /* no .p7c, .p10 support yet. */
659 
660  int len = mutt_str_len(t) - 4;
661  if ((len > 0) && (*(t + len) == '.'))
662  {
663  len++;
664  if (mutt_istr_equal((t + len), "p7m"))
665  {
666  /* Not sure if this is the correct thing to do, but
667  * it's required for compatibility with Outlook */
668  return SMIME_SIGN | SMIME_OPAQUE;
669  }
670  else if (mutt_istr_equal((t + len), "p7s"))
671  return SMIME_SIGN | SMIME_OPAQUE;
672  }
673 
674  return SEC_NO_FLAGS;
675 }
676 
686 {
687  if (!WithCrypto || !m)
688  return SEC_NO_FLAGS;
689 
691 
692  if (m->type == TYPE_APPLICATION)
693  {
695  rc |= mutt_is_application_pgp(m);
696 
698  {
699  rc |= mutt_is_application_smime(m);
700  if (rc && m->goodsig)
701  rc |= SEC_GOODSIGN;
702  if (rc && m->badsig)
703  rc |= SEC_BADSIGN;
704  }
705  }
706  else if (((WithCrypto & APPLICATION_PGP) != 0) && (m->type == TYPE_TEXT))
707  {
708  rc |= mutt_is_application_pgp(m);
709  if (rc && m->goodsig)
710  rc |= SEC_GOODSIGN;
711  }
712 
713  if (m->type == TYPE_MULTIPART)
714  {
716  rc |= mutt_is_multipart_signed(m);
718 
719  if (rc && m->goodsig)
720  rc |= SEC_GOODSIGN;
721 #ifdef USE_AUTOCRYPT
722  if (rc && m->is_autocrypt)
723  rc |= SEC_AUTOCRYPT;
724 #endif
725  }
726 
727  if ((m->type == TYPE_MULTIPART) || (m->type == TYPE_MESSAGE))
728  {
729  SecurityFlags u = m->parts ? SEC_ALL_FLAGS : SEC_NO_FLAGS; /* Bits set in all parts */
730  SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */
731 
732  for (struct Body *b = m->parts; b; b = b->next)
733  {
734  const SecurityFlags v = crypt_query(b);
735  u &= v;
736  w |= v;
737  }
738  rc |= u | (w & ~SEC_GOODSIGN);
739 
740  if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
741  rc |= SEC_PARTSIGN;
742  }
743 
744  return rc;
745 }
746 
757 int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
758 {
759  if (!WithCrypto)
760  return -1;
761 
762  FILE *fp = mutt_file_fopen(tempfile, "w");
763  if (!fp)
764  {
765  mutt_perror(tempfile);
766  return -1;
767  }
768 
769  fseeko(s->fp_in, a->hdr_offset, SEEK_SET);
770  size_t bytes = a->length + a->offset - a->hdr_offset;
771  bool hadcr = false;
772  while (bytes > 0)
773  {
774  const int c = fgetc(s->fp_in);
775  if (c == EOF)
776  break;
777 
778  bytes--;
779 
780  if (c == '\r')
781  hadcr = true;
782  else
783  {
784  if ((c == '\n') && !hadcr)
785  fputc('\r', fp);
786 
787  hadcr = false;
788  }
789 
790  fputc(c, fp);
791  }
792  mutt_file_fclose(&fp);
793 
794  return 0;
795 }
796 
802 {
803  if (!WithCrypto)
804  return;
805 
806  while (a)
807  {
808  if (a->type == TYPE_MULTIPART)
809  {
810  if (a->encoding != ENC_7BIT)
811  {
812  a->encoding = ENC_7BIT;
814  }
815  else if (((WithCrypto & APPLICATION_PGP) != 0) && C_PgpStrictEnc)
817  }
818  else if ((a->type == TYPE_MESSAGE) &&
819  !mutt_istr_equal(a->subtype, "delivery-status"))
820  {
821  if (a->encoding != ENC_7BIT)
822  mutt_message_to_7bit(a, NULL, NeoMutt->sub);
823  }
824  else if (a->encoding == ENC_8BIT)
826  else if (a->encoding == ENC_BINARY)
827  a->encoding = ENC_BASE64;
828  else if (a->content && (a->encoding != ENC_BASE64) &&
829  (a->content->from || (a->content->space && C_PgpStrictEnc)))
830  {
832  }
833  a = a->next;
834  }
835 }
836 
844 void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
845 {
846  if (!WithCrypto)
847  return;
848 
849  struct Buffer *tempfname = mutt_buffer_pool_get();
850  mutt_buffer_mktemp(tempfname);
851  FILE *fp_out = mutt_file_fopen(mutt_b2s(tempfname), "w");
852  if (!fp_out)
853  {
854  mutt_perror(mutt_b2s(tempfname));
855  goto cleanup;
856  }
857 
859  OptDontHandlePgpKeys = true;
860 
861  struct EmailNode *en = NULL;
862  STAILQ_FOREACH(en, el, entries)
863  {
864  struct Email *e = en->email;
865 
868  {
869  mutt_file_fclose(&fp_out);
870  break;
871  }
872 
873  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
874  {
876  fflush(fp_out);
877 
878  mutt_endwin();
879  puts(_("Trying to extract PGP keys...\n"));
880  crypt_pgp_invoke_import(mutt_b2s(tempfname));
881  }
882 
883  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
884  {
885  if (e->security & SEC_ENCRYPT)
886  {
888  CH_NO_FLAGS, 0);
889  }
890  else
892  fflush(fp_out);
893 
894  char *mbox = NULL;
895  if (!TAILQ_EMPTY(&e->env->from))
896  {
898  mbox = TAILQ_FIRST(&e->env->from)->mailbox;
899  }
900  else if (!TAILQ_EMPTY(&e->env->sender))
901  {
903  mbox = TAILQ_FIRST(&e->env->sender)->mailbox;
904  }
905  if (mbox)
906  {
907  mutt_endwin();
908  puts(_("Trying to extract S/MIME certificates..."));
909  crypt_smime_invoke_import(mutt_b2s(tempfname), mbox);
910  }
911  }
912 
913  rewind(fp_out);
914  }
915 
916  mutt_file_fclose(&fp_out);
917  if (isendwin())
919 
920  mutt_file_unlink(mutt_b2s(tempfname));
921 
922  if (WithCrypto & APPLICATION_PGP)
923  OptDontHandlePgpKeys = false;
924 
925 cleanup:
926  mutt_buffer_pool_release(&tempfname);
927 }
928 
943 int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
944 {
945  if (!WithCrypto)
946  return 0;
947 
948  struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
949  const char *fqdn = mutt_fqdn(true, NeoMutt->sub);
950  char *self_encrypt = NULL;
951 
952  /* Do a quick check to make sure that we can find all of the encryption
953  * keys if the user has requested this service. */
954 
955  *keylist = NULL;
956 
957 #ifdef USE_AUTOCRYPT
958  if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
959  {
961  return -1;
962  return 0;
963  }
964 #endif
965 
967  OptPgpCheckTrust = true;
968 
969  mutt_addrlist_copy(&addrlist, &e->env->to, false);
970  mutt_addrlist_copy(&addrlist, &e->env->cc, false);
971  mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
972  mutt_addrlist_qualify(&addrlist, fqdn);
973  mutt_addrlist_dedupe(&addrlist);
974 
975  if (oppenc_mode || (e->security & SEC_ENCRYPT))
976  {
977  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
978  {
979  *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
980  if (!*keylist)
981  {
982  mutt_addrlist_clear(&addrlist);
983  return -1;
984  }
985  OptPgpCheckTrust = false;
987  self_encrypt = C_PgpDefaultKey;
988  }
989  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
990  {
991  *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
992  if (!*keylist)
993  {
994  mutt_addrlist_clear(&addrlist);
995  return -1;
996  }
998  self_encrypt = C_SmimeDefaultKey;
999  }
1000  }
1001 
1002  if (!oppenc_mode && self_encrypt)
1003  {
1004  const size_t keylist_size = mutt_str_len(*keylist);
1005  mutt_mem_realloc(keylist, keylist_size + mutt_str_len(self_encrypt) + 2);
1006  sprintf(*keylist + keylist_size, " %s", self_encrypt);
1007  }
1008 
1009  mutt_addrlist_clear(&addrlist);
1010 
1011  return 0;
1012 }
1013 
1022 {
1023  if (!WithCrypto)
1024  return;
1025 
1027  return;
1028 
1029  char *pgpkeylist = NULL;
1030 
1031  crypt_get_keys(e, &pgpkeylist, 1);
1032  if (pgpkeylist)
1033  {
1034  e->security |= SEC_ENCRYPT;
1035  FREE(&pgpkeylist);
1036  }
1037  else
1038  {
1039  e->security &= ~SEC_ENCRYPT;
1040  }
1041 }
1042 
1049 static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
1050 {
1051  if (!WithCrypto)
1052  return;
1053 
1054  for (; a; a = a->next)
1055  {
1056  if (a->type == TYPE_MULTIPART)
1057  crypt_fetch_signatures(signatures, a->parts, n);
1058  else
1059  {
1060  if ((*n % 5) == 0)
1061  mutt_mem_realloc(signatures, (*n + 6) * sizeof(struct Body **));
1062 
1063  (*signatures)[(*n)++] = a;
1064  }
1065  }
1066 }
1067 
1074 {
1077  {
1078  return true;
1079  }
1080 
1081  return false;
1082 }
1083 
1087 int mutt_protected_headers_handler(struct Body *a, struct State *s)
1088 {
1090  {
1091  if (a->mime_headers->subject)
1092  {
1093  const bool display = (s->flags & MUTT_DISPLAY);
1094 
1095  if (display && C_Weed && mutt_matches_ignore("subject"))
1096  return 0;
1097 
1099  int wraplen = display ? mutt_window_wrap_cols(s->wraplen, C_Wrap) : 0;
1100 
1101  mutt_write_one_header(s->fp_out, "Subject", a->mime_headers->subject, s->prefix,
1102  wraplen, display ? CH_DISPLAY : CH_NO_FLAGS, NeoMutt->sub);
1103  state_puts(s, "\n");
1104  }
1105  }
1106 
1107  return 0;
1108 }
1109 
1113 int mutt_signed_handler(struct Body *a, struct State *s)
1114 {
1115  if (!WithCrypto)
1116  return -1;
1117 
1118  bool inconsistent = false;
1119  struct Body *b = a;
1120  struct Body **signatures = NULL;
1121  int sigcnt = 0;
1122  int rc = 0;
1123  struct Buffer *tempfile = NULL;
1124 
1125  a = a->parts;
1126  SecurityFlags signed_type = mutt_is_multipart_signed(b);
1127  if (signed_type == SEC_NO_FLAGS)
1128  {
1129  /* A null protocol value is already checked for in mutt_body_handler() */
1130  state_printf(s,
1131  _("[-- Error: "
1132  "Unknown multipart/signed protocol %s --]\n\n"),
1133  mutt_param_get(&b->parameter, "protocol"));
1134  return mutt_body_handler(a, s);
1135  }
1136 
1137  if (!(a && a->next))
1138  inconsistent = true;
1139  else
1140  {
1141  switch (signed_type)
1142  {
1143  case SEC_SIGN:
1144  if ((a->next->type != TYPE_MULTIPART) || !mutt_istr_equal(a->next->subtype, "mixed"))
1145  {
1146  inconsistent = true;
1147  }
1148  break;
1149  case PGP_SIGN:
1150  if ((a->next->type != TYPE_APPLICATION) ||
1151  !mutt_istr_equal(a->next->subtype, "pgp-signature"))
1152  {
1153  inconsistent = true;
1154  }
1155  break;
1156  case SMIME_SIGN:
1157  if ((a->next->type != TYPE_APPLICATION) ||
1158  (!mutt_istr_equal(a->next->subtype, "x-pkcs7-signature") &&
1159  !mutt_istr_equal(a->next->subtype, "pkcs7-signature")))
1160  {
1161  inconsistent = true;
1162  }
1163  break;
1164  default:
1165  inconsistent = true;
1166  }
1167  }
1168  if (inconsistent)
1169  {
1170  state_attach_puts(s, _("[-- Error: Missing or bad-format multipart/signed "
1171  "signature --]\n\n"));
1172  return mutt_body_handler(a, s);
1173  }
1174 
1175  if (s->flags & MUTT_DISPLAY)
1176  {
1177  crypt_fetch_signatures(&signatures, a->next, &sigcnt);
1178 
1179  if (sigcnt != 0)
1180  {
1181  tempfile = mutt_buffer_pool_get();
1182  mutt_buffer_mktemp(tempfile);
1183  bool goodsig = true;
1184  if (crypt_write_signed(a, s, mutt_b2s(tempfile)) == 0)
1185  {
1186  for (int i = 0; i < sigcnt; i++)
1187  {
1188  if (((WithCrypto & APPLICATION_PGP) != 0) &&
1189  (signatures[i]->type == TYPE_APPLICATION) &&
1190  mutt_istr_equal(signatures[i]->subtype, "pgp-signature"))
1191  {
1192  if (crypt_pgp_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1193  goodsig = false;
1194 
1195  continue;
1196  }
1197 
1198  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1199  (signatures[i]->type == TYPE_APPLICATION) &&
1200  (mutt_istr_equal(signatures[i]->subtype, "x-pkcs7-signature") ||
1201  mutt_istr_equal(signatures[i]->subtype, "pkcs7-signature")))
1202  {
1203  if (crypt_smime_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1204  goodsig = false;
1205 
1206  continue;
1207  }
1208 
1209  state_printf(s,
1210  _("[-- Warning: "
1211  "We can't verify %s/%s signatures. --]\n\n"),
1212  TYPE(signatures[i]), signatures[i]->subtype);
1213  }
1214  }
1215 
1216  mutt_file_unlink(mutt_b2s(tempfile));
1217  mutt_buffer_pool_release(&tempfile);
1218 
1219  b->goodsig = goodsig;
1220  b->badsig = !goodsig;
1221 
1222  /* Now display the signed body */
1223  state_attach_puts(s, _("[-- The following data is signed --]\n\n"));
1224 
1226 
1227  FREE(&signatures);
1228  }
1229  else
1230  {
1232  _("[-- Warning: Can't find any signatures. --]\n\n"));
1233  }
1234  }
1235 
1236  rc = mutt_body_handler(a, s);
1237 
1238  if ((s->flags & MUTT_DISPLAY) && (sigcnt != 0))
1239  state_attach_puts(s, _("\n[-- End of signed data --]\n"));
1240 
1241  return rc;
1242 }
1243 
1258 const char *crypt_get_fingerprint_or_id(const char *p, const char **pphint,
1259  const char **ppl, const char **pps)
1260 {
1261  const char *ps = NULL, *pl = NULL, *phint = NULL;
1262  char *pfcopy = NULL, *s1 = NULL, *s2 = NULL;
1263  char c;
1264  int isid;
1265  size_t hexdigits;
1266 
1267  /* User input may be partial name, fingerprint or short or long key ID,
1268  * independent of C_PgpLongIds.
1269  * Fingerprint without spaces is 40 hex digits (SHA-1) or 32 hex digits (MD5).
1270  * Strip leading "0x" for key ID detection and prepare pl and ps to indicate
1271  * if an ID was found and to simplify logic in the key loop's inner
1272  * condition of the caller. */
1273 
1274  char *pf = mutt_str_skip_whitespace(p);
1275  if (mutt_istr_startswith(pf, "0x"))
1276  pf += 2;
1277 
1278  /* Check if a fingerprint is given, must be hex digits only, blanks
1279  * separating groups of 4 hex digits are allowed. Also pre-check for ID. */
1280  isid = 2; /* unknown */
1281  hexdigits = 0;
1282  s1 = pf;
1283  do
1284  {
1285  c = *(s1++);
1286  if ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) ||
1287  (('a' <= c) && (c <= 'f')))
1288  {
1289  hexdigits++;
1290  if (isid == 2)
1291  isid = 1; /* it is an ID so far */
1292  }
1293  else if (c)
1294  {
1295  isid = 0; /* not an ID */
1296  if ((c == ' ') && ((hexdigits % 4) == 0))
1297  ; /* skip blank before or after 4 hex digits */
1298  else
1299  break; /* any other character or position */
1300  }
1301  } while (c);
1302 
1303  /* If at end of input, check for correct fingerprint length and copy if. */
1304  pfcopy = (!c && ((hexdigits == 40) || (hexdigits == 32)) ? mutt_str_dup(pf) : NULL);
1305 
1306  if (pfcopy)
1307  {
1308  /* Use pfcopy to strip all spaces from fingerprint and as hint. */
1309  s1 = pfcopy;
1310  s2 = pfcopy;
1311  do
1312  {
1313  *(s1++) = *(s2 = mutt_str_skip_whitespace(s2));
1314  } while (*(s2++));
1315 
1316  phint = pfcopy;
1317  ps = NULL;
1318  pl = NULL;
1319  }
1320  else
1321  {
1322  phint = p;
1323  ps = NULL;
1324  pl = NULL;
1325  if (isid == 1)
1326  {
1327  if (mutt_str_len(pf) == 16)
1328  pl = pf; /* long key ID */
1329  else if (mutt_str_len(pf) == 8)
1330  ps = pf; /* short key ID */
1331  }
1332  }
1333 
1334  *pphint = phint;
1335  *ppl = pl;
1336  *pps = ps;
1337  return pfcopy;
1338 }
1339 
1347 bool crypt_is_numerical_keyid(const char *s)
1348 {
1349  /* or should we require the "0x"? */
1350  if (mutt_strn_equal(s, "0x", 2))
1351  s += 2;
1352  if (strlen(s) % 8)
1353  return false;
1354  while (*s)
1355  if (!strchr("0123456789ABCDEFabcdef", *s++))
1356  return false;
1357 
1358  return true;
1359 }
#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:1087
Convenience wrapper for the gui headers.
bool mutt_matches_ignore(const char *s)
Does the string match the ignore list.
Definition: parse.c:314
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:1258
#define SMIME_OPAQUE
Definition: lib.h:113
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:691
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
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 PGP_INLINE
Definition: lib.h:107
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:63
Miscellaneous email parsing routines.
#define SMIME_SIGN
Definition: lib.h:110
#define WithCrypto
Definition: lib.h:123
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:294
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:680
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:475
#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
struct Body * body
List of MIME parts.
Definition: email.h:91
Structs that make up an email.
Autocrypt end-to-end encryption.
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:84
Convenience wrapper for the send headers.
7-bit text
Definition: mime.h:49
void mutt_message_to_7bit(struct Body *a, FILE *fp, struct ConfigSubset *sub)
Convert an email&#39;s MIME parts to 7-bit.
Definition: sendlib.c:746
#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:1113
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:1468
bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: config.c:37
Wrapper around crypto functions.
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:187
#define SMIME_ENCRYPT
Definition: lib.h:109
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:801
bool crypt_smime_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:420
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1073
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:737
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1347
void crypt_forget_passphrase(void)
Forget a passphrase and display a message.
Definition: crypt.c:92
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
#define PGP_ENCRYPT
Definition: lib.h:103
String manipulation buffer.
Definition: buffer.h:33
bool C_CryptProtectedHeadersRead
Config: Display protected headers (Memory Hole) in the pager.
Definition: config.c:43
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:48
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:471
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
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:830
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
void crypt_pgp_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:402
#define _(a)
Definition: message.h:28
bool is_autocrypt
Flag autocrypt-decrypted messages for replying.
Definition: body.h:79
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:39
FILE * fp_out
File to write to.
Definition: state.h:47
char * mailbox
Mailbox and host address.
Definition: address.h:37
unsigned char C_PgpMimeAuto
Config: Prompt the user to use MIME if inline PGP fails.
Definition: config.c:61
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:94
#define SEC_ALL_FLAGS
Definition: lib.h:101
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:83
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:943
int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
Write the message body/part.
Definition: crypt.c:757
Shared constants/structs that are private to libconn.
unsigned char C_SmimeEncryptSelf
Definition: config.c:65
#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
Container for Accounts, Notifications.
Definition: neomutt.h:36
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
Convenience wrapper for the config headers.
Email Address Handling.
Do no use Autocrypt.
Definition: lib.h:157
void crypt_smime_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:539
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:92
Some miscellaneous functions.
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
struct Body * crypt_smime_sign_message(struct Body *a, const struct AddressList *from)
Wrapper for CryptModuleSpecs::sign_message()
Definition: cryptglue.c:486
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1405
void mutt_prepare_envelope(struct Envelope *env, bool final, struct ConfigSubset *sub)
Prepare an email header.
Definition: sendlib.c:1237
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:447
bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: config.c:41
Many unsorted constants and some structs.
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:57
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
Convenience wrapper for the core headers.
void crypt_current_time(struct State *s, const char *app_name)
Print the current time.
Definition: crypt.c:71
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
bool C_CryptTimestamp
Config: Add a timestamp to PGP or SMIME output to prevent spoofing.
Definition: config.c:59
WHERE bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:36
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:407
int wraplen
Width to wrap lines to (when flags & MUTT_DISPLAY)
Definition: state.h:50
char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: config.c:51
Email Aliases.
unsigned int encoding
content-transfer-encoding, ContentEncoding
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
bool C_SmimeSelfEncrypt
Config: Encrypted messages will also be encrypt to C_SmimeDefaultKey too.
Definition: config.c:66
void crypt_smime_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:411
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
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:336
bool C_CryptUsePka
Config: Use GPGME to use PKA (lookup PGP keys using DNS)
Definition: config.c:38
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
#define mutt_b2s(buf)
Definition: buffer.h:41
bool goodsig
Good cryptographic signature.
Definition: body.h:75
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:98
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:552
WHERE short C_Wrap
Config: Width to wrap text in the pager.
Definition: mutt_globals.h:117
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: multipart.c:125
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:97
Signing/encryption multiplexor.
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
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:362
A mailbox.
Definition: mailbox.h:81
struct Address * mutt_default_from(struct ConfigSubset *sub)
Get a default &#39;from&#39; Address.
Definition: send.c:1323
#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
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:159
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
#define PGP_SIGN
Definition: lib.h:104
struct Body * crypt_pgp_traditional_encryptsign(struct Body *a, int flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign()
Definition: cryptglue.c:292
API for encryption/signing of emails.
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
Definition: mutt_window.c:487
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:508
void state_mark_protected_header(struct State *s)
Write a unique marker around protected headers.
Definition: state.c:56
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
WHERE bool OptPgpCheckTrust
(pseudo) used by dlg_select_pgp_key()
Definition: options.h:49
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:610
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
bool C_PgpRetainableSigs
Config: Create nested multipart/signed or encrypted messages.
Definition: config.c:62
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1049
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * description
content-description
Definition: body.h:40
bool C_PgpStrictEnc
Config: Encode PGP signed messages with quoted-printable (don&#39;t unset)
Definition: config.c:64
char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: config.c:54
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:93
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:88
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
bool from
Has a line beginning with "From "?
Definition: content.h:43
Type: &#39;message/*&#39;.
Definition: mime.h:35
bool mutt_strn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:598
#define SEC_SIGN
Email is signed.
Definition: lib.h:86
#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:604
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:89
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:517
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:636
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1021
struct Body * crypt_smime_build_smime_entity(struct Body *a, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity()
Definition: cryptglue.c:497
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:650
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:314
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:1181
void crypt_smime_invoke_import(const char *infile, const char *mailbox)
Wrapper for CryptModuleSpecs::smime_invoke_import()
Definition: cryptglue.c:508
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:551
Duplicate the structure of an entire email.
#define PGP_KEY
Definition: lib.h:106
int n
Definition: acutest.h:492
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:808
unsigned char C_PgpEncryptSelf
Definition: config.c:60
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
struct Email * email
Email in the list.
Definition: email.h:125
#define mutt_error(...)
Definition: logging.h:84
Binary.
Definition: mime.h:53
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:325
#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
bool C_PgpSelfEncrypt
Config: Encrypted messages will also be encrypted to C_PgpDefaultKey too.
Definition: config.c:63
int crypt_smime_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:517
bool space
Whitespace at the end of lines?
Definition: content.h:41
bool C_Weed
Config: Filter headers when displaying/forwarding/printing/replying.
Definition: globals.c:40
void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
Extract keys from a message.
Definition: crypt.c:844
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:1593
List of Emails.
Definition: email.h:123
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:47
Hundreds of global variables to back the user variables.
Handling of global boolean variables.
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
#define TAILQ_EMPTY(head)
Definition: queue.h:714
#define MUTT_CM_NOHEADER
Don&#39;t copy the message header.
Definition: copy.h:35
Convenience wrapper for the library headers.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
#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
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:685
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:87
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:89
Type: &#39;application/*&#39;.
Definition: mime.h:33
bool crypt_pgp_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:196
struct Address * C_EnvelopeFromAddress
Config: Manually set the sender for outgoing messages.
Definition: config.c:58
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: config.c:57
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags, struct ConfigSubset *sub)
Write one header line to a file.
Definition: header.c:419
The header of an Email.
Definition: envelope.h:54
int crypt_pgp_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:371
bool C_CryptProtectedHeadersWrite
Config: Generate protected header (Memory Hole) for signed and encrypted emails.
Definition: config.c:45