NeoMutt  2020-04-24
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/lib.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 "init.h"
53 #include "mutt_parse.h"
54 #include "muttlib.h"
55 #include "options.h"
56 #include "send.h"
57 #include "sendlib.h"
58 #include "state.h"
59 #include "ncrypt/lib.h"
60 #ifdef USE_AUTOCRYPT
61 #include "autocrypt/lib.h"
62 #endif
63 
64 struct Mailbox;
65 
66 /* These Config Variables are only used in ncrypt/crypt.c */
67 bool C_CryptTimestamp;
68 unsigned char C_PgpEncryptSelf;
69 unsigned char C_PgpMimeAuto;
73 unsigned char C_SmimeEncryptSelf;
75 
83 void crypt_current_time(struct State *s, const char *app_name)
84 {
85  char p[256], tmp[256];
86 
87  if (!WithCrypto)
88  return;
89 
90  if (C_CryptTimestamp)
91  {
92  mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), MUTT_DATE_NOW);
93  }
94  else
95  *p = '\0';
96 
97  snprintf(tmp, sizeof(tmp), _("[-- %s output follows%s --]\n"), NONULL(app_name), p);
98  state_attach_puts(s, tmp);
99 }
100 
105 {
108 
111 
112  if (WithCrypto)
113  {
114  /* L10N: Due to the implementation details (e.g. some passwords are managed
115  by gpg-agent) we can't know whether we forgot zero, 1, 12, ...
116  passwords. So in English we use "Passphrases". Your language might
117  have other means to express this. */
118  mutt_message(_("Passphrases forgotten"));
119  }
120 }
121 
122 #ifndef DEBUG
123 #include <sys/resource.h>
127 static void disable_coredumps(void)
128 {
129  struct rlimit rl = { 0, 0 };
130  static bool done = false;
131 
132  if (!done)
133  {
134  setrlimit(RLIMIT_CORE, &rl);
135  done = true;
136  }
137 }
138 #endif
139 
147 {
148  bool rc = false;
149 
150 #ifndef DEBUG
151  disable_coredumps();
152 #endif
153 
154  if (((WithCrypto & APPLICATION_PGP) != 0) && (flags & APPLICATION_PGP))
156 
157  if (((WithCrypto & APPLICATION_SMIME) != 0) && (flags & APPLICATION_SMIME))
159 
160  return rc;
161 }
162 
171 int mutt_protect(struct Email *e, char *keylist, bool postpone)
172 {
173  struct Body *pbody = NULL, *tmp_pbody = NULL;
174  struct Body *tmp_smime_pbody = NULL;
175  struct Body *tmp_pgp_pbody = NULL;
176  bool has_retainable_sig = false;
177 
178  if (!WithCrypto)
179  return -1;
180 
181  int security = e->security;
182  int sign = security & (SEC_AUTOCRYPT | SEC_SIGN);
183  if (postpone)
184  {
185  sign = SEC_NO_FLAGS;
186  security &= ~SEC_SIGN;
187  }
188 
189  if (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) && !sign)
190  return 0;
191 
192  if (sign && !(security & SEC_AUTOCRYPT) && !crypt_valid_passphrase(security))
193  return -1;
194 
195  if (((WithCrypto & APPLICATION_PGP) != 0) && !(security & SEC_AUTOCRYPT) &&
196  ((security & PGP_INLINE) == PGP_INLINE))
197  {
198  if ((e->content->type != TYPE_TEXT) ||
199  (mutt_str_strcasecmp(e->content->subtype, "plain") != 0))
200  {
202  _("Inline PGP can't be used with attachments. "
203  "Revert to PGP/MIME?")) != MUTT_YES)
204  {
205  mutt_error(
206  _("Mail not sent: inline PGP can't be used with attachments"));
207  return -1;
208  }
209  }
210  else if (mutt_str_strcasecmp("flowed", mutt_param_get(&e->content->parameter, "format")) == 0)
211  {
213  _("Inline PGP can't be used with format=flowed. "
214  "Revert to PGP/MIME?"))) != MUTT_YES)
215  {
216  mutt_error(
217  _("Mail not sent: inline PGP can't be used with format=flowed"));
218  return -1;
219  }
220  }
221  else
222  {
223  /* they really want to send it inline... go for it */
224  if (!isendwin())
225  {
226  mutt_endwin();
227  puts(_("Invoking PGP..."));
228  }
229  pbody = crypt_pgp_traditional_encryptsign(e->content, security, keylist);
230  if (pbody)
231  {
232  e->content = pbody;
233  return 0;
234  }
235 
236  /* otherwise inline won't work...ask for revert */
237  if (query_quadoption(
239  _("Message can't be sent inline. Revert to using PGP/MIME?")) != MUTT_YES)
240  {
241  mutt_error(_("Mail not sent"));
242  return -1;
243  }
244  }
245 
246  /* go ahead with PGP/MIME */
247  }
248 
249  if (!isendwin())
250  mutt_endwin();
251 
253  tmp_smime_pbody = e->content;
254  if (WithCrypto & APPLICATION_PGP)
255  tmp_pgp_pbody = e->content;
256 
257 #ifdef CRYPT_BACKEND_GPGME
258  if (sign && C_CryptUsePka)
259 #else
260  if (sign)
261 #endif
262  {
263  /* Set sender (necessary for e.g. PKA). */
264  const char *mailbox = NULL;
265  struct Address *from = TAILQ_FIRST(&e->env->from);
266  bool free_from = false;
267 
268  if (!from)
269  {
270  free_from = true;
271  from = mutt_default_from();
272  }
273 
274  mailbox = from->mailbox;
275  if (!mailbox && C_EnvelopeFromAddress)
276  mailbox = C_EnvelopeFromAddress->mailbox;
277 
278  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
279  crypt_smime_set_sender(mailbox);
280  else if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
281  crypt_pgp_set_sender(mailbox);
282 
283  if (free_from)
284  mutt_addr_free(&from);
285  }
286 
288  {
289  struct Envelope *protected_headers = mutt_env_new();
290  mutt_str_replace(&protected_headers->subject, e->env->subject);
291  /* Note: if other headers get added, such as to, cc, then a call to
292  * mutt_env_to_intl() will need to be added here too. */
293  mutt_prepare_envelope(protected_headers, 0);
294 
296  e->content->mime_headers = protected_headers;
297  /* Optional part of the draft RFC, but required by Enigmail */
298  mutt_param_set(&e->content->parameter, "protected-headers", "v1");
299  }
300  else
301  {
302  mutt_param_delete(&e->content->parameter, "protected-headers");
303  }
304 
305 #ifdef USE_AUTOCRYPT
306  /* A note about e->content->mime_headers. If postpone or send
307  * fails, the mime_headers is cleared out before returning to the
308  * compose menu. So despite the "robustness" code above and in the
309  * gen_gossip_list function below, mime_headers will not be set when
310  * entering mutt_protect().
311  *
312  * This is important to note because the user could toggle
313  * $crypt_protected_headers_write or $autocrypt off back in the
314  * compose menu. We don't want mutt_write_rfc822_header() to write
315  * stale data from one option if the other is set.
316  */
317  if (C_Autocrypt && !postpone && (security & SEC_AUTOCRYPT))
318  {
320  }
321 #endif
322 
323  if (sign)
324  {
325  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
326  {
327  tmp_pbody = crypt_smime_sign_message(e->content, &e->env->from);
328  if (!tmp_pbody)
329  goto bail;
330  pbody = tmp_pbody;
331  tmp_smime_pbody = tmp_pbody;
332  }
333 
334  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP) &&
335  (!(security & (SEC_ENCRYPT | SEC_AUTOCRYPT)) || C_PgpRetainableSigs))
336  {
337  tmp_pbody = crypt_pgp_sign_message(e->content, &e->env->from);
338  if (!tmp_pbody)
339  goto bail;
340 
341  has_retainable_sig = true;
342  sign = SEC_NO_FLAGS;
343  pbody = tmp_pbody;
344  tmp_pgp_pbody = tmp_pbody;
345  }
346 
347  if ((WithCrypto != 0) && (security & APPLICATION_SMIME) && (security & APPLICATION_PGP))
348  {
349  /* here comes the draft ;-) */
350  }
351  }
352 
353  if (security & (SEC_ENCRYPT | SEC_AUTOCRYPT))
354  {
355  if (((WithCrypto & APPLICATION_SMIME) != 0) && (security & APPLICATION_SMIME))
356  {
357  tmp_pbody = crypt_smime_build_smime_entity(tmp_smime_pbody, keylist);
358  if (!tmp_pbody)
359  {
360  /* signed ? free it! */
361  goto bail;
362  }
363  /* free tmp_body if messages was signed AND encrypted ... */
364  if ((tmp_smime_pbody != e->content) && (tmp_smime_pbody != tmp_pbody))
365  {
366  /* detach and don't delete e->content,
367  * which tmp_smime_pbody->parts after signing. */
368  tmp_smime_pbody->parts = tmp_smime_pbody->parts->next;
369  e->content->next = NULL;
370  mutt_body_free(&tmp_smime_pbody);
371  }
372  pbody = tmp_pbody;
373  }
374 
375  if (((WithCrypto & APPLICATION_PGP) != 0) && (security & APPLICATION_PGP))
376  {
377  pbody = crypt_pgp_encrypt_message(e, tmp_pgp_pbody, keylist, sign, &e->env->from);
378  if (!pbody)
379  {
380  /* did we perform a retainable signature? */
381  if (has_retainable_sig)
382  {
383  /* remove the outer multipart layer */
384  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
385  /* get rid of the signature */
386  mutt_body_free(&tmp_pgp_pbody->next);
387  }
388 
389  goto bail;
390  }
391 
392  // destroy temporary signature envelope when doing retainable signatures.
393  if (has_retainable_sig)
394  {
395  tmp_pgp_pbody = mutt_remove_multipart(tmp_pgp_pbody);
396  mutt_body_free(&tmp_pgp_pbody->next);
397  }
398  }
399  }
400 
401  if (pbody)
402  {
403  e->content = pbody;
404  return 0;
405  }
406 
407 bail:
409  return -1;
410 }
411 
419 {
420  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
421  (mutt_str_strcasecmp(b->subtype, "signed") != 0))
422  {
423  return SEC_NO_FLAGS;
424  }
425 
426  char *p = mutt_param_get(&b->parameter, "protocol");
427  if (!p)
428  return SEC_NO_FLAGS;
429 
430  if (!(mutt_str_strcasecmp(p, "multipart/mixed") != 0))
431  return SEC_SIGN;
432 
433  if (((WithCrypto & APPLICATION_PGP) != 0) &&
434  !(mutt_str_strcasecmp(p, "application/pgp-signature") != 0))
435  {
436  return PGP_SIGN;
437  }
438 
439  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
440  !(mutt_str_strcasecmp(p, "application/x-pkcs7-signature") != 0))
441  {
442  return SMIME_SIGN;
443  }
444  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
445  !(mutt_str_strcasecmp(p, "application/pkcs7-signature") != 0))
446  {
447  return SMIME_SIGN;
448  }
449 
450  return SEC_NO_FLAGS;
451 }
452 
460 {
461  if ((WithCrypto & APPLICATION_PGP) == 0)
462  return SEC_NO_FLAGS;
463 
464  char *p = NULL;
465 
466  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
467  (mutt_str_strcasecmp(b->subtype, "encrypted") != 0) ||
468  !(p = mutt_param_get(&b->parameter, "protocol")) ||
469  (mutt_str_strcasecmp(p, "application/pgp-encrypted") != 0))
470  {
471  return SEC_NO_FLAGS;
472  }
473 
474  return PGP_ENCRYPT;
475 }
476 
484 {
486  return 0;
487 
488  b = b->parts;
489  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
490  (mutt_str_strcasecmp(b->subtype, "pgp-encrypted") != 0))
491  {
492  return 0;
493  }
494 
495  b = b->next;
496  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
497  (mutt_str_strcasecmp(b->subtype, "octet-stream") != 0))
498  {
499  return 0;
500  }
501 
502  return PGP_ENCRYPT;
503 }
504 
521 {
522  if (!(WithCrypto & APPLICATION_PGP))
523  return SEC_NO_FLAGS;
524 
525  if (!b || (b->type != TYPE_MULTIPART) || !b->subtype ||
526  (mutt_str_strcasecmp(b->subtype, "mixed") != 0))
527  {
528  return SEC_NO_FLAGS;
529  }
530 
531  b = b->parts;
532  if (!b || (b->type != TYPE_TEXT) || !b->subtype ||
533  (mutt_str_strcasecmp(b->subtype, "plain") != 0) || (b->length != 0))
534  {
535  return SEC_NO_FLAGS;
536  }
537 
538  b = b->next;
539  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
540  (mutt_str_strcasecmp(b->subtype, "pgp-encrypted") != 0))
541  {
542  return SEC_NO_FLAGS;
543  }
544 
545  b = b->next;
546  if (!b || (b->type != TYPE_APPLICATION) || !b->subtype ||
547  (mutt_str_strcasecmp(b->subtype, "octet-stream") != 0))
548  {
549  return SEC_NO_FLAGS;
550  }
551 
552  b = b->next;
553  if (b)
554  return SEC_NO_FLAGS;
555 
556  return PGP_ENCRYPT;
557 }
558 
566 {
568  char *p = NULL;
569 
570  if (m->type == TYPE_APPLICATION)
571  {
572  if ((mutt_str_strcasecmp(m->subtype, "pgp") == 0) ||
573  (mutt_str_strcasecmp(m->subtype, "x-pgp-message") == 0))
574  {
575  p = mutt_param_get(&m->parameter, "x-action");
576  if (p && ((mutt_str_strcasecmp(p, "sign") == 0) ||
577  (mutt_str_strcasecmp(p, "signclear") == 0)))
578  {
579  t |= PGP_SIGN;
580  }
581 
582  p = mutt_param_get(&m->parameter, "format");
583  if (p && (mutt_str_strcasecmp(p, "keys-only") == 0))
584  {
585  t |= PGP_KEY;
586  }
587 
588  if (t == SEC_NO_FLAGS)
589  t |= PGP_ENCRYPT; /* not necessarily correct, but... */
590  }
591 
592  if (mutt_str_strcasecmp(m->subtype, "pgp-signed") == 0)
593  t |= PGP_SIGN;
594 
595  if (mutt_str_strcasecmp(m->subtype, "pgp-keys") == 0)
596  t |= PGP_KEY;
597  }
598  else if ((m->type == TYPE_TEXT) && (mutt_str_strcasecmp("plain", m->subtype) == 0))
599  {
600  if (((p = mutt_param_get(&m->parameter, "x-mutt-action")) ||
601  (p = mutt_param_get(&m->parameter, "x-action")) ||
602  (p = mutt_param_get(&m->parameter, "action"))) &&
603  mutt_str_startswith(p, "pgp-sign", CASE_IGNORE))
604  {
605  t |= PGP_SIGN;
606  }
607  else if (p && mutt_str_startswith(p, "pgp-encrypt", CASE_IGNORE))
608  t |= PGP_ENCRYPT;
609  else if (p && mutt_str_startswith(p, "pgp-keys", CASE_IGNORE))
610  t |= PGP_KEY;
611  }
612  if (t)
613  t |= PGP_INLINE;
614 
615  return t;
616 }
617 
625 {
626  if (!m)
627  return SEC_NO_FLAGS;
628 
629  if (((m->type & TYPE_APPLICATION) == 0) || !m->subtype)
630  return SEC_NO_FLAGS;
631 
632  char *t = NULL;
633  bool complain = false;
634  /* S/MIME MIME types don't need x- anymore, see RFC2311 */
635  if ((mutt_str_strcasecmp(m->subtype, "x-pkcs7-mime") == 0) ||
636  (mutt_str_strcasecmp(m->subtype, "pkcs7-mime") == 0))
637  {
638  t = mutt_param_get(&m->parameter, "smime-type");
639  if (t)
640  {
641  if (mutt_str_strcasecmp(t, "enveloped-data") == 0)
642  return SMIME_ENCRYPT;
643  if (mutt_str_strcasecmp(t, "signed-data") == 0)
644  return SMIME_SIGN | SMIME_OPAQUE;
645  return SEC_NO_FLAGS;
646  }
647  /* Netscape 4.7 uses
648  * Content-Description: S/MIME Encrypted Message
649  * instead of Content-Type parameter */
650  if (mutt_str_strcasecmp(m->description, "S/MIME Encrypted Message") == 0)
651  return SMIME_ENCRYPT;
652  complain = true;
653  }
654  else if (mutt_str_strcasecmp(m->subtype, "octet-stream") != 0)
655  return SEC_NO_FLAGS;
656 
657  t = mutt_param_get(&m->parameter, "name");
658 
659  if (!t)
660  t = m->d_filename;
661  if (!t)
662  t = m->filename;
663  if (!t)
664  {
665  if (complain)
666  {
667  mutt_message(
668  _("S/MIME messages with no hints on content are unsupported"));
669  }
670  return SEC_NO_FLAGS;
671  }
672 
673  /* no .p7c, .p10 support yet. */
674 
675  int len = mutt_str_strlen(t) - 4;
676  if ((len > 0) && (*(t + len) == '.'))
677  {
678  len++;
679  if (mutt_str_strcasecmp((t + len), "p7m") == 0)
680  {
681  /* Not sure if this is the correct thing to do, but
682  * it's required for compatibility with Outlook */
683  return SMIME_SIGN | SMIME_OPAQUE;
684  }
685  else if (mutt_str_strcasecmp((t + len), "p7s") == 0)
686  return SMIME_SIGN | SMIME_OPAQUE;
687  }
688 
689  return SEC_NO_FLAGS;
690 }
691 
701 {
702  if (!WithCrypto || !m)
703  return SEC_NO_FLAGS;
704 
706 
707  if (m->type == TYPE_APPLICATION)
708  {
710  rc |= mutt_is_application_pgp(m);
711 
713  {
714  rc |= mutt_is_application_smime(m);
715  if (rc && m->goodsig)
716  rc |= SEC_GOODSIGN;
717  if (rc && m->badsig)
718  rc |= SEC_BADSIGN;
719  }
720  }
721  else if (((WithCrypto & APPLICATION_PGP) != 0) && (m->type == TYPE_TEXT))
722  {
723  rc |= mutt_is_application_pgp(m);
724  if (rc && m->goodsig)
725  rc |= SEC_GOODSIGN;
726  }
727 
728  if (m->type == TYPE_MULTIPART)
729  {
731  rc |= mutt_is_multipart_signed(m);
733 
734  if (rc && m->goodsig)
735  rc |= SEC_GOODSIGN;
736 #ifdef USE_AUTOCRYPT
737  if (rc && m->is_autocrypt)
738  rc |= SEC_AUTOCRYPT;
739 #endif
740  }
741 
742  if ((m->type == TYPE_MULTIPART) || (m->type == TYPE_MESSAGE))
743  {
744  SecurityFlags u = m->parts ? SEC_ALL_FLAGS : SEC_NO_FLAGS; /* Bits set in all parts */
745  SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */
746 
747  for (struct Body *b = m->parts; b; b = b->next)
748  {
749  const SecurityFlags v = crypt_query(b);
750  u &= v;
751  w |= v;
752  }
753  rc |= u | (w & ~SEC_GOODSIGN);
754 
755  if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN))
756  rc |= SEC_PARTSIGN;
757  }
758 
759  return rc;
760 }
761 
772 int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
773 {
774  if (!WithCrypto)
775  return -1;
776 
777  FILE *fp = mutt_file_fopen(tempfile, "w");
778  if (!fp)
779  {
780  mutt_perror(tempfile);
781  return -1;
782  }
783 
784  fseeko(s->fp_in, a->hdr_offset, SEEK_SET);
785  size_t bytes = a->length + a->offset - a->hdr_offset;
786  bool hadcr = false;
787  while (bytes > 0)
788  {
789  const int c = fgetc(s->fp_in);
790  if (c == EOF)
791  break;
792 
793  bytes--;
794 
795  if (c == '\r')
796  hadcr = true;
797  else
798  {
799  if ((c == '\n') && !hadcr)
800  fputc('\r', fp);
801 
802  hadcr = false;
803  }
804 
805  fputc(c, fp);
806  }
807  mutt_file_fclose(&fp);
808 
809  return 0;
810 }
811 
817 {
818  if (!WithCrypto)
819  return;
820 
821  while (a)
822  {
823  if (a->type == TYPE_MULTIPART)
824  {
825  if (a->encoding != ENC_7BIT)
826  {
827  a->encoding = ENC_7BIT;
829  }
830  else if (((WithCrypto & APPLICATION_PGP) != 0) && C_PgpStrictEnc)
832  }
833  else if ((a->type == TYPE_MESSAGE) &&
834  (mutt_str_strcasecmp(a->subtype, "delivery-status") != 0))
835  {
836  if (a->encoding != ENC_7BIT)
837  mutt_message_to_7bit(a, NULL);
838  }
839  else if (a->encoding == ENC_8BIT)
841  else if (a->encoding == ENC_BINARY)
842  a->encoding = ENC_BASE64;
843  else if (a->content && (a->encoding != ENC_BASE64) &&
844  (a->content->from || (a->content->space && C_PgpStrictEnc)))
845  {
847  }
848  a = a->next;
849  }
850 }
851 
859 void crypt_extract_keys_from_messages(struct Mailbox *m, struct EmailList *el)
860 {
861  if (!WithCrypto)
862  return;
863 
864  struct Buffer *tempfname = mutt_buffer_pool_get();
865  mutt_buffer_mktemp(tempfname);
866  FILE *fp_out = mutt_file_fopen(mutt_b2s(tempfname), "w");
867  if (!fp_out)
868  {
869  mutt_perror(mutt_b2s(tempfname));
870  goto cleanup;
871  }
872 
874  OptDontHandlePgpKeys = true;
875 
876  struct EmailNode *en = NULL;
877  STAILQ_FOREACH(en, el, entries)
878  {
879  struct Email *e = en->email;
880 
883  {
884  mutt_file_fclose(&fp_out);
885  break;
886  }
887 
888  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
889  {
891  fflush(fp_out);
892 
893  mutt_endwin();
894  puts(_("Trying to extract PGP keys...\n"));
895  crypt_pgp_invoke_import(mutt_b2s(tempfname));
896  }
897 
898  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
899  {
900  if (e->security & SEC_ENCRYPT)
901  {
903  CH_NO_FLAGS, 0);
904  }
905  else
907  fflush(fp_out);
908 
909  char *mbox = NULL;
910  if (!TAILQ_EMPTY(&e->env->from))
911  {
913  mbox = TAILQ_FIRST(&e->env->from)->mailbox;
914  }
915  else if (!TAILQ_EMPTY(&e->env->sender))
916  {
918  mbox = TAILQ_FIRST(&e->env->sender)->mailbox;
919  }
920  if (mbox)
921  {
922  mutt_endwin();
923  puts(_("Trying to extract S/MIME certificates..."));
924  crypt_smime_invoke_import(mutt_b2s(tempfname), mbox);
925  }
926  }
927 
928  rewind(fp_out);
929  }
930 
931  mutt_file_fclose(&fp_out);
932  if (isendwin())
934 
935  mutt_file_unlink(mutt_b2s(tempfname));
936 
937  if (WithCrypto & APPLICATION_PGP)
938  OptDontHandlePgpKeys = false;
939 
940 cleanup:
941  mutt_buffer_pool_release(&tempfname);
942 }
943 
958 int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
959 {
960  if (!WithCrypto)
961  return 0;
962 
963  struct AddressList addrlist = TAILQ_HEAD_INITIALIZER(addrlist);
964  const char *fqdn = mutt_fqdn(true);
965  char *self_encrypt = NULL;
966 
967  /* Do a quick check to make sure that we can find all of the encryption
968  * keys if the user has requested this service. */
969 
970  *keylist = NULL;
971 
972 #ifdef USE_AUTOCRYPT
973  if (!oppenc_mode && (e->security & SEC_AUTOCRYPT))
974  {
976  return -1;
977  return 0;
978  }
979 #endif
980 
982  OptPgpCheckTrust = true;
983 
984  mutt_addrlist_copy(&addrlist, &e->env->to, false);
985  mutt_addrlist_copy(&addrlist, &e->env->cc, false);
986  mutt_addrlist_copy(&addrlist, &e->env->bcc, false);
987  mutt_addrlist_qualify(&addrlist, fqdn);
988  mutt_addrlist_dedupe(&addrlist);
989 
990  if (oppenc_mode || (e->security & SEC_ENCRYPT))
991  {
992  if (((WithCrypto & APPLICATION_PGP) != 0) && (e->security & APPLICATION_PGP))
993  {
994  *keylist = crypt_pgp_find_keys(&addrlist, oppenc_mode);
995  if (!*keylist)
996  {
997  mutt_addrlist_clear(&addrlist);
998  return -1;
999  }
1000  OptPgpCheckTrust = false;
1002  self_encrypt = C_PgpDefaultKey;
1003  }
1004  if (((WithCrypto & APPLICATION_SMIME) != 0) && (e->security & APPLICATION_SMIME))
1005  {
1006  *keylist = crypt_smime_find_keys(&addrlist, oppenc_mode);
1007  if (!*keylist)
1008  {
1009  mutt_addrlist_clear(&addrlist);
1010  return -1;
1011  }
1013  self_encrypt = C_SmimeDefaultKey;
1014  }
1015  }
1016 
1017  if (!oppenc_mode && self_encrypt)
1018  {
1019  const size_t keylist_size = mutt_str_strlen(*keylist);
1020  mutt_mem_realloc(keylist, keylist_size + mutt_str_strlen(self_encrypt) + 2);
1021  sprintf(*keylist + keylist_size, " %s", self_encrypt);
1022  }
1023 
1024  mutt_addrlist_clear(&addrlist);
1025 
1026  return 0;
1027 }
1028 
1037 {
1038  if (!WithCrypto)
1039  return;
1040 
1042  return;
1043 
1044  char *pgpkeylist = NULL;
1045 
1046  crypt_get_keys(e, &pgpkeylist, 1);
1047  if (pgpkeylist)
1048  {
1049  e->security |= SEC_ENCRYPT;
1050  FREE(&pgpkeylist);
1051  }
1052  else
1053  {
1054  e->security &= ~SEC_ENCRYPT;
1055  }
1056 }
1057 
1064 static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
1065 {
1066  if (!WithCrypto)
1067  return;
1068 
1069  for (; a; a = a->next)
1070  {
1071  if (a->type == TYPE_MULTIPART)
1072  crypt_fetch_signatures(signatures, a->parts, n);
1073  else
1074  {
1075  if ((*n % 5) == 0)
1076  mutt_mem_realloc(signatures, (*n + 6) * sizeof(struct Body **));
1077 
1078  (*signatures)[(*n)++] = a;
1079  }
1080  }
1081 }
1082 
1089 {
1092  {
1093  return true;
1094  }
1095 
1096  return false;
1097 }
1098 
1102 int mutt_protected_headers_handler(struct Body *a, struct State *s)
1103 {
1105  {
1106  if (a->mime_headers->subject)
1107  {
1108  const bool display = (s->flags & MUTT_DISPLAY);
1109 
1110  if (display && C_Weed && mutt_matches_ignore("subject"))
1111  return 0;
1112 
1114  int wraplen = display ? mutt_window_wrap_cols(s->wraplen, C_Wrap) : 0;
1115 
1116  mutt_write_one_header(s->fp_out, "Subject", a->mime_headers->subject,
1117  s->prefix, wraplen, display ? CH_DISPLAY : CH_NO_FLAGS);
1118  state_puts(s, "\n");
1119  }
1120  }
1121 
1122  return 0;
1123 }
1124 
1128 int mutt_signed_handler(struct Body *a, struct State *s)
1129 {
1130  if (!WithCrypto)
1131  return -1;
1132 
1133  bool inconsistent = false;
1134  struct Body *b = a;
1135  struct Body **signatures = NULL;
1136  int sigcnt = 0;
1137  int rc = 0;
1138  struct Buffer *tempfile = NULL;
1139 
1140  a = a->parts;
1141  SecurityFlags signed_type = mutt_is_multipart_signed(b);
1142  if (signed_type == SEC_NO_FLAGS)
1143  {
1144  /* A null protocol value is already checked for in mutt_body_handler() */
1145  state_printf(s,
1146  _("[-- Error: "
1147  "Unknown multipart/signed protocol %s --]\n\n"),
1148  mutt_param_get(&b->parameter, "protocol"));
1149  return mutt_body_handler(a, s);
1150  }
1151 
1152  if (!(a && a->next))
1153  inconsistent = true;
1154  else
1155  {
1156  switch (signed_type)
1157  {
1158  case SEC_SIGN:
1159  if ((a->next->type != TYPE_MULTIPART) ||
1160  (mutt_str_strcasecmp(a->next->subtype, "mixed") != 0))
1161  {
1162  inconsistent = true;
1163  }
1164  break;
1165  case PGP_SIGN:
1166  if ((a->next->type != TYPE_APPLICATION) ||
1167  (mutt_str_strcasecmp(a->next->subtype, "pgp-signature") != 0))
1168  {
1169  inconsistent = true;
1170  }
1171  break;
1172  case SMIME_SIGN:
1173  if ((a->next->type != TYPE_APPLICATION) ||
1174  ((mutt_str_strcasecmp(a->next->subtype, "x-pkcs7-signature") != 0) &&
1175  (mutt_str_strcasecmp(a->next->subtype, "pkcs7-signature") != 0)))
1176  {
1177  inconsistent = true;
1178  }
1179  break;
1180  default:
1181  inconsistent = true;
1182  }
1183  }
1184  if (inconsistent)
1185  {
1186  state_attach_puts(s, _("[-- Error: Missing or bad-format multipart/signed "
1187  "signature --]\n\n"));
1188  return mutt_body_handler(a, s);
1189  }
1190 
1191  if (s->flags & MUTT_DISPLAY)
1192  {
1193  crypt_fetch_signatures(&signatures, a->next, &sigcnt);
1194 
1195  if (sigcnt != 0)
1196  {
1197  tempfile = mutt_buffer_pool_get();
1198  mutt_buffer_mktemp(tempfile);
1199  bool goodsig = true;
1200  if (crypt_write_signed(a, s, mutt_b2s(tempfile)) == 0)
1201  {
1202  for (int i = 0; i < sigcnt; i++)
1203  {
1204  if (((WithCrypto & APPLICATION_PGP) != 0) &&
1205  (signatures[i]->type == TYPE_APPLICATION) &&
1206  (mutt_str_strcasecmp(signatures[i]->subtype, "pgp-signature") == 0))
1207  {
1208  if (crypt_pgp_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1209  goodsig = false;
1210 
1211  continue;
1212  }
1213 
1214  if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1215  (signatures[i]->type == TYPE_APPLICATION) &&
1216  ((mutt_str_strcasecmp(signatures[i]->subtype,
1217  "x-pkcs7-signature") == 0) ||
1218  (mutt_str_strcasecmp(signatures[i]->subtype,
1219  "pkcs7-signature") == 0)))
1220  {
1221  if (crypt_smime_verify_one(signatures[i], s, mutt_b2s(tempfile)) != 0)
1222  goodsig = false;
1223 
1224  continue;
1225  }
1226 
1227  state_printf(s,
1228  _("[-- Warning: "
1229  "We can't verify %s/%s signatures. --]\n\n"),
1230  TYPE(signatures[i]), signatures[i]->subtype);
1231  }
1232  }
1233 
1234  mutt_file_unlink(mutt_b2s(tempfile));
1235  mutt_buffer_pool_release(&tempfile);
1236 
1237  b->goodsig = goodsig;
1238  b->badsig = !goodsig;
1239 
1240  /* Now display the signed body */
1241  state_attach_puts(s, _("[-- The following data is signed --]\n\n"));
1242 
1244 
1245  FREE(&signatures);
1246  }
1247  else
1248  {
1250  _("[-- Warning: Can't find any signatures. --]\n\n"));
1251  }
1252  }
1253 
1254  rc = mutt_body_handler(a, s);
1255 
1256  if ((s->flags & MUTT_DISPLAY) && (sigcnt != 0))
1257  state_attach_puts(s, _("\n[-- End of signed data --]\n"));
1258 
1259  return rc;
1260 }
1261 
1276 const char *crypt_get_fingerprint_or_id(const char *p, const char **pphint,
1277  const char **ppl, const char **pps)
1278 {
1279  const char *ps = NULL, *pl = NULL, *phint = NULL;
1280  char *pfcopy = NULL, *s1 = NULL, *s2 = NULL;
1281  char c;
1282  int isid;
1283  size_t hexdigits;
1284 
1285  /* User input may be partial name, fingerprint or short or long key ID,
1286  * independent of C_PgpLongIds.
1287  * Fingerprint without spaces is 40 hex digits (SHA-1) or 32 hex digits (MD5).
1288  * Strip leading "0x" for key ID detection and prepare pl and ps to indicate
1289  * if an ID was found and to simplify logic in the key loop's inner
1290  * condition of the caller. */
1291 
1292  char *pf = mutt_str_skip_whitespace(p);
1293  if (mutt_str_startswith(pf, "0x", CASE_IGNORE))
1294  pf += 2;
1295 
1296  /* Check if a fingerprint is given, must be hex digits only, blanks
1297  * separating groups of 4 hex digits are allowed. Also pre-check for ID. */
1298  isid = 2; /* unknown */
1299  hexdigits = 0;
1300  s1 = pf;
1301  do
1302  {
1303  c = *(s1++);
1304  if ((('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) ||
1305  (('a' <= c) && (c <= 'f')))
1306  {
1307  hexdigits++;
1308  if (isid == 2)
1309  isid = 1; /* it is an ID so far */
1310  }
1311  else if (c)
1312  {
1313  isid = 0; /* not an ID */
1314  if ((c == ' ') && ((hexdigits % 4) == 0))
1315  ; /* skip blank before or after 4 hex digits */
1316  else
1317  break; /* any other character or position */
1318  }
1319  } while (c);
1320 
1321  /* If at end of input, check for correct fingerprint length and copy if. */
1322  pfcopy = (!c && ((hexdigits == 40) || (hexdigits == 32)) ? mutt_str_strdup(pf) : NULL);
1323 
1324  if (pfcopy)
1325  {
1326  /* Use pfcopy to strip all spaces from fingerprint and as hint. */
1327  s1 = pfcopy;
1328  s2 = pfcopy;
1329  do
1330  {
1331  *(s1++) = *(s2 = mutt_str_skip_whitespace(s2));
1332  } while (*(s2++));
1333 
1334  phint = pfcopy;
1335  ps = NULL;
1336  pl = NULL;
1337  }
1338  else
1339  {
1340  phint = p;
1341  ps = NULL;
1342  pl = NULL;
1343  if (isid == 1)
1344  {
1345  if (mutt_str_strlen(pf) == 16)
1346  pl = pf; /* long key ID */
1347  else if (mutt_str_strlen(pf) == 8)
1348  ps = pf; /* short key ID */
1349  }
1350  }
1351 
1352  *pphint = phint;
1353  *ppl = pl;
1354  *pps = ps;
1355  return pfcopy;
1356 }
1357 
1365 bool crypt_is_numerical_keyid(const char *s)
1366 {
1367  /* or should we require the "0x"? */
1368  if (strncmp(s, "0x", 2) == 0)
1369  s += 2;
1370  if (strlen(s) % 8)
1371  return false;
1372  while (*s)
1373  if (!strchr("0123456789ABCDEFabcdef", *s++))
1374  return false;
1375 
1376  return true;
1377 }
#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:1102
Convenience wrapper for the gui headers.
bool mutt_matches_ignore(const char *s)
Does the string match the ignore list.
Definition: parse.c:308
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:1276
#define SMIME_OPAQUE
Definition: lib.h:153
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:746
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:81
#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:1301
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
WHERE bool C_Autocrypt
Config: Enables the Autocrypt feature.
Definition: globals.h:200
#define PGP_INLINE
Definition: lib.h:147
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
#define SMIME_SIGN
Definition: lib.h:150
#define WithCrypto
Definition: lib.h:163
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:303
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:698
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:480
#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
Config/command parsing.
Structs that make up an email.
Autocrypt end-to-end encryption.
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:124
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: init.c:1112
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:1128
WHERE char * C_SmimeDefaultKey
Config: Default key for SMIME operations.
Definition: globals.h:164
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:1412
WHERE char * C_CryptProtectedHeadersSubject
Config: Use this as the subject for encrypted emails.
Definition: globals.h:107
Wrapper around crypto functions.
void crypt_pgp_void_passphrase(void)
Wrapper for CryptModuleSpecs::void_passphrase()
Definition: cryptglue.c:192
#define SMIME_ENCRYPT
Definition: lib.h:149
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:125
void crypt_convert_to_7bit(struct Body *a)
Convert an email to 7bit encoding.
Definition: crypt.c:816
bool crypt_smime_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:425
bool mutt_should_hide_protected_subject(struct Email *e)
Should NeoMutt hide the protected subject?
Definition: crypt.c:1088
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:734
bool crypt_is_numerical_keyid(const char *s)
Is this a numerical keyid.
Definition: crypt.c:1365
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:104
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
#define PGP_ENCRYPT
Definition: lib.h:143
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:262
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:483
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:812
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:407
#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:153
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_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:134
#define SEC_ALL_FLAGS
Definition: lib.h:141
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:123
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:692
int crypt_get_keys(struct Email *e, char **keylist, bool oppenc_mode)
Check we have all the keys we need.
Definition: crypt.c:958
bool C_PgpStrictEnc
Config: Encode PGP signed messages with quoted-printable (don&#39;t unset)
Definition: crypt.c:72
int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
Write the message body/part.
Definition: crypt.c:772
#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
bool C_PgpSelfEncrypt
Config: Encrypted messages will also be encrypted to C_PgpDefaultKey too.
Definition: crypt.c:71
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:3003
Convenience wrapper for the config headers.
Prepare and send an email.
Hundreds of global variables to back the user variables.
Email Address Handling.
Do no use Autocrypt.
Definition: lib.h:155
void crypt_smime_set_sender(const char *sender)
Wrapper for CryptModuleSpecs::set_sender()
Definition: cryptglue.c:544
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:132
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:491
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:146
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1349
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:459
Many unsorted constants and some structs.
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:68
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
bool C_PgpRetainableSigs
Config: Create nested multipart/signed or encrypted messages.
Definition: crypt.c:70
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:83
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:36
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:418
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:416
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:341
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
bool C_SmimeSelfEncrypt
Config: Encrypted messages will also be encrypt to C_SmimeDefaultKey too.
Definition: crypt.c:74
#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:138
SecurityFlags mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:565
struct Address * mutt_default_from(void)
Get a default &#39;from&#39; Address.
Definition: send.c:1333
WHERE bool C_CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:268
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:137
Signing/encryption multiplexor.
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:546
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:367
A mailbox.
Definition: mailbox.h:81
#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:171
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:144
struct Body * crypt_pgp_traditional_encryptsign(struct Body *a, int flags, char *keylist)
Wrapper for CryptModuleSpecs::pgp_traditional_encryptsign()
Definition: cryptglue.c:297
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:385
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:520
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:73
WHERE bool OptPgpCheckTrust
(pseudo) used by pgp_select_key()
Definition: options.h:50
SecurityFlags mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:624
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1064
#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/lib.h pgplib...
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:455
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:133
const char * mutt_fqdn(bool may_hide_host)
Get the Fully-Qualified Domain Name.
Definition: sendlib.c:2531
#define SEC_BADSIGN
Email has a bad signature.
Definition: lib.h:128
unsigned int type
content-type primary type
Definition: body.h:65
bool from
Has a line beginning with "From "?
Definition: content.h:43
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:64
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:69
#define SEC_SIGN
Email is signed.
Definition: lib.h:126
#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:579
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:1036
struct Body * crypt_smime_build_smime_entity(struct Body *a, char *certlist)
Wrapper for CryptModuleSpecs::smime_build_smime_entity()
Definition: cryptglue.c:502
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition: address.c:647
char * crypt_pgp_find_keys(struct AddressList *addrlist, bool oppenc_mode)
Wrapper for CryptModuleSpecs::find_keys()
Definition: cryptglue.c:319
void crypt_smime_invoke_import(const char *infile, const char *mailbox)
Wrapper for CryptModuleSpecs::smime_invoke_import()
Definition: cryptglue.c:513
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:552
Duplicate the structure of an entire email.
#define PGP_KEY
Definition: lib.h:146
int n
Definition: acutest.h:492
int mutt_autocrypt_generate_gossip_list(struct Email *e)
Create the gossip list headers.
Definition: autocrypt.c:786
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
struct Email * email
Email in the list.
Definition: email.h:116
#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:654
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:330
WHERE char * C_PgpDefaultKey
Config: Default key to use for PGP operations.
Definition: globals.h:160
#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:522
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:859
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:1550
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
#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:700
#define SEC_GOODSIGN
Email has a valid signature.
Definition: lib.h:127
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
#define SEC_PARTSIGN
Not all parts of the email is signed.
Definition: lib.h:129
Type: &#39;application/*&#39;.
Definition: mime.h:33
bool crypt_pgp_valid_passphrase(void)
Wrapper for CryptModuleSpecs::valid_passphrase()
Definition: cryptglue.c:201
void mutt_param_set(struct ParameterList *pl, const char *attribute, const char *value)
Set a Parameter.
Definition: parameter.c:110
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
int crypt_pgp_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:376